diff --git a/CMakeLists.txt b/CMakeLists.txt
index f7bf32c..e198417 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,190 +1,196 @@
 # Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret
 
 ################################################################################
 #    This file is part of NUISANCE.
 #
 #    NUISANCE is free software: you can redistribute it and/or modify
 #    it under the terms of the GNU General Public License as published by
 #    the Free Software Foundation, either version 3 of the License, or
 #    (at your option) any later version.
 #
 #    NUISANCE is distributed in the hope that it will be useful,
 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 #    GNU General Public License for more details.
 #
 #    You should have received a copy of the GNU General Public License
 #    along with NUISANCE.  If not, see <http://www.gnu.org/licenses/>.
 ################################################################################
 cmake_minimum_required (VERSION 2.6 FATAL_ERROR)
 
 project(NUISANCE)
 
 include(ExternalProject)
 
 enable_language(Fortran)
 
 set (NUISANCE_VERSION_MAJOR 2)
 set (NUISANCE_VERSION_MINOR 7)
 set (NUISANCE_VERSION_REVISION 0)
 
 set (NUISANCE_VERSION_STRING "v${NUISANCE_VERSION_MAJOR}r${NUISANCE_VERSION_MINOR}")
 if(${NUISANCE_VERSION_REVISION} STRGREATER "0")
   set (NUISANCE_VERSION_STRING "${NUISANCE_VERSION_STRING}p${NUISANCE_VERSION_REVISION}")
 endif()
 
 #Set this to TRUE to enable build debugging messages
 set(BUILD_DEBUG_MSGS TRUE)
 include(${CMAKE_SOURCE_DIR}/cmake/cmessage.cmake)
 
 include(${CMAKE_SOURCE_DIR}/cmake/cacheVariables.cmake)
 
 cmessage(STATUS "CMAKE_INSTALL_PREFIX: \"${CMAKE_INSTALL_PREFIX}\"")
 cmessage(STATUS "CMAKE_BUILD_TYPE: \"${CMAKE_BUILD_TYPE}\"")
 
 ################################################################################
 #                            Check Dependencies
 ################################################################################
 
 ##################################  ROOT  ######################################
 include(${CMAKE_SOURCE_DIR}/cmake/ROOTSetup.cmake)
 
 #################################  HEPMC  ######################################
 include(${CMAKE_SOURCE_DIR}/cmake/HepMC.cmake)
 
 ############################  Reweight Engines  ################################
 include(${CMAKE_SOURCE_DIR}/cmake/ReweightEnginesSetup.cmake)
 
 ############################  Other Generators  ################################
 
 include(${CMAKE_SOURCE_DIR}/cmake/GiBUUSetup.cmake)
 
 if(USE_NUANCE)
   LIST(APPEND EXTRA_CXX_FLAGS -D__NUANCE_ENABLED__)
 endif()
 
 #################################  Pythia6/8  ####################################
 include(${CMAKE_SOURCE_DIR}/cmake/pythia6Setup.cmake)
 include(${CMAKE_SOURCE_DIR}/cmake/pythia8Setup.cmake)
 
 ################################# gperftools ###################################
 
 include(${CMAKE_SOURCE_DIR}/cmake/gperfSetup.cmake)
 
 if(NOT NOTEST)
   enable_testing()
 endif()
 
 SET(GENERATOR_SUPPORT)
 
 foreach(gen NEUT;NuWro;GENIE;GiBUU;NUANCE)
   if(USE_${gen})
     SET(GENERATOR_SUPPORT "${GENERATOR_SUPPORT}${gen} ")
   endif()
 endforeach(gen)
 
 cmessage(STATUS "Generator Input Support: ${GENERATOR_SUPPORT}")
 
 set(MINCODE
   Routines
   FCN)
 
 set(CORE
   MCStudies
   Genie
   FitBase
+  Config
+  Logger
   InputHandler
   Splines
-  Reweight
+  Reweight	
   Utils
+  Statistical
   #Devel
   Smearceptance
   )
 
 LIST(APPEND ALLEXPERIMENTS
   ANL
   ArgoNeuT
   BEBC
   BNL
   Electron
   FNAL
   GGM
   K2K
   MINERvA
   MiniBooNE
   SciBooNE
   T2K)
 
 foreach(exp ${ALLEXPERIMENTS})
   if(NOT NO_${exp})
     LIST(APPEND EXPERIMENTS_TO_BUILD ${exp})
   else()
     LIST(REVERSE EXTRA_CXX_FLAGS)
     LIST(APPEND EXTRA_CXX_FLAGS -D__NO_${exp}__)
     LIST(REVERSE EXTRA_CXX_FLAGS)
   endif()
 endforeach()
 
 ################################## COMPILER ####################################
 include(${CMAKE_SOURCE_DIR}/cmake/c++CompilerSetup.cmake)
 
 ################################### doxygen ###################################
 
 include(${CMAKE_SOURCE_DIR}/cmake/docsSetup.cmake)
 
 ################################################################################
 
 
 set(MINIMUM_INCLUDE_DIRECTORIES)
 LIST(APPEND MINIMUM_INCLUDE_DIRECTORIES
   ${RWENGINE_INCLUDE_DIRECTORIES}
   ${CMAKE_SOURCE_DIR}/src/FitBase
   ${CMAKE_SOURCE_DIR}/src/Reweight
   ${CMAKE_SOURCE_DIR}/src/InputHandler
+  ${CMAKE_SOURCE_DIR}/src/Config
+  ${CMAKE_SOURCE_DIR}/src/Logger
+  ${CMAKE_SOURCE_DIR}/src/Statistical
   ${CMAKE_SOURCE_DIR}/src/Splines
   ${CMAKE_SOURCE_DIR}/src/Utils
   ${CMAKE_SOURCE_DIR}/src/Genie)
 
 cmessage(DEBUG "Base include directories: ${MINIMUM_INCLUDE_DIRECTORIES}")
 
 set(EXP_INCLUDE_DIRECTORIES)
 
 foreach(edir ${EXPERIMENTS_TO_BUILD})
   LIST(APPEND EXP_INCLUDE_DIRECTORIES ${CMAKE_SOURCE_DIR}/src/${edir})
 endforeach()
 cmessage(DEBUG "Included experiments: ${EXP_INCLUDE_DIRECTORIES}")
 
 foreach(mdir ${MINCODE})
   cmessage (DEBUG "Configuring directory: src/${mdir}")
   add_subdirectory(src/${mdir})
 endforeach()
 
 foreach(edir ${EXPERIMENTS_TO_BUILD})
   cmessage (DEBUG "Configuring directory: src/${edir}")
   add_subdirectory(src/${edir})
 endforeach()
 
 foreach(cdir ${CORE})
   cmessage (DEBUG "Configuring directory: src/${cdir}")
   add_subdirectory(src/${cdir})
 endforeach()
 
 cmessage(DEBUG "Module targets: ${MODULETargets}")
 
 add_subdirectory(app)
 add_subdirectory(src/Tests)
 
 configure_file(cmake/setup.sh.in
   "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/setup.sh" @ONLY)
 install(FILES
   "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/setup.sh" DESTINATION
   ${CMAKE_INSTALL_PREFIX})
 
 
 install(PROGRAMS
   "${PROJECT_SOURCE_DIR}/scripts/nuiscardgen" DESTINATION
   bin)
 
 install(PROGRAMS
   "${PROJECT_SOURCE_DIR}/scripts/nuissamples" DESTINATION
   bin)
diff --git a/VERSION b/VERSION
index f3677eb..8f6d685 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-Fitter Version Tag: v2r7
\ No newline at end of file
+Fitter Version Tag: v2r8
\ No newline at end of file
diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt
index c260ba6..1d488e3 100644
--- a/app/CMakeLists.txt
+++ b/app/CMakeLists.txt
@@ -1,192 +1,217 @@
 # Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret
 
 ################################################################################
 #    This file is part of NUISANCE.
 #
 #    NUISANCE is free software: you can redistribute it and/or modify
 #    it under the terms of the GNU General Public License as published by
 #    the Free Software Foundation, either version 3 of the License, or
 #    (at your option) any later version.
 #
 #    NUISANCE is distributed in the hope that it will be useful,
 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 #    GNU General Public License for more details.
 #
 #    You should have received a copy of the GNU General Public License
 #    along with NUISANCE.  If not, see <http://www.gnu.org/licenses/>.
 ################################################################################
 
 set(TARGETS_TO_BUILD)
 
 if(USE_MINIMIZER)
   add_executable(nuismin nuismin.cxx)
   set(TARGETS_TO_BUILD ${TARGETS_TO_BUILD};nuismin)
   target_link_libraries(nuismin ${MODULETargets})
   target_link_libraries(nuismin ${CMAKE_DEPENDLIB_FLAGS})
   # target_link_libraries(nuismin ${ROOT_LIBS})
   if(NOT "${CMAKE_LINK_FLAGS}" STREQUAL "")
     set_target_properties(nuismin PROPERTIES LINK_FLAGS ${CMAKE_LINK_FLAGS})
   endif()
 
   add_executable(nuissplines nuissplines.cxx)
   set(TARGETS_TO_BUILD ${TARGETS_TO_BUILD};nuissplines)
   target_link_libraries(nuissplines ${MODULETargets})
   target_link_libraries(nuissplines ${CMAKE_DEPENDLIB_FLAGS})
   # target_link_libraries(nuissplines ${ROOT_LIBS})
   if(NOT "${CMAKE_LINK_FLAGS}" STREQUAL "")
     set_target_properties(nuissplines PROPERTIES LINK_FLAGS ${CMAKE_LINK_FLAGS})
   endif()
 
 endif()
 
 include_directories(${RWENGINE_INCLUDE_DIRECTORIES})
 include_directories(${CMAKE_SOURCE_DIR}/src/Routines)
 include_directories(${CMAKE_SOURCE_DIR}/src/InputHandler)
 include_directories(${CMAKE_SOURCE_DIR}/src/Genie)
 include_directories(${CMAKE_SOURCE_DIR}/src/FitBase)
+include_directories(${CMAKE_SOURCE_DIR}/src/Statistical)
 include_directories(${CMAKE_SOURCE_DIR}/src/Utils)
+include_directories(${CMAKE_SOURCE_DIR}/src/Config)
+include_directories(${CMAKE_SOURCE_DIR}/src/Logger)
 include_directories(${CMAKE_SOURCE_DIR}/src/Splines)
 include_directories(${CMAKE_SOURCE_DIR}/src/Reweight)
 include_directories(${CMAKE_SOURCE_DIR}/src/FCN)
 include_directories(${CMAKE_SOURCE_DIR}/src/MCStudies)
 include_directories(${CMAKE_SOURCE_DIR}/src/Smearceptance)
 include_directories(${EXP_INCLUDE_DIRECTORIES})
 
 if (USE_NuWro AND NOT NUWRO_BUILT_FROM_FILE)
   add_executable(nuwro_nuisance nuwro_NUISANCE.cxx)
   set(TARGETS_TO_BUILD ${TARGETS_TO_BUILD};nuwro_nuisance)
   target_link_libraries(nuwro_nuisance ${MODULETargets})
   target_link_libraries(nuwro_nuisance ${CMAKE_DEPENDLIB_FLAGS})
   # target_link_libraries(nuwro_nuisance ${ROOT_LIBS})
   include_directories(${CMAKE_SOURCE_DIR}/src/FitBase)
   if(NOT "${CMAKE_LINK_FLAGS}" STREQUAL "")
     set_target_properties(nuwro_nuisance PROPERTIES LINK_FLAGS ${CMAKE_LINK_FLAGS})
   endif()
 endif()
 
 if (USE_NEUT)
   add_executable(neut_nuisance neut_NUISANCE.cxx)
   set(TARGETS_TO_BUILD ${TARGETS_TO_BUILD};neut_nuisance)
   target_link_libraries(neut_nuisance ${MODULETargets})
   target_link_libraries(neut_nuisance ${CMAKE_DEPENDLIB_FLAGS})
   target_link_libraries(neut_nuisance ${ROOT_LIBS})
   include_directories(${CMAKE_SOURCE_DIR}/src/FitBase)
   if(NOT "${CMAKE_LINK_FLAGS}" STREQUAL "")
     set_target_properties(neut_nuisance PROPERTIES LINK_FLAGS ${CMAKE_LINK_FLAGS})
   endif()
 endif()
 
 if (BUILD_GEVGEN)
   add_executable(gevgen_nuisance gEvGen_NUISANCE.cxx)
   set(TARGETS_TO_BUILD ${TARGETS_TO_BUILD};gevgen_nuisance)
   target_link_libraries(gevgen_nuisance ${MODULETargets})
   target_link_libraries(gevgen_nuisance ${CMAKE_DEPENDLIB_FLAGS})
   # target_link_libraries(gevgen_nuisance ${ROOT_LIBS})
   include_directories(${CMAKE_SOURCE_DIR}/src/FitBase)
   include_directories(${GENIE_INCLUDES}/Apps)
   include_directories(${GENIE_INCLUDES}/FluxDrivers)
   include_directories(${GENIE_INCLUDES}/EVGDrivers)
   if(NOT "${CMAKE_LINK_FLAGS}" STREQUAL "")
     set_target_properties(gevgen_nuisance PROPERTIES LINK_FLAGS ${CMAKE_LINK_FLAGS})
   endif()
 
 
   add_executable(gevgen_nuisance_mixed gEvGen_NUISANCE_MIXED.cxx)
   set(TARGETS_TO_BUILD ${TARGETS_TO_BUILD};gevgen_nuisance_mixed)
   target_link_libraries(gevgen_nuisance_mixed ${MODULETargets})
   target_link_libraries(gevgen_nuisance_mixed ${CMAKE_DEPENDLIB_FLAGS})
   # target_link_libraries(gevgen_nuisance_mixed ${ROOT_LIBS})
   include_directories(${CMAKE_SOURCE_DIR}/src/FitBase)
   include_directories(${GENIE_INCLUDES}/Apps)
   include_directories(${GENIE_INCLUDES}/FluxDrivers)
   include_directories(${GENIE_INCLUDES}/EVGDrivers)
   if(NOT "${CMAKE_LINK_FLAGS}" STREQUAL "")
     set_target_properties(gevgen_nuisance_mixed PROPERTIES LINK_FLAGS ${CMAKE_LINK_FLAGS})
   endif()
 endif()
 
 if (USE_GiBUU)
   add_executable(DumpGiBUUEvents DumpGiBUUEvents.cxx)
   set(TARGETS_TO_BUILD ${TARGETS_TO_BUILD};DumpGiBUUEvents)
   target_link_libraries(DumpGiBUUEvents ${MODULETargets})
   target_link_libraries(DumpGiBUUEvents ${CMAKE_DEPENDLIB_FLAGS})
   # target_link_libraries(DumpGiBUUEvents ${ROOT_LIBS})
   include_directories(${CMAKE_SOURCE_DIR}/src/FitBase)
   if(NOT "${CMAKE_LINK_FLAGS}" STREQUAL "")
     set_target_properties(DumpGiBUUEvents PROPERTIES LINK_FLAGS ${CMAKE_LINK_FLAGS})
   endif()
 endif()
 
 add_executable(nuiscomp nuiscomp.cxx)
 set(TARGETS_TO_BUILD ${TARGETS_TO_BUILD};nuiscomp)
 target_link_libraries(nuiscomp ${MODULETargets})
 target_link_libraries(nuiscomp ${CMAKE_DEPENDLIB_FLAGS})
 # target_link_libraries(nuiscomp ${ROOT_LIBS})
 if(NOT "${CMAKE_LINK_FLAGS}" STREQUAL "")
   set_target_properties(nuiscomp PROPERTIES LINK_FLAGS ${CMAKE_LINK_FLAGS})
 endif()
 
 add_executable(nuisflat nuisflat.cxx)
 set(TARGETS_TO_BUILD ${TARGETS_TO_BUILD};nuisflat)
 target_link_libraries(nuisflat ${MODULETargets})
 target_link_libraries(nuisflat ${CMAKE_DEPENDLIB_FLAGS})
 # target_link_libraries(nuisflat ${ROOT_LIBS})
 if(NOT "${CMAKE_LINK_FLAGS}" STREQUAL "")
   set_target_properties(nuisflat PROPERTIES LINK_FLAGS ${CMAKE_LINK_FLAGS})
 endif()
 
 add_executable(nuissmear nuissmear.cxx)
 set(TARGETS_TO_BUILD ${TARGETS_TO_BUILD};nuissmear)
 target_link_libraries(nuissmear ${MODULETargets})
 target_link_libraries(nuissmear ${CMAKE_DEPENDLIB_FLAGS})
 # target_link_libraries(nuissmear ${ROOT_LIBS})
 if(NOT "${CMAKE_LINK_FLAGS}" STREQUAL "")
   set_target_properties(nuissmear PROPERTIES LINK_FLAGS ${CMAKE_LINK_FLAGS})
 endif()
 
 add_executable(nuissyst nuissyst.cxx)
 set(TARGETS_TO_BUILD ${TARGETS_TO_BUILD};nuissyst)
 target_link_libraries(nuissyst ${MODULETargets})
 target_link_libraries(nuissyst ${CMAKE_DEPENDLIB_FLAGS})
 # target_link_libraries(nuissyst ${ROOT_LIBS})
 if(NOT "${CMAKE_LINK_FLAGS}" STREQUAL "")
   set_target_properties(nuissyst PROPERTIES LINK_FLAGS ${CMAKE_LINK_FLAGS})
 endif()
 
+add_executable(nuisbayes nuisbayes.cxx)
+set(TARGETS_TO_BUILD ${TARGETS_TO_BUILD};nuisbayes)
+target_link_libraries(nuisbayes ${MODULETargets})
+target_link_libraries(nuisbayes ${CMAKE_DEPENDLIB_FLAGS})
+# target_link_libraries(nuisbayes ${ROOT_LIBS})
+if(NOT "${CMAKE_LINK_FLAGS}" STREQUAL "")
+  set_target_properties(nuisbayes PROPERTIES LINK_FLAGS ${CMAKE_LINK_FLAGS})
+endif()
+
 if(USE_GENIE)
   add_executable(PrepareGENIE PrepareGENIE.cxx)
   set(TARGETS_TO_BUILD ${TARGETS_TO_BUILD};PrepareGENIE)
   target_link_libraries(PrepareGENIE ${MODULETargets})
   target_link_libraries(PrepareGENIE ${CMAKE_DEPENDLIB_FLAGS})
   # target_link_libraries(PrepareGENIE ${ROOT_LIBS})
   if(NOT "${CMAKE_LINK_FLAGS}" STREQUAL "")
      set_target_properties(PrepareGENIE PROPERTIES LINK_FLAGS ${CMAKE_LINK_FLAGS})
   endif()
 endif()
 
 if(USE_NEUT)
   add_executable(PrepareNEUT PrepareNEUT.cxx)
   set(TARGETS_TO_BUILD ${TARGETS_TO_BUILD};PrepareNEUT)
   target_link_libraries(PrepareNEUT ${MODULETargets})
   target_link_libraries(PrepareNEUT ${CMAKE_DEPENDLIB_FLAGS})
   # target_link_libraries(PrepareNEUT ${ROOT_LIBS})
   if(NOT "${CMAKE_LINK_FLAGS}" STREQUAL "")
      set_target_properties(PrepareNEUT PROPERTIES LINK_FLAGS ${CMAKE_LINK_FLAGS})
   endif()
 endif()
 
 # PREPARE NUWRO
 # Commented out for the time being until it is finished..
 if(USE_NuWro)
   add_executable(PrepareNuwro PrepareNuwroEvents.cxx)
   set(TARGETS_TO_BUILD ${TARGETS_TO_BUILD};PrepareNuwro)
   target_link_libraries(PrepareNuwro ${MODULETargets})
   target_link_libraries(PrepareNuwro ${CMAKE_DEPENDLIB_FLAGS})
   # target_link_libraries(PrepareNuwro ${ROOT_LIBS})
   if(NOT "${CMAKE_LINK_FLAGS}" STREQUAL "")
     set_target_properties(PrepareNuwro PROPERTIES LINK_FLAGS ${CMAKE_LINK_FLAGS})
   endif()
 endif()
 
 install(TARGETS ${TARGETS_TO_BUILD} DESTINATION bin)
+
+#add_executable(DumpROOTClassesFromVector DumpROOTClassesFromVector.cxx)
+#  #Strip out -lNuWro_event1
+#  string(REPLACE "-lNuWro_event1" "" NWEVSTRIPPED_CDF ${CMAKE_DEPENDLIB_FLAGS})
+#  cmessage(DEBUG "Attempted to strip out nuwro library: \"${CMAKE_DEPENDLIB_FLAGS}\" -> \"${NWEVSTRIPPED_CDF}\"")
+#  add_executable(PrepareNEUT PrepareNEUT.cxx)
+#  target_link_libraries(DumpROOTClassesFromVector ${MODULETargets})
+#  target_link_libraries(DumpROOTClassesFromVector ${NWEVSTRIPPED_CDF})
+#  if(NOT CMAKE_LINK_FLAGS STREQUAL "")
+#    set_target_properties(DumpROOTClassesFromVector PROPERTIES LINK_FLAGS ${CMAKE_LINK_FLAGS})
+#  endif()
+#install(TARGETS DumpROOTClassesFromVector DESTINATION bin)
+
diff --git a/src/Utils/DumpROOTClassesFromVector.cxx b/app/DumpROOTClassesFromVector.cxx
similarity index 100%
rename from src/Utils/DumpROOTClassesFromVector.cxx
rename to app/DumpROOTClassesFromVector.cxx
diff --git a/app/PrepareNEUT.cxx b/app/PrepareNEUT.cxx
index a4c31ed..3b37e40 100644
--- a/app/PrepareNEUT.cxx
+++ b/app/PrepareNEUT.cxx
@@ -1,237 +1,238 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include "TFile.h"
 #include "TH1D.h"
 #include "TTree.h"
 #include "PlotUtils.h"
+#include "StatUtils.h"
 #include "FitLogger.h"
 
 // If you don't have NEUT enabled, you shouldn't compile this...
 #include "neutpart.h"
 #include "neutvect.h"
 
 
 std::string fInputFiles = "";
 std::string fOutputFile = "";
 std::string fFluxFile   = "";
 bool fFluxInGeV = false;
 
 void PrintOptions();
 void ParseOptions(int argc, char* argv[]);
 void CreateRateHistogram(std::string inputList, std::string flux, std::string output);
 
 //*******************************
 int main(int argc, char* argv[]){
 //*******************************
 
   LOG_VERB(FitPar::Config().GetParI("VERBOSITY"));
   ERR_VERB(FitPar::Config().GetParI("ERROR"));
 
   ParseOptions(argc, argv);
   LOG(FIT) << "Running PrepareNEUT" << std::endl;
   CreateRateHistogram(fInputFiles, fFluxFile, fOutputFile);
 };
 
 //*******************************
 void CreateRateHistogram(std::string inputList, std::string flux, std::string output){
 //*******************************
 
   // Need to allow for more than one file... will do soon
   TChain* tn = new TChain("neuttree");
 
   std::vector<std::string> inputs = GeneralUtils::ParseToStr(inputList,",");
   for (std::vector<std::string>::iterator it = inputs.begin();
        it != inputs.end(); ++it){
     LOG(FIT) << "Adding " << *it << " to the output" << std::endl;
     tn->AddFile((*it).c_str());
   }
 
   if (inputs.size() > 1 && output.empty()){
     ERR(FTL) << "You must provide a new output file name if you want to have more than 1 input file!" << std::endl;
     throw;
   } 
 
   int nevts = tn->GetEntries();
 
   if (!nevts){
     ERR(FTL) << "Either the input file is not from NEUT, or it's empty..." <<std::endl;
     throw;
   }
 
   NeutVect *fNeutVect = NULL;
   tn->SetBranchAddress("vectorbranch", &fNeutVect);
 
   // Get Flux Hist
   std::vector<std::string> fluxvect = GeneralUtils::ParseToStr(flux,",");
   TH1D* fluxHist = NULL;
   if (fluxvect.size() > 1){
     TFile* fluxfile = new TFile(fluxvect[0].c_str(),"READ");
     fluxHist = (TH1D*) fluxfile->Get(fluxvect[1].c_str());
     fluxHist->SetDirectory(0);
   } else {
     ERR(FTL) << "NO FLUX SPECIFIED" << std::endl;
     throw;
   }
 
   // Decide what type of flux was given
   if (fFluxInGeV) LOG(FIT) << "Assuming flux histogram is in GeV" << std::endl;
   else LOG(FIT) << "Assuming flux histogram is in MeV" << std::endl;
 
   // Make Event Hist
   TH1D* xsecHist = (TH1D*)fluxHist->Clone();
   xsecHist->Reset();
 
   // Make a total cross section hist for shits and giggles
   TH1D* entryHist = (TH1D*) xsecHist->Clone();
 
   for (int i = 0; i < nevts; ++i){
     tn->GetEntry(i);
     NeutPart* part = fNeutVect->PartInfo(0);    
     double E = part->fP.E();
     double xsec = fNeutVect->Totcrs;
 
     // Unit conversion
     if (fFluxInGeV) E*=1E-3;
     
     xsecHist ->Fill(E, xsec);
     entryHist->Fill(E);
 
     if (i % (nevts/20) == 0){
       LOG(FIT) << "Processed " << i <<  "/" << nevts << " NEUT events." << std::endl;
     }
   }
   LOG(FIT) << "Processed all events" << std::endl;
   
   xsecHist ->Divide(entryHist);
 
   // This will be the evtrt histogram
   TH1D* evtHist = NULL;
   
   // If the integral of xsecHist is 0 the input file used a really old version of NEUT without Totcrs
   if (!xsecHist->Integral(0, -1)){
     ERR(WRN) << "Old NEUT input file: events will not be correctly normalized" << std::endl;
     evtHist = (TH1D*)entryHist->Clone();
     
     if (evtHist->Integral() != 0)
       evtHist ->Scale(fluxHist->Integral()/float(evtHist->Integral()));
   } else {
     evtHist = (TH1D*)xsecHist->Clone();
     evtHist ->Multiply(fluxHist);
   }
 
   // Check whether the overflow is empty. If not, advise that either the wrong flux histogram or units were used...
   // If the events were generated with a limited range of the flux histogram, this may be benign
   if (evtHist->Integral(0, -1) != evtHist->Integral() || evtHist->Integral(0, -1) == 0){
     ERR(WRN) << "The input file and flux histogram provided do not match... " << std::endl;
     ERR(WRN) << "Are the units correct? Did you provide the correct flux file?" << std::endl;
     ERR(WRN) << "Use output with caution..." << std::endl;
   }
 
   // Pick where the output should go
   TFile *outFile = NULL;
   if (!output.empty()){
     LOG(FIT) << "Saving histograms in " << output << std::endl;
     outFile = new TFile(output.c_str(), "RECREATE");
   } else {
     LOG(FIT) << "Saving histograms in " << inputs[0] << std::endl;
     outFile = new TFile(inputs[0].c_str(), "UPDATE");
   }
   outFile->cd();
 
   std::string xsec_name = "xsec_PrepareNeut";
   std::string flux_name = "flux_PrepareNeut";
   std::string rate_name = "evtrt_PrepareNeut";
 
   if (output.empty()){
     // Check whether we should overwrite existing histograms
     std::string input_xsec = PlotUtils::GetObjectWithName(outFile, "xsec");
     std::string input_flux = PlotUtils::GetObjectWithName(outFile, "flux");
     std::string input_rate = PlotUtils::GetObjectWithName(outFile, "evtrt");
 
     if (!input_xsec.empty()) {
       LOG(FIT) << "Updating histogram: " << input_xsec << std::endl;
       xsec_name = input_xsec;
     }
     if (!input_flux.empty()) {
       LOG(FIT) << "Updating histogram: " << input_flux << std::endl;
       flux_name = input_flux;
     }
     if (!input_rate.empty()) {
       LOG(FIT) << "Updating histogram: " << input_rate << std::endl;
       rate_name = input_rate;
     }
 
   } else {
     LOG(FIT) << "Cloning neuttree into output file." << std::endl;
     StopTalking();
     TTree* newtree = (TTree*)tn->CloneTree(-1, "fast");
     StartTalking();
     newtree->Write();
   }
 
   xsecHist->Write(xsec_name.c_str(), TObject::kOverwrite);
   fluxHist->Write(flux_name.c_str(), TObject::kOverwrite);
   evtHist ->Write(rate_name.c_str(), TObject::kOverwrite);
   outFile ->Close();
 
   return;
 }
 
 
 void PrintOptions(){
 
   std::cout << "PrepareNEUT NUISANCE app. "  << std::endl
      	    << "Produces or recalculates evtrt and flux histograms necessary for NUISANCE normalization." << std::endl;
   std::cout << "PrepareNEUT: " << std::endl;
   std::cout << "    [-h,-help,--h,--help]" << std::endl;
   std::cout << "    -i inputfile1.root,inputfile2.root,inputfile3.root,..." << std::endl;
   std::cout << "          Takes any number of files, but assumes all are produced with a single flux" << std::endl;
   std::cout << "    -f flux_root_file.root,flux_hist_name" << std::endl;
   std::cout << "          Path to root file containing the flux histogram used when generating the NEUT files" << std::endl;
   std::cout << "    [-o outputfile.root] " << std::endl;
   std::cout << "          If an output file is not given, the input file will be used" << std::endl;
   std::cout << "          If more than one input file is given, an output file must be given" << std::endl;
   std::cout << "    [-G]" << std::endl;
   std::cout << "          Flux is assumed to be in MeV. This switch indicates the input flux is in GeV" << std::endl << std::endl;
 
 }
 
 void ParseOptions(int argc, char* argv[]){
   bool flagopt = false;
   
   // If No Arguments print commands
   for (int i = 1; i< argc; ++i){
     if (!std::strcmp(argv[i], "-h"))   { flagopt  = true; break; }
     else if (!std::strcmp(argv[i], "-G")) { fFluxInGeV  = true; }
     if (i+1 != argc){
       
       // Cardfile
       if (!std::strcmp(argv[i], "-h"))      { flagopt = true; break; }
       else if (!std::strcmp(argv[i], "-i")) { fInputFiles = argv[i+1]; ++i; }
       else if (!std::strcmp(argv[i], "-o")) { fOutputFile = argv[i+1]; ++i; }
       else if (!std::strcmp(argv[i], "-f")) { fFluxFile   = argv[i+1]; ++i; }
       else {
 	ERR(FTL) << "ERROR: unknown command line option given! - '"
 		 <<argv[i]<<" "<<argv[i+1]<<"'"<< std::endl;
 	PrintOptions();
 	break;
       }
     }
   }
   if (fInputFiles == "" && !flagopt){
     ERR(FTL) << "No input file(s) specified!" << std::endl;
     flagopt = true;
   }
   
   if (fFluxFile == "" && !flagopt){
     ERR(FTL) << "No flux input specified!" << std::endl;
     flagopt = true;
   }
   
   if (argc < 1 || flagopt){
     PrintOptions();
     exit(-1);
   }
   
   return;
 }
diff --git a/app/nuisbayes.cxx b/app/nuisbayes.cxx
new file mode 100644
index 0000000..44a3df0
--- /dev/null
+++ b/app/nuisbayes.cxx
@@ -0,0 +1,68 @@
+// Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret
+
+/*******************************************************************************
+*    This file is part of NUISANCE.
+*
+*    NUISANCE is free software: you can redistribute it and/or modify
+*    it under the terms of the GNU General Public License as published by
+*    the Free Software Foundation, either version 3 of the License, or
+*    (at your option) any later version.
+*
+*    NUISANCE is distributed in the hope that it will be useful,
+*    but WITHOUT ANY WARRANTY; without even the implied warranty of
+*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*    GNU General Public License for more details.
+*
+*    You should have received a copy of the GNU General Public License
+*    along with NUISANCE.  If not, see <http://www.gnu.org/licenses/>.
+*******************************************************************************/
+
+// Author: Patrick Stowell     09/2016
+/*
+  Usage: ./nuissyst -c card file -o output file, where the results of the throws are stored
+   where:   
+*/
+
+#include "BayesianRoutines.h"
+
+//*******************************
+void printInputCommands(){
+//*******************************
+  
+  exit(-1);
+
+};
+
+//*******************************
+int main(int argc, char* argv[]){ 
+//*******************************
+
+  // Program status;
+  int status = 0;
+  
+  // If No Arguments print commands
+  if (argc == 1) printInputCommands();
+    
+  for (int i = 1; i< argc; ++i){
+    // Cardfile
+    if (!std::strcmp(argv[i], "-h")) printInputCommands();
+    else break;
+  }
+  
+  // Read input arguments such as card file, parameter arguments, and fit routines
+  LOG(FIT)<<"Starting nuissyst"<<std::endl;
+
+  // Make systematic class and run fit
+  BayesianRoutines* min = new BayesianRoutines(argc, argv);
+  min->Run();
+  
+  
+  // Show Final Status
+  LOG(FIT)<<"-------------------------------------"<<std::endl;
+  LOG(FIT)<<"FINISHED" << std::endl;
+  LOG(FIT)<<"-------------------------------------"<<std::endl;
+  return status;
+}
+
+
+
diff --git a/app/nuisflat.cxx b/app/nuisflat.cxx
index d0772bf..c5c0f1b 100644
--- a/app/nuisflat.cxx
+++ b/app/nuisflat.cxx
@@ -1,177 +1,177 @@
 // Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret
 
 /*******************************************************************************
 *    This file is part of NUISANCE.
 *
 *    NUISANCE is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    NUISANCE is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with NUISANCE.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
 #include "ComparisonRoutines.h"
 #include "InputUtils.h"
 #include "MeasurementBase.h"
 #include "GenericFlux_Tester.h"
 #include "Smearceptance_Tester.h"
 
 // Global Arguments
 std::string gOptInputFile = "";
 std::string gOptFormat = "";
 std::string gOptOutputFile = "";
 std::string gOptType = "DEFAULT";
 std::string gOptNumberEvents = "NULL";
 std::string gOptCardInput = "";
 std::string gOptOptions = "";
 
 //*******************************
 void PrintSyntax() {
   //*******************************
 
   std::cout << "nuisflat -i input -f format [-o outfile] [-n nevents] [-t "
                "options] [-q con=val] \n";
   std::cout
       << "\n Arguments : "
       << "\n\t -i input   : Path to input vector of events to flatten"
       << "\n\t"
       << "\n\t              This should be given in the same format a normal "
          "input file"
       << "\n\t              is given to NUISANCE. {e.g. NUWRO:eventsout.root}."
       << "\n\t"
       << "\n\t -f format  : FlatTree format to output:"
       << "\n\t\t GenericFlux   : Standard event summary format."
       << "\n\t "
       << "\n\t[-c crd.xml]: Input card file to override configs or set dial values."
       << "\n\t "
       << "\n\t[-o outfile]: Optional output file path. "
       << "\n\t "
       << "\n\t              If none given, input.format.root is chosen."
       << "\n\t"
       << "\n\t[-n nevents]: Optional choice of Nevents to run over. Default is "
          "all."
       << "\n\t"
       << "\n\t[-t options]: Pass OPTION to the FlatTree sample. "
       << "\n\t              Similar to type field in comparison xml configs."
       << "\n\t"
       << "\n\t[-q con=val]: Configuration overrides." << std::endl;
 
   exit(-1);
 };
 
 //____________________________________________________________________________
 void GetCommandLineArgs(int argc, char** argv) {
   // Check for -h flag.
   for (int i = 0; i < argc; i++) {
     if ((!std::string(argv[i]).compare("-h")) ||
         (!std::string(argv[i]).compare("-?")) ||
         (!std::string(argv[i]).compare("--help")))
       PrintSyntax();
   }
 
   // Format is nuwro -r run_number -n n events
   std::vector<std::string> args = GeneralUtils::LoadCharToVectStr(argc, argv);
 
   // Parse input file
   ParserUtils::ParseArgument(args, "-i", gOptInputFile, false);
   if (gOptInputFile == "") {
     THROW("Need to provide a valid input file to nuisflat using -i flag!");
   } else {
     LOG(FIT) << "Reading Input File = " << gOptInputFile << std::endl;
   }
 
   // Get Output Format
   ParserUtils::ParseArgument(args, "-f", gOptFormat, false);
   if (gOptFormat == "") {
     THROW("Need to provide a valid output format to nuisflat!");
   } else {
     LOG(FIT) << "Saving flattree in format = " << gOptFormat << std::endl;
   }
 
   // Get Output File
   ParserUtils::ParseArgument(args, "-o", gOptOutputFile, false);
   if (gOptOutputFile == "") {
     gOptOutputFile = gOptInputFile + "." + gOptFormat + ".root";
     LOG(FIT) << "No output file given so saving nuisflat output to:"
              << gOptOutputFile << std::endl;
   } else {
     LOG(FIT) << "Saving nuisflat output to " << gOptOutputFile << std::endl;
   }
 
   // Get N Events and Configs
   nuisconfig configuration = Config::Get();
 
   ParserUtils::ParseArgument(args, "-n", gOptNumberEvents, false);
   if (gOptNumberEvents.compare("NULL")) {
     configuration.OverrideConfig("MAXEVENTS=" + gOptNumberEvents);
   }
 
   std::vector<std::string> configargs;
   ParserUtils::ParseArgument(args, "-q", configargs);
   for (size_t i = 0; i < configargs.size(); i++) {
     configuration.OverrideConfig(configargs[i]);
   }
 
   ParserUtils::ParseArgument(args, "-c", gOptCardInput, false);
   if (gOptCardInput != "") {
     QLOG(FIT, "Reading cardfile: " << gOptCardInput);
-    configuration.LoadConfig(gOptCardInput, "");
+    configuration.LoadSettings(gOptCardInput, "");
   }
 
   ParserUtils::ParseArgument(args, "-t", gOptOptions, false);
   if (gOptOptions != "") {
     QLOG(FIT, "Read options: \"" << gOptOptions << "\'");
   }
   return;
 }
 
 //*******************************
 int main(int argc, char* argv[]) {
   //*******************************
 
   // Parse
   GetCommandLineArgs(argc, argv);
 
   // Make output file
   TFile* f = new TFile(gOptOutputFile.c_str(), "RECREATE");
   if (f->IsZombie()) {
     THROW("Cannot create output file!");
   }
   f->cd();
   FitPar::Config().out = f;
 
   // Create a new measurementbase class depending on the Format
   MeasurementBase* flattreecreator = NULL;
 
   // Make a new sample key for the format of interest.
   nuiskey samplekey = Config::CreateKey("sample");
   if (!gOptFormat.compare("GenericFlux")) {
-    samplekey.AddS("name", "FlatTree");
-    samplekey.AddS("input", gOptInputFile);
-    samplekey.AddS("type", gOptType);
+    samplekey.Set("name", "FlatTree");
+    samplekey.Set("input", gOptInputFile);
+    samplekey.Set("type", gOptType);
     flattreecreator = new GenericFlux_Tester("FlatTree", gOptInputFile,
                                              FitBase::GetRW(), gOptType, "");
 
   } else {
     ERR(FTL) << "Unknown FlatTree format!" << std::endl;
   }
 
   // Make the FlatTree reconfigure
   flattreecreator->Reconfigure();
   f->cd();
   flattreecreator->Write();
   f->Close();
 
   // Show Final Status
   LOG(FIT) << "-------------------------------------" << std::endl;
   LOG(FIT) << "Flattree Generation Complete." << std::endl;
   LOG(FIT) << "-------------------------------------" << std::endl;
 
   return 0;
 }
diff --git a/app/nuissmear.cxx b/app/nuissmear.cxx
index 878f0d5..c558d1f 100644
--- a/app/nuissmear.cxx
+++ b/app/nuissmear.cxx
@@ -1,222 +1,223 @@
 // Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret
 
 /*******************************************************************************
 *    This file is part of NUISANCE.
 *
 *    NUISANCE is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    NUISANCE is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with NUISANCE.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
 #include "ComparisonRoutines.h"
 #include "InputUtils.h"
 
 #include "Smearceptance_Tester.h"
 
 // Global Arguments
 std::string gOptInputFile = "";
 std::string gOptOutputFile = "";
 std::string gOptType = "DEFAULT";
 std::string gOptNumberEvents = "NULL";
 std::string gOptCardInput = "";
 std::string gOptOptions = "";
 
 //*******************************
 void PrintSyntax() {
   //*******************************
 
   std::cout << "nuisflat -i input [-o outfile] [-n nevents] [-t "
                "options] [-q con=val] \n";
   std::cout
       << "\n Arguments : "
       << "\n\t -i input   : Path to input vector of events to flatten"
       << "\n\t"
       << "\n\t              This should be given in the same format a normal "
          "input file"
       << "\n\t              is given to NUISANCE. {e.g. NUWRO:eventsout.root}."
       << "\n\t"
       << "\n\t[-c crd.xml]: Input card file to override configs or define "
          "smearcepters."
       << "\n\t "
       << "\n\t[-o outfile]: Optional output file path. "
       << "\n\t "
       << "\n\t              If none given, input.smear.root is chosen."
       << "\n\t"
       << "\n\t[-n nevents]: Optional choice of Nevents to run over. Default is "
          "all."
       << "\n\t"
       << "\n\t[-t options]: Pass OPTION to the smearception sample. "
       << "\n\t              Similar to type field in comparison xml configs."
       << "\n\t"
       << "\n\t[-q con=val]: Configuration overrides." << std::endl;
 
   exit(-1);
 };
 
 //____________________________________________________________________________
 void GetCommandLineArgs(int argc, char** argv) {
   // Check for -h flag.
   for (int i = 0; i < argc; i++) {
     if ((!std::string(argv[i]).compare("-h")) ||
         (!std::string(argv[i]).compare("-?")) ||
         (!std::string(argv[i]).compare("--help")))
       PrintSyntax();
   }
 
   // Format is nuwro -r run_number -n n events
   std::vector<std::string> args = GeneralUtils::LoadCharToVectStr(argc, argv);
 
   // Parse input file
   ParserUtils::ParseArgument(args, "-i", gOptInputFile, false);
   if (gOptInputFile == "") {
     THROW("Need to provide a valid input file to nuisflat using -i flag!");
   } else {
     LOG(FIT) << "Reading Input File = " << gOptInputFile << std::endl;
     gOptInputFile = InputUtils::PrependGuessedInputTypeToName(gOptInputFile);
   }
 
   // Get Output File
   ParserUtils::ParseArgument(args, "-o", gOptOutputFile, false);
   if (gOptOutputFile == "") {
     gOptOutputFile = gOptInputFile + ".smear.root";
     LOG(FIT) << "No output file given so saving nuisflat output to:"
              << gOptOutputFile << std::endl;
   } else {
     LOG(FIT) << "Saving nuisflat output to " << gOptOutputFile << std::endl;
   }
 
   // Get N Events and Configs
   nuisconfig configuration = Config::Get();
 
   ParserUtils::ParseArgument(args, "-n", gOptNumberEvents, false);
   if (gOptNumberEvents.compare("NULL")) {
     configuration.OverrideConfig("MAXEVENTS=" + gOptNumberEvents);
   }
 
   std::vector<std::string> configargs;
   ParserUtils::ParseArgument(args, "-q", configargs);
   for (size_t i = 0; i < configargs.size(); i++) {
     configuration.OverrideConfig(configargs[i]);
   }
 
   ParserUtils::ParseArgument(args, "-c", gOptCardInput, false);
   if (gOptCardInput != "") {
     QLOG(FIT, "Reading cardfile: " << gOptCardInput);
-    configuration.LoadConfig(gOptCardInput, "");
+    configuration.LoadSettings(gOptCardInput, "");
   }
 
   ParserUtils::ParseArgument(args, "-t", gOptOptions, false);
   if (gOptOptions != "") {
     QLOG(FIT, "Read options: \"" << gOptOptions << "\'");
   }
   return;
 }
 
 void SetupRW() {
   std::vector<nuiskey> parkeys = Config::QueryKeys("parameter");
   if (!parkeys.empty()) {
     LOG(FIT) << "Number of parameters :  " << parkeys.size() << std::endl;
   }
 
   std::vector<std::string> Params;
   std::map<std::string, int> TypeVals;
   std::map<std::string, double> CurrVals;
   for (size_t i = 0; i < parkeys.size(); i++) {
     nuiskey key = parkeys.at(i);
 
     // Check for type,name,nom
     if (!key.Has("type")) {
       ERR(FTL) << "No type given for parameter " << i << std::endl;
       ERR(FTL) << "type='PARAMETER_TYPE'" << std::endl;
       throw;
     } else if (!key.Has("name")) {
       ERR(FTL) << "No name given for parameter " << i << std::endl;
       ERR(FTL) << "name='SAMPLE_NAME'" << std::endl;
       throw;
     } else if (!key.Has("nominal")) {
       ERR(FTL) << "No nominal given for parameter " << i << std::endl;
       ERR(FTL) << "nominal='NOMINAL_VALUE'" << std::endl;
       throw;
     }
 
     // Get Inputs
     std::string partype = key.GetS("type");
     std::string parname = key.GetS("name");
     double parnom = key.GetD("nominal");
 
     // Push into vectors
     Params.push_back(parname);
 
     TypeVals[parname] = FitBase::ConvDialType(partype);
     CurrVals[parname] = parnom;
   }
 
   for (UInt_t i = 0; i < Params.size(); i++) {
     FitBase::GetRW()->IncludeDial(Params[i], TypeVals[Params[i]]);
     FitBase::GetRW()->SetDialValue(Params[i], CurrVals[Params[i]]);
   }
 
   FitBase::GetRW()->Reconfigure();
 }
 
 //*******************************
 int main(int argc, char* argv[]) {
   //*******************************
 
   // Parse
   GetCommandLineArgs(argc, argv);
 
   // Make output file
   TFile* f = new TFile(gOptOutputFile.c_str(), "RECREATE");
   if (f->IsZombie()) {
     THROW("Cannot create output file!");
   }
   f->cd();
-  FitPar::Config().out = f;
+  Config::Get().out = f;
 
   // Create a new measurementbase class depending on the Format
   MeasurementBase* flattreecreator = NULL;
 
   // Make a new sample key for the format of interest.
   nuiskey samplekey = Config::CreateKey("sample");
 
-  samplekey.SetS("name", std::string("FlatTree_") + gOptOptions);
-  samplekey.SetS("input", gOptInputFile);
-  samplekey.SetS("type", gOptType);
+  samplekey.Set("name", "FlatTree");
+  samplekey.Set("smearceptor", gOptOptions);
+  samplekey.Set("input", gOptInputFile);
+  samplekey.Set("type", gOptType);
 
   if (gOptOptions == "") {
     THROW(
         "Attempting to flatten with Smearceptor, but no Smearceptor given. "
         "Please supply a -t option.");
   }
   if (gOptCardInput == "") {
     THROW(
         "Attempting to flatten with Smearceptor, but no card passed with "
         "Smearceptors configured. Please supply a -c option.");
   }
 
   SetupRW();
 
   flattreecreator = new Smearceptance_Tester(samplekey);
 
   // Make the FlatTree reconfigure
   flattreecreator->Reconfigure();
   f->cd();
   flattreecreator->Write();
   f->Close();
 
   // Show Final Status
   LOG(FIT) << "-------------------------------------" << std::endl;
   LOG(FIT) << "Flattree Generation Complete." << std::endl;
   LOG(FIT) << "-------------------------------------" << std::endl;
 
   return 0;
 }
diff --git a/cmake/GENIESetup.cmake b/cmake/GENIESetup.cmake
index 148d685..7c0b2c5 100644
--- a/cmake/GENIESetup.cmake
+++ b/cmake/GENIESetup.cmake
@@ -1,155 +1,157 @@
 # Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret
 
 ################################################################################
 #    This file is part of NUISANCE.
 #
 #    NUISANCE is free software: you can redistribute it and/or modify
 #    it under the terms of the GNU General Public License as published by
 #    the Free Software Foundation, either version 3 of the License, or
 #    (at your option) any later version.
 #
 #    NUISANCE is distributed in the hope that it will be useful,
 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 #    GNU General Public License for more details.
 #
 #    You should have received a copy of the GNU General Public License
 #    along with NUISANCE.  If not, see <http://www.gnu.org/licenses/>.
 ################################################################################
 
 # TODO
 # check system for libxml2
 # check whether we need the includes
 # check if we can use a subset of the GENIE libraries
 
 ################################################################################
 #                            Check Dependencies
 ################################################################################
 
 #################################  GENIE  ######################################
 if(GENIE STREQUAL "")
   cmessage(FATAL_ERROR "Variable GENIE is not defined. "
     "The location of a pre-built GENIE install must be defined either as"
     " $ cmake -DGENIE=/path/to/GENIE or as and environment vairable"
     " $ export GENIE=/path/to/GENIE")
 endif()
 
 if (BUILD_GEVGEN)
   cmessage(STATUS "Building custom gevgen")
   LIST(APPEND EXTRA_CXX_FLAGS -D__GEVGEN_ENABLED__)
 endif()
 
 # Extract GENIE VERSION
-execute_process (COMMAND ${CMAKE_SOURCE_DIR}/cmake/getgenieversion.sh ${GENIE}
-  OUTPUT_VARIABLE GENIE_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE)
+if (GENIE_VERSION STREQUAL "AUTO")
+   execute_process (COMMAND ${CMAKE_SOURCE_DIR}/cmake/getgenieversion.sh ${GENIE}
+   OUTPUT_VARIABLE GENIE_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE)
+endif()
 
 execute_process (COMMAND genie-config
   --libs OUTPUT_VARIABLE GENIE_LD_FLAGS_STR OUTPUT_STRIP_TRAILING_WHITESPACE)
 execute_process (COMMAND genie-config
   --topsrcdir OUTPUT_VARIABLE GENIE_INCLUDES_DIR OUTPUT_STRIP_TRAILING_WHITESPACE)
 
 string(REGEX MATCH "-L\([^ ]+\) \(.*\)$" PARSE_GENIE_LIBS_MATCH ${GENIE_LD_FLAGS_STR})
 
 cmessage(DEBUG "genie-config --libs: ${GENIE_LD_FLAGS_STR}")
 
 if(NOT PARSE_GENIE_LIBS_MATCH)
   cmessage(FATAL_ERROR "Expected to be able to parse the result of genie-config --libs to a lib directory and a list of libraries to include, but got: \"${GENIE_LD_FLAGS_STR}\"")
 endif()
 
 set(GENIE_LIB_DIR ${CMAKE_MATCH_1})
 set(GENIE_LIBS_RAW ${CMAKE_MATCH_2})
 string(REPLACE "-l" "" GENIE_LIBS_STRIPED "${GENIE_LIBS_RAW}")
 
 cmessage(STATUS "GENIE version : ${GENIE_VERSION}")
 cmessage(STATUS "GENIE libdir  : ${GENIE_LIB_DIR}")
 cmessage(STATUS "GENIE libs    : ${GENIE_LIBS_STRIPED}")
 
 string(REGEX MATCH "ReinSeghal" WASMATCHED ${GENIE_LIBS_STRIPED})
 if(WASMATCHED AND GENIE_VERSION STREQUAL "210")
   set(GENIE_SEHGAL ${GENIE_LIBS_STRIPED})
   STRING(REPLACE "ReinSeghal" "ReinSehgal" GENIE_LIBS_STRIPED ${GENIE_SEHGAL})
   cmessage(DEBUG "Fixed inconsistency in library naming: ${GENIE_LIBS_STRIPED}")
 endif()
 
 string(REGEX MATCH "ReWeight" WASMATCHED ${GENIE_LIBS_STRIPED})
 if(NOT WASMATCHED)
   set(GENIE_LIBS_STRIPED "GReWeight ${GENIE_LIBS_STRIPED}")
   cmessage(DEBUG "Force added ReWeight library: ${GENIE_LIBS_STRIPED}")
 endif()
 
 string(REPLACE " " ";" GENIE_LIBS_LIST "${GENIE_LIBS_STRIPED}")
 cmessage(DEBUG "genie-config --libs -- MATCH1: ${CMAKE_MATCH_1}")
 cmessage(DEBUG "genie-config --libs -- MATCH2: ${CMAKE_MATCH_2}")
 cmessage(DEBUG "genie-config --libs -- libs stripped: ${GENIE_LIBS_STRIPED}")
 cmessage(DEBUG "genie-config --libs -- libs list: ${GENIE_LIBS_LIST}")
 
 ################################  LHAPDF  ######################################
 if(LHAPDF_LIB STREQUAL "")
   cmessage(FATAL_ERROR "Variable LHAPDF_LIB is not defined. The location of a pre-built lhapdf install must be defined either as $ cmake -DLHAPDF_LIB=/path/to/LHAPDF_libraries or as and environment vairable $ export LHAPDF_LIB=/path/to/LHAPDF_libraries")
 endif()
 
 if(LHAPDF_INC STREQUAL "")
   cmessage(FATAL_ERROR "Variable LHAPDF_INC is not defined. The location of a pre-built lhapdf install must be defined either as $ cmake -DLHAPDF_INC=/path/to/LHAPDF_includes or as and environment vairable $ export LHAPDF_INC=/path/to/LHAPDF_includes")
 endif()
 
 if(LHAPATH STREQUAL "")
   cmessage(FATAL_ERROR "Variable LHAPATH is not defined. The location of a the LHAPATH directory must be defined either as $ cmake -DLHAPATH=/path/to/LHAPATH or as and environment variable $ export LHAPATH=/path/to/LHAPATH")
 endif()
 
 ################################  LIBXML  ######################################
 if(LIBXML2_LIB STREQUAL "")
   cmessage(FATAL_ERROR "Variable LIBXML2_LIB is not defined. The location of a pre-built libxml2 install must be defined either as $ cmake -DLIBXML2_LIB=/path/to/LIBXML2_libraries or as and environment vairable $ export LIBXML2_LIB=/path/to/LIBXML2_libraries")
 endif()
 
 if(LIBXML2_INC STREQUAL "")
   cmessage(FATAL_ERROR "Variable LIBXML2_INC is not defined. The location of a pre-built libxml2 install must be defined either as $ cmake -DLIBXML2_INC=/path/to/LIBXML2_includes or as and environment vairable $ export LIBXML2_INC=/path/to/LIBXML2_includes")
 endif()
 ###############################  log4cpp  ######################################
 if(LOG4CPP_LIB STREQUAL "")
   cmessage(FATAL_ERROR "Variable LOG4CPP_LIB is not defined. The location of a pre-built log4cpp install must be defined either as $ cmake -DLOG4CPP_LIB=/path/to/LOG4CPP_libraries or as and environment vairable $ export LOG4CPP_LIB=/path/to/LOG4CPP_libraries")
 endif()
 
 if(LOG4CPP_INC  STREQUAL "")
   cmessage(FATAL_ERROR "Variable LOG4CPP_INC is not defined. The location of a pre-built log4cpp install must be defined either as $ cmake -DGENIE_LOG4CPP_INC=/path/to/LOG4CPP_includes or as and environment vairable $ export LOG4CPP_INC=/path/to/LOG4CPP_includes")
 endif()
 ################################################################################
 
 LIST(APPEND EXTRA_CXX_FLAGS -D__GENIE_ENABLED__ -D__GENIE_VERSION__=${GENIE_VERSION})
 
 LIST(APPEND RWENGINE_INCLUDE_DIRECTORIES
   ${GENIE_INCLUDES_DIR}
   ${GENIE_INCLUDES_DIR}/GHEP
   ${GENIE_INCLUDES_DIR}/Ntuple
   ${GENIE_INCLUDES_DIR}/ReWeight
   ${GENIE_INCLUDES_DIR}/Apps
   ${GENIE_INCLUDES_DIR}/FluxDrivers
   ${GENIE_INCLUDES_DIR}/EVGDrivers
   ${LHAPDF_INC}
   ${LIBXML2_INC}
   ${LOG4CPP_INC})
 
 SAYVARS()
 
 LIST(APPEND EXTRA_LINK_DIRS
   ${GENIE_LIB_DIR}
   ${LHAPDF_LIB}
   ${LIBXML2_LIB}
   ${LOG4CPP_LIB})
 
 #LIST(REVERSE EXTRA_LIBS)
 #LIST(REVERSE GENIE_LIBS_LIST)
 LIST(APPEND EXTRA_LIBS ${GENIE_LIBS_LIST})
 #LIST(REVERSE EXTRA_LIBS)
 
 LIST(APPEND EXTRA_LIBS LHAPDF xml2 log4cpp)
 
 if(USE_PYTHIA8)
   set(NEED_PYTHIA8 TRUE)
   set(NEED_ROOTPYTHIA8 TRUE)
 else()
   set(NEED_PYTHIA6 TRUE)
   set(NEED_ROOTPYTHIA6 TRUE)
 endif()
 set(NEED_ROOTEVEGEN TRUE)
 
 SET(USE_GENIE TRUE CACHE BOOL "Whether to enable GENIE (reweight) support. Requires external libraries. <FALSE>" FORCE)
diff --git a/cmake/cacheVariables.cmake b/cmake/cacheVariables.cmake
index 1c75a96..9aa2f08 100644
--- a/cmake/cacheVariables.cmake
+++ b/cmake/cacheVariables.cmake
@@ -1,208 +1,209 @@
 # Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret
 
 ################################################################################
 #    This file is part of NUISANCE.
 #
 #    NUISANCE is free software: you can redistribute it and/or modify
 #    it under the terms of the GNU General Public License as published by
 #    the Free Software Foundation, either version 3 of the License, or
 #    (at your option) any later version.
 #
 #    NUISANCE is distributed in the hope that it will be useful,
 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 #    GNU General Public License for more details.
 #
 #    You should have received a copy of the GNU General Public License
 #    along with NUISANCE.  If not, see <http://www.gnu.org/licenses/>.
 ################################################################################
 
 function(CheckAndSetDefaultEnv VARNAME DEFAULT CACHETYPE DOCSTRING ENVNAME)
   #cmessage(DEBUG "Trying to assign variable ${VARNAME} into the cache.")
   if(NOT DEFINED ${VARNAME})
     if(DEFINED ENV{${ENVNAME}} AND NOT $ENV{${ENVNAME}} STREQUAL "")
       set(${VARNAME} $ENV{${ENVNAME}} CACHE ${CACHETYPE} ${DOCSTRING})
       cmessage(DEBUG "    Read ${VARNAME} from ENVVAR ${ENVNAME} as $ENV{${ENVNAME}}.")
     else()
       set(${VARNAME} ${DEFAULT} CACHE ${CACHETYPE} ${DOCSTRING})
     endif()
   else()
     set(${VARNAME} ${${VARNAME}} CACHE ${CACHETYPE} ${DOCSTRING})
     unset(${VARNAME})
   endif()
   cmessage(CACHE "--Set cache variable: \"${VARNAME}\" to \"${${VARNAME}}\", in cache ${CACHETYPE}.")
 endfunction()
 
 function(CheckAndSetDefaultCache VARNAME DEFAULT CACHETYPE DOCSTRING)
 #  cmessage(DEBUG "Trying to assign variable ${VARNAME} into the cache.")
   if(NOT DEFINED ${VARNAME})
     set(${VARNAME} ${DEFAULT} CACHE ${CACHETYPE} ${DOCSTRING})
   else()
     set(${VARNAME} ${${VARNAME}} CACHE ${CACHETYPE} ${DOCSTRING})
     unset(${VARNAME})
   endif()
   cmessage(CACHE "--Set cache variable: \"${VARNAME}\" to \"${${VARNAME}}\", in cache ${CACHETYPE}.")
 endfunction()
 
 function(CheckAndSetDefault VARNAME DEFAULT)
 #  cmessage(DEBUG "Trying to assign variable ${VARNAME}.")
   if(NOT DEFINED ${VARNAME})
     set(${VARNAME} ${DEFAULT} PARENT_SCOPE)
     set(${VARNAME} ${DEFAULT})
   endif()
   cmessage(CACHE "--Set variable: \"${VARNAME}\" to \"${${VARNAME}}\".")
 endfunction()
 
 CheckAndSetDefaultCache(VERBOSE TRUE BOOL "Whether to configure loudly.")
 
 set (CMAKE_SKIP_BUILD_RPATH TRUE)
 
 #Changes default install path to be a subdirectory of the build dir.
 #Can set build dir at configure time with -DCMAKE_INSTALL_PREFIX=/install/path
 if(CMAKE_INSTALL_PREFIX STREQUAL "" OR CMAKE_INSTALL_PREFIX STREQUAL
   "/usr/local")
   set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/${CMAKE_SYSTEM_NAME}")
 elseif(NOT DEFINED CMAKE_INSTALL_PREFIX)
   set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/${CMAKE_SYSTEM_NAME}")
 endif()
 
 if(CMAKE_BUILD_TYPE STREQUAL "")
   set(CMAKE_BUILD_TYPE DEBUG)
 elseif(NOT DEFINED CMAKE_BUILD_TYPE)
   set(CMAKE_BUILD_TYPE DEBUG)
 endif()
 
 CheckAndSetDefaultCache(USE_MINIMIZER TRUE INTERNAL "Whether we are using the ROOT minimization libraries. <TRUE>")
 
 CheckAndSetDefaultCache(USE_HEPMC FALSE BOOL "Whether to enable HepMC input support. <FALSE>")
 CheckAndSetDefaultEnv(HEPMC "" PATH "Path to HepMC source tree root directory. Overrides environment variable \$HEPMC <>" HEPMC)
 CheckAndSetDefaultCache(HEPMC_MOMUNIT "GEV" STRING "HepMC momentum units [MEV|GEV]. <GEV>")
 CheckAndSetDefaultCache(HEPMC_LENUNIT "CM" STRING "HepMC momentum units [MM|CM]. <CM>")
 CheckAndSetDefaultCache(HEPMC_USED_EP FALSE INTERNAL "Whether we built HepMC or not. <FALSE>")
 
 CheckAndSetDefaultCache(USE_NEUT FALSE BOOL "Whether to enable NEUT (reweight) support. Requires external libraries. <FALSE>")
 CheckAndSetDefaultEnv(NEUT_ROOT "" PATH "Path to NEUT source tree root directory. Overrides environment variable \$NEUT_ROOT <>" NEUT_ROOT)
 CheckAndSetDefaultEnv(CERN "" PATH "Path to CERNLIB source tree root directory that NEUT was built against. Overrides environment variable \$CERN <>" CERN)
 CheckAndSetDefaultEnv(CERN_LEVEL "" STRING "CERNLIB Library version. Overrides environment variable \$CERN_LEVEL <>" CERN_LEVEL)
 
 CheckAndSetDefaultCache(USE_NuWro FALSE BOOL "Whether to enable NuWro support. <FALSE>")
 CheckAndSetDefaultEnv(NUWRO "" PATH "Path to NuWro source tree root directory. Overrides environment variable \$NUWRO <>" NUWRO)
 CheckAndSetDefaultEnv(NUWRO_INC "" PATH "Path to NuWro installed includes directory, needs to contain \"params_all.h\". Overrides environment variable \$NUWRO_INC <>" NUWRO_INC)
 CheckAndSetDefaultCache(NUWRO_INPUT_FILE "" FILEPATH "Path to an input NuWro event vector, which can be used to build NuWro i/o libraries. <>")
 CheckAndSetDefaultCache(NUWRO_BUILT_FROM_FILE FALSE INTERNAL "Whether the NuWro libraries were built by NUISANCE. <FALSE>")
 CheckAndSetDefaultCache(USE_NuWro_RW FALSE BOOL "Whether to try and build support for NuWro reweighting. <FALSE>")
 CheckAndSetDefaultCache(USE_NuWro_SRW_Event FALSE BOOL "Whether to use cut down NuWro reweight event format. Requires NuWro reweight. <FALSE>")
 
 CheckAndSetDefaultCache(USE_GENIE FALSE BOOL "Whether to enable GENIE (reweight) support. Requires external libraries. <FALSE>")
+CheckAndSetDefaultCache(GENIE_VERSION "AUTO" STRING "GENIE Version <AUTO>")
 CheckAndSetDefaultEnv(GENIE "" PATH "Path to GENIE source tree root directory. Overrides environment variable \$GENIE <>" GENIE)
 CheckAndSetDefaultEnv(LHAPDF_LIB "" PATH "Path to pre-built LHAPDF libraries. Overrides environment variable \$LHAPDF_LIB. <>" LHAPDF_LIB)
 CheckAndSetDefaultEnv(LHAPDF_INC "" PATH "Path to installed LHAPDF headers. Overrides environment variable \$LHAPDF_INC. <>" LHAPDF_INC)
 CheckAndSetDefaultEnv(LHAPATH "" PATH "Path to LHA PDF inputs. Overrides environment variable \$LHAPATH. <>" LHAPATH)
 CheckAndSetDefaultEnv(LIBXML2_LIB "" PATH "Path to pre-built LIBXML2 libraries. Overrides environment variable \$LIBXML2_LIB. <>" LIBXML2_LIB)
 CheckAndSetDefaultEnv(LIBXML2_INC "" PATH "Path to installed LIBXML2 headers. Overrides environment variable \$LIBXML2_INC. <>" LIBXML2_INC)
 CheckAndSetDefaultEnv(LOG4CPP_LIB "" PATH "Path to pre-built LOG4CPP libraries. Overrides environment variable \$LOG4CPP_LIB. <>" LOG4CPP_LIB)
 CheckAndSetDefaultEnv(LOG4CPP_INC "" PATH "Path to installed LOG4CPP headers. Overrides environment variable \$LOG4CPP_INC. <>" LOG4CPP_INC)
 
 CheckAndSetDefaultCache(BUILD_GEVGEN FALSE BOOL "Whether to build nuisance_gevgen app.")
 
 CheckAndSetDefaultCache(USE_T2K FALSE BOOL "Whether to enable T2KReWeight support. Requires external libraries. <FALSE>")
 CheckAndSetDefaultEnv(T2KREWEIGHT "" PATH "Path to installed T2KREWEIGHTReWeight. Overrides environment variable \$T2KREWEIGHT. <>" T2KREWEIGHT)
 
 CheckAndSetDefaultCache(USE_NIWG FALSE BOOL "Whether to enable (T2K) NIWG ReWeight support. Requires external libraries. <FALSE>")
 CheckAndSetDefaultEnv(NIWG_ROOT "" PATH "Path to installed NIWGReWeight. Overrides environment variable \$NIWG. <>" NIWG)
 
 CheckAndSetDefaultCache(USE_MINERvA_RW FALSE BOOL "Whether to enable MINERvA ReWeight support. <FALSE>")
 
 CheckAndSetDefaultEnv(PYTHIA6 "" PATH "Path to directory containing libPythia6.so. Overrides environment variable \$PYTHIA6 <>" PYTHIA6)
 
 CheckAndSetDefaultEnv(PYTHIA8 "" PATH "Path to directory containing libPythia8.so. Overrides environment variable \$PYTHIA8 <>" PYTHIA8)
 CheckAndSetDefaultCache(USE_PYTHIA8 FALSE BOOL "Whether to enable PYTHIA8 event support. <FALSE>")
 
 CheckAndSetDefaultCache(USE_GiBUU TRUE BOOL "Whether to enable GiBUU event support. <TRUE>")
 CheckAndSetDefaultCache(BUILD_GiBUU FALSE BOOL "Whether to build supporting GiBUU event tools along with a patched version of GiBUU. <FALSE>")
 
 CheckAndSetDefaultCache(USE_NUANCE TRUE BOOL "Whether to enable NUANCE event support. <TRUE>")
 
 CheckAndSetDefaultCache(USE_PROB3PP FALSE BOOL "Whether to download and compile in Prob3++ support. <FALSE>")
 
 CheckAndSetDefaultCache(NO_EXTERNAL_UPDATE TRUE BOOL "Whether to perform the update target for external dependencies. <TRUE>")
 
 CheckAndSetDefaultCache(USE_GPERFTOOLS FALSE BOOL "Whether to compile in google performance tools. <TRUE>")
 
 CheckAndSetDefault(NEED_PYTHIA6 FALSE)
 CheckAndSetDefault(NEED_PYTHIA8 FALSE)
 
 CheckAndSetDefault(NEED_ROOTEVEGEN FALSE)
 CheckAndSetDefault(NEED_ROOTPYTHIA6 FALSE)
 
 CheckAndSetDefaultCache(USE_OMP FALSE BOOL "Whether to enable multicore features (there currently are none...). <FALSE>")
 
 CheckAndSetDefault(NO_EXPERIMENTS FALSE)
 
 cmessage(STATUS "NO_EXPERIMENTS: ${NO_EXPERIMENTS}")
 
 CheckAndSetDefaultCache(NO_ANL ${NO_EXPERIMENTS} BOOL "Whether to *NOT* build ANL samples. <-DNO_EXPERIMENTS=FALSE>")
 CheckAndSetDefaultCache(NO_ArgoNeuT ${NO_EXPERIMENTS} BOOL "Whether to *NOT* build ArgoNeuT samples. <-DNO_EXPERIMENTS=FALSE>")
 CheckAndSetDefaultCache(NO_BEBC ${NO_EXPERIMENTS} BOOL "Whether to *NOT* build BEBC samples. <-DNO_EXPERIMENTS=FALSE>")
 CheckAndSetDefaultCache(NO_BNL ${NO_EXPERIMENTS} BOOL "Whether to *NOT* build BNL samples. <-DNO_EXPERIMENTS=FALSE>")
 CheckAndSetDefaultCache(NO_FNAL ${NO_EXPERIMENTS} BOOL "Whether to *NOT* build FNAL samples. <-DNO_EXPERIMENTS=FALSE>")
 CheckAndSetDefaultCache(NO_GGM ${NO_EXPERIMENTS} BOOL "Whether to *NOT* build GGM samples. <-DNO_EXPERIMENTS=FALSE>")
 CheckAndSetDefaultCache(NO_K2K ${NO_EXPERIMENTS} BOOL "Whether to *NOT* build K2K samples. <-DNO_EXPERIMENTS=FALSE>")
 CheckAndSetDefaultCache(NO_MINERvA ${NO_EXPERIMENTS} BOOL "Whether to *NOT* build MINERvA samples. <-DNO_EXPERIMENTS=FALSE>")
 CheckAndSetDefaultCache(NO_MiniBooNE ${NO_EXPERIMENTS} BOOL "Whether to *NOT* build MiniBooNE samples. <-DNO_EXPERIMENTS=FALSE>")
 CheckAndSetDefaultCache(NO_T2K ${NO_EXPERIMENTS} BOOL "Whether to *NOT* build T2K samples. <-DNO_EXPERIMENTS=FALSE>")
 CheckAndSetDefaultCache(NO_SciBooNE ${NO_EXPERIMENTS} BOOL "Whether to *NOT* build SciBooNE samples. <-DNO_EXPERIMENTS=FALSE>")
 
 
 function(SAYVARS)
 
 LIST(APPEND VARS
   USE_HEPMC
   HEPMC
   HEPMC_MOMUNIT
   HEPMC_LENUNIT
   HEPMC_USED_EP
   USE_NEUT
   NEUT_ROOT
   CERN
   CERN_LEVEL
   USE_NuWro
   NUWRO
   NUWRO_INC
   NUWRO_INPUT_FILE
   NUWRO_BUILT_FROM_FILE
   USE_GENIE
   GENIE
   LHAPDF_LIB
   LHAPDF_INC
   LIBXML2_LIB
   LIBXML2_INC
   LOG4CPP_LIB
   GENIE_LOG4CPP_INC
   BUILD_GEVGEN
   USE_T2K
   USE_NIWG
   USE_GiBUU
   BUILD_GiBUU
   USE_NUANCE
   NO_EXTERNAL_UPDATE
   USE_GPERFTOOLS
   NO_ANL
   NO_ArgoNeuT
   NO_BEBC
   NO_BNL
   NO_FNAL
   NO_GGM
   NO_K2K
   NO_MINERvA
   NO_MiniBooNE
   NO_T2K
   NO_SciBooNE)
 
   foreach(v ${VARS})
     if(DEFINED ${v})
       cmessage(DEBUG "VARIABLE: \"${v}\" = \"${${v}}\"")
     endif()
   endforeach(v)
 
 endfunction()
diff --git a/parameters/config.xml b/parameters/config.xml
index 8ad5bc2..4e103d0 100644
--- a/parameters/config.xml
+++ b/parameters/config.xml
@@ -1,200 +1,214 @@
 <nuisance>
 <!-- # ###################################################### -->
 <!-- # NUISANCE CONFIGURATION OPTIONS -->
 <!-- # This file is read in by default at runtime -->
 <!-- # If you want to override on a case by case bases use -q at runtime -->
 <!-- # ###################################################### -->
 
 <!-- # MAIN Configs -->
 <!-- # ###################################################### -->
 
 <!-- # Logger goes from -->
 <!-- # 1 Quiet -->
 <!-- # 2 Fitter -->
 <!-- # 3 Samples -->
 <!-- # 4 Reconfigure Loops -->
 <!-- # 5 Every Event print out (SHOUT) -->
 <!-- # -1 DEBUGGING -->
 <config verbosity='5'/>
 <config VERBOSITY='5'/>
 
 <!-- # ERROR goes from -->
 <!-- # 0 NONE -->
 <!-- # 1 FATAL -->
 <!-- # 2 WARN -->
 <config ERROR='2'/>
 <config TRACE='0'/>
 
 <config cores='1' />
 <config spline_test_throws='50' />
 <config spline_cores='1' />
 <config spline_chunks='20' />
 <config spline_procchunk='-1' />
 
 <config Electron_NThetaBins='4' />
 <config Electron_NEnergyBins='4' />
 <config Electron_ThetaWidth='1.0' />
 <config Electron_EnergyWidth='0.10' />
 
 <config RemoveFSIParticles='0' />
 <config RemoveUndefParticles='0' />
 <config RemoveNuclearParticles='0'/>
 <config logging.JointFCN.cxx='4'/>
 <config MINERvASaveExtraCCQE='0' />
 
 <!-- # Input Configs -->
 <!-- # ###################################################### -->
 
 <!-- # Default Requirements file for the externalDataFitter Package -->
 <!-- # MAX Events : -1 is no cut. Events will be scaled automatically to give good xsec predictions. -->
 <config input.maxevents='-1'/>
 <config MAXEVENTS='-1'/>
 <config input.MAXEVENTS='-1'/>
 <config includeemptystackhists='0'/>
 <!-- # Turn on/off event manager -->
 <!-- # EventManager enables us to only loop number of events once for multiple projections of the same measurements -->
 <!-- # e.g. MiniBooNE CC1pi+ Q2 and MiniBooNE CC1pi+ Tmu would ordinarily require 2 reconfigures, but with this enabled it requires only one -->
 <config input.eventmanager='1'/>
 <config EventManager='1'/>
 
 <!-- # Event Directories -->
 <!-- # Can setup default directories and use @EVENT_DIR/path to link to it -->
 <config EVENT_DIR='/data2/stowell/NIWG/'/>
 <config NEUT_EVENT_DIR='/data2/stowell/NIWG/neut/fit_samples_neut5.3.3/'/>
 <config GENIE_EVENT_DIR='/data2/stowell/NIWG/genie/fit_samples_R.2.10.0/'/>
 <config NUWRO_EVENT_DIR='/data2/stowell/NIWG/nuwro/fit_samples/'/>
 <config GIBUU_EVENT_DIR='/data/GIBUU/DIR/'/>
 <config SaveNuWroExtra='0' />
 
 <!-- # In PrepareGENIE the reconstructed splines can be saved into the file -->
 <config save_genie_splines='1'/>
 
 <!-- # In InputHandler the option to regenerate NuWro flux/xsec plots is available -->
 <!-- # Going to move this to its own app soon -->
 <config input.regen_nuwro_plots='0'/>
 
 <!-- # DEVEL CONFIG OPTION, don't touch! -->
 <config CacheSize='0'/>
 
 <!-- # ReWeighting Configuration Options -->
 <!-- # ###################################################### -->
 
 <!-- # Set absolute twkdial for parameters -->
 <config params.setabstwk='0'/>
 
 <!-- # Convert Dials in output statements using dial conversion card -->
 <config convert_dials='0'/>
 
 <!-- # Make RW Calculations be quiet -->
 <config params.silentweighting='0'/>
 
 <!-- # Vetos can be used to specify RW dials NOT to be loaded in -->
 <!-- # Useful if one specific one has an issue -->
 <config FitWeight.fNIWGRW_veto=''/>
 <config FitWeight.fNuwroRW_veto=''/>
 <config FitWeight.fNeutRW_veto=''/>
 <config FitWeight.fGenieRW_veto=''/>
 
 
 <!-- # Output Options -->
 <!-- # ###################################################### -->
 
 <!-- # Save Nominal prediction with all rw engines at default -->
 <config savenominal='0'/>
 
 <!-- # Save prefit with values at starting values -->
 <config saveprefit='0'/>
 
 <!-- # Here's the full list of drawing options -->
 <!-- # See src/FitBase/Measurement1D::Write for more info -->
 <!-- #config drawopts DATA/MC/EVT/FINE/RATIO/MODES/SHAPE/RESIDUAL/MATRIX/FLUX/MASK/MAP -->
 <!-- #config drawopts DATA/MC -->
 <config drawopts='DATA/MC/EVT/FINE/RATIO/MODES/SHAPE/FLUX/XSEC/MASK/COV/INCOV/DECOMP/CANVPDG/CANVMC/SETTINGS'/>
 
 <config InterpolateSigmaQ0Histogram='1' />
 <config InterpolateSigmaQ0HistogramRes='100' />
 <config InterpolateSigmaQ0HistogramThrow='1' />
 <config InterpolateSigmaQ0HistogramNTHROWS='100000' />
 
 <!-- # Save the shape scaling applied with option SHAPE into the main MC hist -->
 <config saveshapescaling='0'/>
 
 <config CorrectGENIEMECNorm='1'/>
 
 <!-- # Set style of 1D output histograms -->
 <config linecolour='1'/>
 <config linestyle='1'/>
 <config linewidth='1'/>
 
 <!-- # For GenericFlux -->
 <config isLiteMode='0'/>
 
 <!-- # Statistical Options -->
 <!-- # ###################################################### -->
 
 <!-- # Add MC Statistical error to likelihoods -->
 <config statutils.addmcerror='0'/>
 
 <!-- # NUISMIN Configurations -->
 <!-- # ###################################################### -->
 
 <config minimizer.maxcalls='1000000'/>
 <config minimizer.maxiterations='1000000'/>
 <config minimizer.tolerance='0.001'/>
 
 <!-- # Number of events required in low stats routines -->
 <config minimizer.lowstatevents='25000'/>
 
 
 <!-- # Error band generator configs -->
 <!-- # ###################################################### -->
 
 <!-- # For -f ErrorBands creates error bands for given measurements -->
 <!-- # How many throws do we want (The higher the better precision) -->
 <config error_throws='250'/>
 
 <!-- # Are we throwing uniform or according to Gaussian? -->
 <!-- # Only use uniform if wanting to study the limits of a dial. -->
 <config error_uniform='0'/>
 <config WriteSeperateStacks='1'/>
 
 <!-- # Other Individual Case Configs -->
 <!-- # ###################################################### -->
 
 <!-- # Covariance throw options for fake data studies with MiniBooNE data. -->
 <config thrown_covariance='FULL'/>
 <config throw_mc_stat='0.0'/>
 <config throw_diag_syst='0'/>
 <config throw_corr_syst='0'/>
 <config throw_mc_stat='0'/>
 
 <!-- # Apply a shift to the muon momentum before calculation of Q2 -->
 <config muon_momentum_shift='0.0'/>
 <config muon_momentum_throw='0'/>
 
 <!-- # MINERvA Specific Configs -->
 <config MINERvA_XSec_CCinc_2DEavq3_nu.hadron_cut='0'/>
 <config MINERvA_CCinc_XSec_2DEavq3_nu.useq3true='0'/>
 <config Modes.split_PN_NN='0'/>
 <config SignalReconfigures='0'/>
 
 <!-- # SciBooNE specific -->
 <config SciBarDensity='1.04'/>
 <config SciBarRecoDist='10.0'/>
 <config PenetratingMuonEnergy='1.4'/>
 <config NumRangeSteps='50'/>
 
 <config MINERvADensity='1.04'/>
 <config MINERvARecoDist='10.0'/>
 <config PenetratingMuonEnergy='1.4'/>
 <config NumRangeSteps='50'/>
 
 
 
 <config GENIEWeightEngine_CCRESMode="kModeMaMv"/>
 <config  GENIEInputHandler.SavePrimary="0" />
 
 <config NToyThrows='100000' />
 
+
+<config GENIEXSecModelCCRES="genie::ReinSehgalRESPXSec" />
+<config GENIEXSecModelCOH="genie::ReinSehgalCOHPiPXSec" />
+<config GENIEXSecModelCCQE="genie::LwlynSmithQELCCPXSec" />
+
+<!--
+<config GENIEXSecModelCCQE="genie::NievesQELCCPXSec" />
+<config GENIEXSecModelCCRES="genie::BergerSehgalRESPXSec2014" />
+<config GENIEXSecModelCOH="genie::BergerSehgalCOHPiPXSec2015" />
+-->
+
+<config UseShapeCovar="0" />
+<config CC0piNBINS="156" />
+
 </nuisance>
 
diff --git a/scripts/dumpgenieconfig.py b/scripts/dumpgenieconfig.py
new file mode 100644
index 0000000..b5c98c3
--- /dev/null
+++ b/scripts/dumpgenieconfig.py
@@ -0,0 +1,35 @@
+from ROOT import TFile, TFolder, TObjString
+import sys
+
+def PrintKey(obj, indent):
+    splitkey = obj.GetName().split(";")
+    keydict  = {}
+    for val in reversed(splitkey):
+        splitval = val.split(":")
+        if (len(splitval) < 2): splitval = val.split("=")
+        keydict[splitval[0].strip()] = ''.join(splitval[1:]).strip()
+        
+    print indent, keydict
+
+def ExpandKeys(keydir, indent):
+    for obj in keydir.GetListOfFolders():
+        if "TFolder" in str(type(obj)):
+            print indent, obj.GetName()
+            ExpandKeys(obj, indent + " -> ")
+        if "TObjString" in str(type(obj)):
+            PrintKey(obj, indent )
+
+def ExpandGlobalList(keydir):
+    for obj in keydir.GetListOfFolders():
+        if str(obj.GetName()) != "GlobalParameterList": continue
+        print "GLOBAL : ", obj.GetName()
+        ExpandKeys(obj,"GLOBAL : ")
+
+if __name__=="__main__":
+
+    myfile = TFile(sys.argv[1],"READ")
+    configs = myfile.Get("gconfig")
+    ExpandKeys(configs,"")
+
+    print "\n# Global List #\n"
+    ExpandGlobalList(configs)
diff --git a/scripts/nuissamples b/scripts/nuissamples
index a80432a..7721fe5 100755
--- a/scripts/nuissamples
+++ b/scripts/nuissamples
@@ -1,20 +1,19 @@
 #!/bin/sh
 
-for line in $(grep compare $NUISANCE/src/FCN/SampleList.cxx)
-do
-    if [[ $line != *"compare"* ]];
-    then
-	continue
-    fi
-    line=${line//\!name\.compare\(/}
-    line=${line//\(/}
-    line=${line//\)/}
-    line=${line//\"/}
+for line in $(grep compare $NUISANCE/src/FCN/SampleList.cxx); do
+  if [[ $line != *"compare"* ]]; then
+    continue
+  fi
+  line=${line//\!name\.compare\(/}
+  line=${line//\(/}
+  line=${line//\)/}
+  line=${line//\"/}
+  line=${line//\{}
 
-    if [[ $line != *"$1"* ]];
-    then
-	continue
-    fi
+  if [[ $line != *"$1"* ]];
+  then
+    continue
+  fi
 
-    echo ${2}${line}${3}
+  echo ${2}${line}${3}
 done
diff --git a/src/Routines/CMakeLists.txt b/src/Config/CMakeLists.txt
similarity index 79%
copy from src/Routines/CMakeLists.txt
copy to src/Config/CMakeLists.txt
index 2c5cf1c..7577b9d 100644
--- a/src/Routines/CMakeLists.txt
+++ b/src/Config/CMakeLists.txt
@@ -1,66 +1,52 @@
 # Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret
 
 ################################################################################
 #    This file is part of NUISANCE.
 #
 #    NUISANCE is free software: you can redistribute it and/or modify
 #    it under the terms of the GNU General Public License as published by
 #    the Free Software Foundation, either version 3 of the License, or
 #    (at your option) any later version.
 #
 #    NUISANCE is distributed in the hope that it will be useful,
 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 #    GNU General Public License for more details.
 #
 #    You should have received a copy of the GNU General Public License
 #    along with NUISANCE.  If not, see <http://www.gnu.org/licenses/>.
 ################################################################################
-set(IMPLFILES
-ComparisonRoutines.cxx
-SystematicRoutines.cxx
-SplineRoutines.cxx
-)
-
-if(USE_MINIMIZER)
-  set(IMPLFILES ${IMPLFILES};MinimizerRoutines.cxx)
-endif()
-
 set(HEADERFILES
-ComparisonRoutines.h
-SystematicRoutines.h
-SplineRoutines.h
+NuisConfig.h
+NuisKey.h
 )
 
-if(USE_MINIMIZER)
-  set(HEADERFILES ${HEADERFILES};MinimizerRoutines.h)
-endif()
+set(IMPLFILES
+NuisConfig.cxx
+NuisKey.cxx
+)
 
-set(LIBNAME Routines)
+set(LIBNAME Config)
 
 if(CMAKE_BUILD_TYPE MATCHES DEBUG)
   add_library(${LIBNAME} STATIC ${IMPLFILES})
 else(CMAKE_BUILD_TYPE MATCHES RELEASE)
   add_library(${LIBNAME} SHARED ${IMPLFILES})
 endif()
 
-include_directories(${EXP_INCLUDE_DIRECTORIES})
-
 include_directories(${MINIMUM_INCLUDE_DIRECTORIES})
 
-include_directories(${CMAKE_SOURCE_DIR}/src/FCN)
-include_directories(${CMAKE_SOURCE_DIR}/src/MCStudies)
-
 set_target_properties(${LIBNAME} PROPERTIES VERSION
   "${NUISANCE_VERSION_MAJOR}.${NUISANCE_VERSION_MINOR}.${NUISANCE_VERSION_REVISION}")
+
 #set_target_properties(${LIBNAME} PROPERTIES LINK_FLAGS ${ROOT_LD_FLAGS})
 
 if(DEFINED PROJECTWIDE_EXTRA_DEPENDENCIES)
   add_dependencies(${LIBNAME} ${PROJECTWIDE_EXTRA_DEPENDENCIES})
 endif()
 
 install(TARGETS ${LIBNAME} DESTINATION lib)
 #Can uncomment this to install the headers... but is it really neccessary?
 #install(FILES ${HEADERFILES} DESTINATION include)
 
 set(MODULETargets ${MODULETargets} ${LIBNAME} PARENT_SCOPE)
diff --git a/src/Config/NuisConfig.cxx b/src/Config/NuisConfig.cxx
new file mode 100644
index 0000000..f1f1033
--- /dev/null
+++ b/src/Config/NuisConfig.cxx
@@ -0,0 +1,802 @@
+// Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret
+
+/*******************************************************************************
+*    This file is part of NUISANCE.
+*
+*    NUISANCE is free software: you can redistribute it and/or modify
+*    it under the terms of the GNU General Public License as published by
+*    the Free Software Foundation, either version 3 of the License, or
+*    (at your option) any later version.
+*
+*    NUISANCE is distributed in the hope that it will be useful,
+*    but WITHOUT ANY WARRANTY; without even the implied warranty of
+*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*    GNU General Public License for more details.
+*
+*    You should have received a copy of the GNU General Public License
+*    along with NUISANCE.  If not, see <http://www.gnu.org/licenses/>.
+*******************************************************************************/
+#include "NuisConfig.h"
+
+#include "FitLogger.h"
+#include "GeneralUtils.h"
+#include "TXMLEngine.h"
+
+namespace Config {
+
+nuisconfig &Get() { return nuisconfig::GetConfig(); };
+std::string GetPar(std::string const &name) { return Get().GetConfig(name); }
+bool HasPar(std::string const &name) { return Get().HasConfig(name); }
+std::string GetParS(std::string const &name) { return Get().GetConfigS(name); }
+int GetParI(std::string const &name) { return Get().GetConfigI(name); }
+bool GetParB(std::string const &name) { return Get().GetConfigB(name); }
+float GetParF(std::string const &name) { return Get().GetConfigF(name); }
+double GetParD(std::string const &name) { return Get().GetConfigD(name); }
+void SetPar(std::string const &name, std::string const &val) {
+  Get().SetConfig(name, val);
+}
+void SetPar(std::string const &name, char const *val) {
+  Get().SetConfig(name, val);
+}
+void SetPar(std::string const &name, bool val) { Get().SetConfig(name, val); }
+void SetPar(std::string const &name, int val) { Get().SetConfig(name, val); }
+void SetPar(std::string const &name, float val) { Get().SetConfig(name, val); }
+void SetPar(std::string const &name, double val) { Get().SetConfig(name, val); }
+}
+
+namespace FitPar {
+std::string GetDataBase() { return GeneralUtils::GetTopLevelDir() + "/data/"; };
+nuisconfig &Config() { return Config::Get(); };
+}
+
+nuisconfig *nuisconfig::m_nuisconfigInstance = NULL;
+nuisconfig &nuisconfig::GetConfig(void) {
+  if (!m_nuisconfigInstance) m_nuisconfigInstance = new nuisconfig;
+  return *m_nuisconfigInstance;
+};
+
+// Main Class Definition
+nuisconfig::nuisconfig() {
+  // Load default Parameters
+  std::string filename =
+      (GeneralUtils::GetTopLevelDir() + "/parameters/config.xml");
+  std::cout << "[ NUISANCE ]: Loading DEFAULT settings from : " << filename;
+
+  // Create XML Engine
+  fXML = new TXMLEngine;
+  fXML->SetSkipComments(true);
+
+  // Load in documents
+  fXMLDocs.push_back(fXML->ParseFile(filename.c_str(), 1000000));
+  if (!fXMLDocs[0]) {
+    THROW("Cannot Read Parameters File!");
+  }
+
+  // Setup Main XML Node to be the first file read
+  fMainNode = fXML->DocGetRootElement(fXMLDocs[0]);
+
+  // Print result
+  std::cout << " -> DONE." << std::endl;
+}
+
+nuisconfig::~nuisconfig() {
+  // Should really delete XML objects here but we don't
+}
+
+void nuisconfig::LoadSettings(std::string const &filename,
+                              std::string const &state) {
+  // Open file and see if its XML
+  std::cout << "[ NUISANCE ]: Trying to parse file : " << filename;
+  StopTalking();
+  XMLDocPointer_t readdoc = fXML->ParseFile(filename.c_str(), 1000000);
+  StartTalking();
+
+  // If it is parse it as a nice XML config file
+  if (readdoc) {
+    std::cout << " -> Found XML file." << std::endl;
+    LoadXMLSettings(filename, state);
+
+    // Otherwise its an old simple card file
+  } else {
+    std::cout << " -> Assuming its a simple card file." << std::endl;
+    LoadCardSettings(filename, state);
+  }
+}
+
+void nuisconfig::LoadXMLSettings(std::string const &filename,
+                                 std::string const &state) {
+  std::cout << "[ NUISANCE ]: Loading XML settings from : " << filename
+            << std::endl;
+
+  // Add new file to xml docs list
+  fXMLDocs.push_back(fXML->ParseFile(filename.c_str(), 1000000));
+
+  if (!fXMLDocs.back()) {
+    THROW("Failed to read: " << filename);
+  }
+
+  // Loop over children and add
+  XMLNodePointer_t child =
+      fXML->GetChild(fXML->DocGetRootElement(fXMLDocs.back()));
+
+  // // Here we manually load all the children from the card file into our root
+  // node
+  if (!child) {
+    THROW("CANNOT Find child inside settings file!");
+  }
+
+  while (child) {
+    // SPECIAL CONFIG CASE
+    // If its a config node, then remove previous attributes, overriding old
+    // value
+    if (!std::string(fXML->GetNodeName(child)).compare("config")) {
+      // Loop over attribues
+      XMLAttrPointer_t attr1 = fXML->GetFirstAttr(child);
+      while (attr1) {
+        // If a valid attribute name is given then compare
+        if (!GetConfigS(fXML->GetAttrName(attr1)).empty()) {
+          // Get full list of present configs
+          std::vector<XMLNodePointer_t> confignodes = GetNodes("config");
+
+          // Loop over present configs and compare
+          for (size_t i = 0; i < confignodes.size(); i++) {
+            // If we already have this config, free the old attribute
+            if (fXML->HasAttr(confignodes[i], fXML->GetAttrName(attr1))) {
+              fXML->FreeAttr(confignodes[i], fXML->GetAttrName(attr1));
+              break;
+            }
+          }
+        }
+
+        // Move onto next config attribute
+        attr1 = fXML->GetNextAttr(attr1);
+      }
+    }
+
+    TString nodeStr;
+
+    fXML->SaveSingleNode(child, &nodeStr);
+
+    XMLNodePointer_t copyNode = fXML->ReadSingleNode(nodeStr.Data());
+
+    // Add this child to the main config list
+    fXML->AddChild(fMainNode, copyNode);
+
+    // Get Next Child
+    child = fXML->GetNext(child);
+  }
+  std::cout << " -> DONE." << std::endl;
+}
+
+void nuisconfig::LoadCardSettings(std::string const &filename,
+                                  std::string const &state) {
+  std::cout << "[ NUISANCE ]: Loading simple config from : " << filename;
+
+  // Build XML Config from the card file by parsing each line
+  std::vector<std::string> cardlines =
+      GeneralUtils::ParseFileToStr(filename, "\n");
+  int linecount = 0;
+
+  // Loop over all input lines
+  for (std::vector<std::string>::iterator iter = cardlines.begin();
+       iter != cardlines.end(); iter++) {
+    std::string line = (*iter);
+    linecount++;
+
+    // Skip Comments
+    if (line.empty()) continue;
+    if (line.c_str()[0] == '#') continue;
+
+    // Parse whitespace
+    std::vector<std::string> strvct = GeneralUtils::ParseToStr(line, " ");
+    if (strvct.empty()) continue;
+
+    // Get Identifier
+    std::string id = strvct[0];
+
+    // Build backwards compatible xml configs
+
+    // Sample structure
+    if (!id.compare("sample")) {
+      CreateSampleNodeFromLine(line);
+    }
+
+    // Any parameter structure
+    if (id.find("_parameter") != std::string::npos) {
+      CreateParameterNodeFromLine(line);
+    }
+
+    // Any covar structure
+    if (!id.compare("covar") || !id.compare("pull") || !id.compare("throw")) {
+      CreatePullNodeFromLine(line);
+    }
+
+    // Any config structure
+    if (!id.compare("config")) {
+      CreateOldConfigNodeFromLine(line);
+    }
+  }
+  std::cout << " -> DONE." << std::endl;
+}
+
+XMLNodePointer_t nuisconfig::CreateSampleNodeFromLine(std::string const &line) {
+  // Create new node entry
+  XMLNodePointer_t samplenode = CreateNode("sample");
+
+  // Parse line
+  std::vector<std::string> strvct = GeneralUtils::ParseToStr(line, " ");
+
+  // Add line elements to the node
+  // name input type norm
+  if (strvct.size() > 1) Set(samplenode, "name", strvct[1]);
+  if (strvct.size() > 2) Set(samplenode, "input", strvct[2]);
+  if (strvct.size() > 3) Set(samplenode, "type", strvct[3]);
+  if (strvct.size() > 4) Set(samplenode, "norm", strvct[4]);
+
+  return samplenode;
+}
+
+XMLNodePointer_t nuisconfig::CreateParameterNodeFromLine(
+    std::string const &line) {
+  // Create new node entry
+  XMLNodePointer_t parnode = CreateNode("parameter");
+
+  // Parse line
+  std::vector<std::string> strvct = GeneralUtils::ParseToStr(line, " ");
+
+  // Add line elements to the node
+  // type name nominal [low] [high] [step] state
+  if (strvct.size() > 0) Set(parnode, "type", strvct[0]);
+  if (strvct.size() > 1) Set(parnode, "name", strvct[1]);
+  if (strvct.size() > 2) Set(parnode, "nominal", strvct[2]);
+
+  // If free structure
+  if (strvct.size() == 7) {
+    Set(parnode, "low", strvct[3]);
+    Set(parnode, "high", strvct[4]);
+    Set(parnode, "step", strvct[5]);
+    Set(parnode, "state", strvct[6]);
+
+    // Fixed param structure
+  } else if (strvct.size() == 3) {
+    Set(parnode, "state", "FIX");
+  } else if (strvct.size() == 4) {
+    Set(parnode, "state", strvct[3]);
+  }
+
+  return parnode;
+}
+
+XMLNodePointer_t nuisconfig::CreatePullNodeFromLine(std::string const &line) {
+  // Create new node entry
+  XMLNodePointer_t parnode = CreateNode("covar");
+
+  // Parse line
+  std::vector<std::string> strvct = GeneralUtils::ParseToStr(line, " ");
+
+  // Add line elements to the node
+  // name input type
+  if (strvct.size() > 1) Set(parnode, "name", strvct[1]);
+  if (strvct.size() > 2) Set(parnode, "input", strvct[2]);
+  if (strvct.size() > 3) Set(parnode, "type", strvct[3]);
+
+  return parnode;
+}
+
+XMLNodePointer_t nuisconfig::CreateOldConfigNodeFromLine(
+    std::string const &line) {
+  // Create new node entry
+  XMLNodePointer_t confignode = CreateNode("config");
+
+  // Parse line
+  std::vector<std::string> strvct = GeneralUtils::ParseToStr(line, " ");
+
+  // Add line elements to the node
+  // name value
+  if (strvct.size() > 2) Set(confignode, strvct[1], strvct[2]);
+
+  return confignode;
+}
+
+void nuisconfig::FinaliseSettings(std::string const &name) {
+  std::cout << "[ NUISANCE ]: Finalising run settings";
+
+  WriteSettings(name);
+
+  // Save full config to file
+  RemoveEmptyNodes();
+  RemoveIdenticalNodes();
+
+  std::cout << " -> DONE." << std::endl;
+}
+
+void nuisconfig::WriteSettings(std::string const &outputname) {
+  // Create a New XML Doc
+  XMLDocPointer_t newxmldoc = fXML->NewDoc();
+  fXML->DocSetRootElement(newxmldoc, fMainNode);
+
+  // Save document to file
+  if (GetConfigB("SaveParsedXMLFile")) {
+    fXML->SaveDoc(newxmldoc, outputname.c_str());
+  }
+}
+
+void nuisconfig::PrintXML(XMLNodePointer_t node, int indent) {
+  std::stringstream ss("");
+  for (int i = 0; i < indent; ++i) {
+    ss << " ";
+  }
+
+  std::cout << ss.str() << "<" << fXML->GetNodeName(node) << std::flush;
+
+  XMLAttrPointer_t attr = fXML->GetFirstAttr(node);
+  while (attr) {
+    std::cout << " " << fXML->GetAttrName(attr) << "=\""
+              << fXML->GetAttrValue(attr) << "\"" << std::flush;
+    attr = fXML->GetNextAttr(attr);
+  }
+  if (!fXML->GetChild(node)) {
+    std::cout << " />" << std::endl;
+    return;
+  }
+  std::cout << " >" << std::endl;
+
+  XMLNodePointer_t child = fXML->GetChild(node);
+  while (child) {
+    PrintXML(child, indent + 1);
+    child = fXML->GetNext(child);
+  }
+
+  std::cout << ss.str() << "</" << fXML->GetNodeName(node) << ">" << std::endl;
+}
+
+XMLNodePointer_t nuisconfig::CreateNode(std::string const &name) {
+  return fXML->NewChild(fMainNode, 0, name.c_str());
+}
+
+XMLNodePointer_t nuisconfig::CreateNode(XMLNodePointer_t node,
+                                        std::string const &name) {
+  return fXML->NewChild(node, 0, name.c_str());
+}
+
+XMLNodePointer_t nuisconfig::GetNode(XMLNodePointer_t node,
+                                     std::string const &type) {
+  /// Loop over all children
+  XMLNodePointer_t child = fXML->GetChild(node);
+  while (child != 0) {
+    /// Get nodes for given type (if type empty return all)
+    if (std::string(fXML->GetNodeName(child)) == type.c_str() or type.empty()) {
+      return child;
+    }
+
+    // Next child
+    child = fXML->GetNext(child);
+  }
+
+  // Child not found
+  return 0;
+}
+
+void nuisconfig::RemoveEmptyNodes() {
+  std::vector<XMLNodePointer_t> nodelist = Config::Get().GetNodes();
+  for (size_t i = 0; i < nodelist.size(); i++) {
+    if (fXML->IsEmptyNode(nodelist[i])) {
+      RemoveNode(nodelist[i]);
+    }
+  }
+}
+
+void nuisconfig::RemoveIdenticalNodes() {
+  std::vector<XMLNodePointer_t> removed;
+
+  // Loop over all nodes and check for identical nodes
+  std::vector<XMLNodePointer_t> nodelist = Config::Get().GetNodes();
+  for (size_t i = 0; i < nodelist.size(); i++) {
+    for (size_t j = 0; j < nodelist.size(); j++) {
+      if (i == j) continue;
+
+      XMLNodePointer_t node1 = nodelist[i];
+      XMLNodePointer_t node2 = nodelist[j];
+
+      // Check node already removed.
+      if (std::find(removed.begin(), removed.end(), node1) != removed.end()) {
+        continue;
+      }
+      if (std::find(removed.begin(), removed.end(), node2) != removed.end()) {
+        continue;
+      }
+
+      // Check matching
+      if (!MatchingNodes(node1, node2)) {
+        continue;
+      }
+
+      if (std::string(fXML->GetNodeName(node1)).compare("config") and
+          fXML->IsEmptyNode(node1)) {
+        // Matching so print out warning
+        std::cout << "Matching nodes given! Removing node1!" << std::endl
+                  << "Node 1" << std::endl;
+        PrintNode(node1);
+
+        std::cout << "Node 2" << std::endl;
+        PrintNode(node2);
+      }
+
+      // Remove node
+      removed.push_back(node1);
+    }
+  }
+
+  // Now go through and remove this node.
+  for (size_t i = 0; i < removed.size(); i++) {
+    RemoveNode(removed.at(i));
+  }
+
+  return;
+}
+
+void nuisconfig::RemoveNode(XMLNodePointer_t node) {
+  fXML->FreeAllAttr(node);
+  fXML->CleanNode(node);
+  fXML->FreeNode(node);
+  fXML->UnlinkNode(node);
+}
+
+void nuisconfig::PrintNode(XMLNodePointer_t node) {
+  // Print Node Name
+  std::cout << fXML->GetNodeName(node) << std::endl;
+
+  // Loop and print all attributes
+  XMLAttrPointer_t attr = fXML->GetFirstAttr(node);
+  while (attr != 0) {
+    std::cout << " -> " << fXML->GetAttrName(attr) << " : "
+              << fXML->GetAttrValue(attr) << std::endl;
+    attr = fXML->GetNextAttr(attr);
+  }
+}
+
+bool nuisconfig::MatchingNodes(XMLNodePointer_t node1, XMLNodePointer_t node2) {
+  bool matching = true;
+  XMLAttrPointer_t attr = fXML->GetFirstAttr(node1);
+  while (attr != 0) {
+    if (GetS(node2, fXML->GetAttrName(attr)) != fXML->GetAttrValue(attr))
+      matching = false;
+    attr = fXML->GetNextAttr(attr);
+  }
+  return matching;
+}
+
+XMLNodePointer_t nuisconfig::GetNode(std::string const &type) {
+  return GetNode(fMainNode, type);
+}
+
+std::vector<XMLNodePointer_t> nuisconfig::GetNodes(XMLNodePointer_t node,
+                                                   std::string const &type) {
+  // Create new vector for nodes
+  std::vector<XMLNodePointer_t> nodelist;
+
+  /// Loop over all children
+  XMLNodePointer_t child = fXML->GetChild(node);
+  while (child != 0) {
+    /// Get nodes for given type (if type empty return all)
+    if (std::string(fXML->GetNodeName(child)) == type.c_str() or type.empty()) {
+      nodelist.push_back(child);
+    }
+
+    // Next child
+    child = fXML->GetNext(child);
+  }
+
+  // return list
+  return nodelist;
+}
+
+std::vector<XMLNodePointer_t> nuisconfig::GetNodes(std::string const &type) {
+  return GetNodes(fMainNode, type);
+}
+
+void nuisconfig::Set(XMLNodePointer_t node, std::string const &name,
+                     std::string const &val) {
+  // Remove and re-add attribute
+  if (fXML->HasAttr(node, name.c_str())) {
+    fXML->FreeAttr(node, name.c_str());
+  }
+
+  fXML->NewAttr(node, 0, name.c_str(), val.c_str());
+}
+void nuisconfig::Set(XMLNodePointer_t node, std::string const &name,
+                     char const *val) {
+  Set(node, name, std::string(val));
+}
+
+void nuisconfig::Set(XMLNodePointer_t node, std::string const &name, bool val) {
+  Set(node, name, GeneralUtils::BoolToStr(val));
+}
+
+void nuisconfig::Set(XMLNodePointer_t node, std::string const &name, int val) {
+  Set(node, name, GeneralUtils::IntToStr(val));
+}
+
+void nuisconfig::Set(XMLNodePointer_t node, std::string const &name,
+                     float val) {
+  Set(node, name, GeneralUtils::DblToStr(val));
+}
+
+void nuisconfig::Set(XMLNodePointer_t node, std::string const &name,
+                     double val) {
+  Set(node, name, GeneralUtils::DblToStr(val));
+}
+
+void nuisconfig::SetS(XMLNodePointer_t node, std::string const &name,
+                      std::string const &val) {
+  Set(node, name, val);
+}
+
+void nuisconfig::SetB(XMLNodePointer_t node, std::string const &name,
+                      bool val) {
+  Set(node, name, GeneralUtils::BoolToStr(val));
+}
+
+void nuisconfig::SetI(XMLNodePointer_t node, std::string const &name, int val) {
+  Set(node, name, GeneralUtils::IntToStr(val));
+}
+
+void nuisconfig::SetF(XMLNodePointer_t node, std::string const &name,
+                      float val) {
+  Set(node, name, GeneralUtils::DblToStr(val));
+}
+
+void nuisconfig::SetD(XMLNodePointer_t node, std::string const &name,
+                      double val) {
+  Set(node, name, GeneralUtils::DblToStr(val));
+}
+
+bool nuisconfig::Has(XMLNodePointer_t node, std::string const &name) {
+  // If node empty return empty
+  if (node == 0) return false;
+
+  // Search attributes
+  XMLAttrPointer_t attr = fXML->GetFirstAttr(node);
+  bool found = false;
+
+  // Loop over all attributes
+  while (attr != 0) {
+    // Find value of correct name
+    if (std::string(fXML->GetAttrName(attr)) == name.c_str()) {
+      found = true;
+      break;
+    }
+
+    // Next Attribute
+    attr = fXML->GetNextAttr(attr);
+  }
+
+  return found;
+}
+
+std::string nuisconfig::Get(XMLNodePointer_t node, std::string const &name) {
+  // If node empty return empty
+  if (node == 0) return "";
+
+  // Get Attribute from child with name
+  XMLAttrPointer_t attr = fXML->GetFirstAttr(node);
+  std::string temp = "";
+
+  // Loop over all attributes
+  while (attr != 0) {
+    // If valid match then save
+    if (std::string(fXML->GetAttrName(attr)) == name.c_str()) {
+      temp = fXML->GetAttrValue(attr);
+    }
+
+    // Next Attribute
+    attr = fXML->GetNextAttr(attr);
+  }
+
+  return temp;
+}
+
+std::string nuisconfig::GetS(XMLNodePointer_t node, std::string const &name) {
+  return Get(node, name);
+}
+
+bool nuisconfig::GetB(XMLNodePointer_t node, std::string const &name) {
+  std::string tempattr = Get(node, name);
+  return GeneralUtils::StrToBool(tempattr);
+}
+
+int nuisconfig::GetI(XMLNodePointer_t node, std::string const &name) {
+  std::string tempattr = Get(node, name);
+  return GeneralUtils::StrToInt(tempattr);
+}
+
+float nuisconfig::GetF(XMLNodePointer_t node, std::string const &name) {
+  std::string tempattr = Get(node, name);
+  return GeneralUtils::StrToDbl(tempattr);
+}
+
+double nuisconfig::GetD(XMLNodePointer_t node, std::string const &name) {
+  std::string tempattr = Get(node, name);
+  return GeneralUtils::StrToDbl(tempattr);
+}
+
+std::vector<std::string> nuisconfig::GetVS(XMLNodePointer_t node,
+                                           std::string const &name,
+                                           const char *del) {
+  std::string tempattr = Get(node, name);
+  return GeneralUtils::ParseToStr(tempattr, del);
+}
+
+// std::vector<int> nuisconfig::GetVB(XMLNodePointer_t node,
+//                                    std::string name,
+//                                    const char* del) {
+//   std::string tempattr = Get(node, name);
+//   return GeneralUtils::ParseToBool(tempattr, del);
+// }
+
+std::vector<int> nuisconfig::GetVI(XMLNodePointer_t node,
+                                   std::string const &name, const char *del) {
+  std::string tempattr = Get(node, name);
+  return GeneralUtils::ParseToInt(tempattr, del);
+}
+
+// std::vector<int> nuisconfig::GetVF(XMLNodePointer_t node,
+//                                    std::string name,
+//                                    const char* del) {
+//   std::string tempattr = Get(node, name);
+//   return GeneralUtils::ParseToDouble(tempattr, del);
+// }
+
+std::vector<double> nuisconfig::GetVD(XMLNodePointer_t node,
+                                      std::string const &name,
+                                      char const *del) {
+  std::string tempattr = Get(node, name);
+  return GeneralUtils::ParseToDbl(tempattr, del);
+}
+
+std::vector<std::string> nuisconfig::GetAllKeysForNode(XMLNodePointer_t node) {
+  bool matching = true;
+  XMLAttrPointer_t attr = fXML->GetFirstAttr(node);
+  std::vector<std::string> keys;
+  while (attr != 0) {
+    if (!std::string(fXML->GetAttrName(attr)).empty()) {
+      keys.push_back(std::string(fXML->GetAttrName(attr)));
+    }
+    attr = fXML->GetNextAttr(attr);
+  }
+
+  return keys;
+}
+
+XMLNodePointer_t nuisconfig::GetConfigNode(std::string const &name) {
+  // Loop over children and look for name
+  XMLNodePointer_t child = fXML->GetChild(fMainNode);
+  while (child != 0) {
+    // Select only config parameters
+    if (!std::string(fXML->GetNodeName(child)).compare("config")) {
+      // Loop over config attributes and search for name
+      XMLAttrPointer_t attr = fXML->GetFirstAttr(child);
+      while (attr != 0) {
+        // Save name value
+        if (std::string(fXML->GetAttrName(attr)) == name.c_str()) {
+          return child;
+        }
+
+        // Get Next Attribute
+        attr = fXML->GetNextAttr(attr);
+      }
+    }
+
+    // Next Child
+    child = fXML->GetNext(child);
+  }
+
+  return 0;
+}
+
+void nuisconfig::SetConfig(std::string const &name, std::string const &val) {
+  XMLNodePointer_t node = GetConfigNode(name);
+  if (!node) node = CreateNode("config");
+  Set(node, name, val);
+}
+void nuisconfig::SetConfig(std::string const &name, char const *val) {
+  SetConfig(name, std::string(val));
+}
+
+void nuisconfig::SetConfig(std::string const &name, bool val) {
+  XMLNodePointer_t node = GetConfigNode(name);
+  if (!node) node = CreateNode("config");
+  Set(node, name, val);
+}
+
+void nuisconfig::SetConfig(std::string const &name, int val) {
+  XMLNodePointer_t node = GetConfigNode(name);
+  if (!node) node = CreateNode("config");
+  Set(node, name, val);
+}
+
+void nuisconfig::SetConfig(std::string const &name, float val) {
+  XMLNodePointer_t node = GetConfigNode(name);
+  if (!node) node = CreateNode("config");
+  Set(node, name, val);
+}
+
+void nuisconfig::SetConfig(std::string const &name, double val) {
+  XMLNodePointer_t node = GetConfigNode(name);
+  if (!node) node = CreateNode("config");
+  Set(node, name, val);
+}
+
+void nuisconfig::OverrideConfig(std::string const &conf) {
+  std::vector<std::string> opts = GeneralUtils::ParseToStr(conf, "=");
+  SetConfig(opts[0], opts[1]);
+}
+
+std::string nuisconfig::GetConfig(std::string const &name) {
+  XMLNodePointer_t node = GetConfigNode(name);
+  if (!node) return "";
+
+  XMLAttrPointer_t attr = fXML->GetFirstAttr(node);
+  std::string temp = "";
+
+  // Loop config attributes
+  while (attr != 0) {
+    // Find match
+    if (std::string(fXML->GetAttrName(attr)) == name.c_str()) {
+      temp = fXML->GetAttrValue(attr);
+    }
+
+    // Get Next Attribute
+    attr = fXML->GetNextAttr(attr);
+  }
+  return temp;
+}
+
+bool nuisconfig::HasConfig(std::string const &name) {
+  return bool(GetConfigNode(name));
+}
+
+std::string nuisconfig::GetConfigS(std::string const &name) {
+  return GetConfig(name);
+}
+
+bool nuisconfig::GetConfigB(std::string const &name) {
+  std::string pars = GetConfig(name);
+  return GeneralUtils::StrToBool(pars);
+}
+
+int nuisconfig::GetConfigI(std::string const &name) {
+  std::string pars = GetConfig(name);
+  return GeneralUtils::StrToInt(pars);
+}
+
+float nuisconfig::GetConfigF(std::string const &name) {
+  std::string pars = GetConfig(name);
+  return GeneralUtils::StrToDbl(pars);
+}
+
+double nuisconfig::GetConfigD(std::string const &name) {
+  std::string pars = GetConfig(name);
+  return GeneralUtils::StrToDbl(pars);
+}
+
+std::string nuisconfig::GetParDIR(std::string const &parName) {
+  std::string outstr = this->GetParS(parName);
+
+  // Make replacements in the string
+  const int nfiletypes = 2;
+  const std::string filetypes[nfiletypes] = {"@data", "@nuisance"};
+  std::string filerepl[nfiletypes] = {FitPar::GetDataBase(),
+                                      FitPar::GetDataBase() + "/../"};
+
+  for (int i = 0; i < nfiletypes; i++) {
+    std::string findstring = filetypes[i];
+    std::string replstring = filerepl[i];
+    if (outstr.find(findstring) != std::string::npos) {
+      outstr.replace(outstr.find(findstring), findstring.size(), filerepl[i]);
+      break;
+    }
+  }
+
+  return outstr;
+};
diff --git a/src/Config/NuisConfig.h b/src/Config/NuisConfig.h
new file mode 100644
index 0000000..d95795e
--- /dev/null
+++ b/src/Config/NuisConfig.h
@@ -0,0 +1,193 @@
+// Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret
+
+/*******************************************************************************
+*    This file is part of NUISANCE.
+*
+*    NUISANCE is free software: you can redistribute it and/or modify
+*    it under the terms of the GNU General Public License as published by
+*    the Free Software Foundation, either version 3 of the License, or
+*    (at your option) any later version.
+*
+*    NUISANCE is distributed in the hope that it will be useful,
+*    but WITHOUT ANY WARRANTY; without even the implied warranty of
+*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*    GNU General Public License for more details.
+*
+*    You should have received a copy of the GNU General Public License
+*    along with NUISANCE.  If not, see <http://www.gnu.org/licenses/>.
+*******************************************************************************/
+#ifndef NUISCONFIG_H_SEEN
+#define NUISCONFIG_H_SEEN
+
+#include <algorithm>
+#include <map>
+
+#include "TFile.h"
+#include "TXMLEngine.h"
+
+/// NUISANCE Global Settings Class
+class nuisconfig {
+ public:
+  /// Singleton Get Function
+  static nuisconfig &GetConfig(void);
+
+  /// Constructor \n
+  /// Loads defaults from $NUISANCE/parameters/config.xml
+  nuisconfig();
+
+  /// Desctructor \n Frees XML Docs
+  virtual ~nuisconfig();
+
+  /// Adds a new configuration list
+  void LoadSettings(std::string const &filename, std::string const &state);
+
+  /// Adds a new config from new xml file format
+  void LoadXMLSettings(std::string const &filename,
+                       std::string const &state = "");
+
+  /// Adds a new config from old card file format
+  void LoadCardSettings(std::string const &filename, std::string const &state);
+
+  /// Save the config to file
+  void WriteSettings(std::string const &filename);
+
+  void PrintXML(XMLNodePointer_t node, int indent = 0);
+
+  XMLNodePointer_t CreateNode(std::string const &name);
+  XMLNodePointer_t CreateNode(XMLNodePointer_t node, std::string const &name);
+
+  void RemoveEmptyNodes();
+  void RemoveIdenticalNodes();
+
+  bool MatchingNodes(XMLNodePointer_t node1, XMLNodePointer_t node2);
+  void PrintNode(XMLNodePointer_t node);
+  void RemoveNode(XMLNodePointer_t node);
+
+  void FinaliseSettings(std::string const &name);
+
+  XMLNodePointer_t CreateSampleNodeFromLine(std::string const &line);
+  XMLNodePointer_t CreateParameterNodeFromLine(std::string const &line);
+  XMLNodePointer_t CreatePullNodeFromLine(std::string const &line);
+  XMLNodePointer_t CreateOldConfigNodeFromLine(std::string const &line);
+
+  // Get List of child nodes of nuisance element
+  std::vector<XMLNodePointer_t> GetNodes(std::string const &type = "");
+  std::vector<XMLNodePointer_t> GetNodes(XMLNodePointer_t node,
+                                         std::string const &type = "");
+  XMLNodePointer_t GetNode(std::string const &type = "");
+  XMLNodePointer_t GetNode(XMLNodePointer_t node, std::string const &type = "");
+
+  std::vector<std::string> GetAllKeysForNode(XMLNodePointer_t node);
+
+  std::string GetElementName(XMLNodePointer_t node) {
+    return fXML->GetNodeName(node);
+  }
+
+  /// Check node has key name
+  bool Has(XMLNodePointer_t node, std::string const &name);
+
+  /// Add attribute to node
+  void Set(XMLNodePointer_t node, std::string const &name,
+           std::string const &val);
+  void Set(XMLNodePointer_t node, std::string const &name,
+           char const *val);
+  void Set(XMLNodePointer_t node, std::string const &name, bool val);
+  void Set(XMLNodePointer_t node, std::string const &name, int val);
+  void Set(XMLNodePointer_t node, std::string const &name, float val);
+  void Set(XMLNodePointer_t node, std::string const &name, double val);
+
+  void SetS(XMLNodePointer_t node, std::string const &name,
+            std::string const &val);
+  void SetB(XMLNodePointer_t node, std::string const &name, bool val);
+  void SetI(XMLNodePointer_t node, std::string const &name, int val);
+  void SetF(XMLNodePointer_t node, std::string const &name, float val);
+  void SetD(XMLNodePointer_t node, std::string const &name, double val);
+
+  /// Get String from a given node
+  std::string Get(XMLNodePointer_t node, std::string const &name);
+  std::string GetS(XMLNodePointer_t node, std::string const &name);
+  bool GetB(XMLNodePointer_t node, std::string const &name);
+  int GetI(XMLNodePointer_t node, std::string const &name);
+  float GetF(XMLNodePointer_t node, std::string const &name);
+  double GetD(XMLNodePointer_t node, std::string const &name);
+
+  // Get values parsed into a vector
+  std::vector<std::string> GetVS(XMLNodePointer_t node, std::string const &name,
+                                 const char *del);
+  std::vector<int> GetVI(XMLNodePointer_t node, std::string const &name,
+                         const char *del);
+  std::vector<double> GetVD(XMLNodePointer_t node, std::string const &name,
+                            const char *del);
+
+  /// Set an already set config value to something else
+  void OverrideConfig(std::string const &conf);
+
+  /// Return the node of a given config parameter
+  XMLNodePointer_t GetConfigNode(std::string const &name);
+
+  void SetConfig(std::string const &name, std::string const &val);
+  void SetConfig(std::string const &name, char const *val);
+  void SetConfig(std::string const &name, bool val);
+  void SetConfig(std::string const &name, int val);
+  void SetConfig(std::string const &name, float val);
+  void SetConfig(std::string const &name, double val);
+
+  void SetParS(std::string const &name, std::string const &val);
+  void SetParB(std::string const &name, bool val);
+  void SetParI(std::string const &name, int val);
+  void SetParD(std::string const &name, double val);
+
+  std::string GetConfig(std::string const &name);
+  bool HasConfig(std::string const &name);
+  std::string GetConfigS(std::string const &name);
+  bool GetConfigB(std::string const &name);
+  int GetConfigI(std::string const &name);
+  float GetConfigF(std::string const &name);
+  double GetConfigD(std::string const &name);
+
+  std::string GetPar(std::string const &name) { return GetConfig(name); };
+  std::string GetParS(std::string const &name) { return GetConfigS(name); };
+  bool GetParB(std::string const &name) { return GetConfigB(name); };
+  int GetParI(std::string const &name) { return GetConfigI(name); };
+  float GetParF(std::string const &name) { return GetConfigF(name); };
+  double GetParD(std::string const &name) { return GetConfigD(name); };
+
+  std::string GetParDIR(std::string const &parName);
+
+  TFile *out;
+
+ private:
+  XMLNodePointer_t fMainNode;             ///< Main XML Parent Node
+  TXMLEngine *fXML;                       ///< ROOT XML Engine
+  std::vector<XMLDocPointer_t> fXMLDocs;  ///< List of all XML document inputs
+
+ protected:
+  static nuisconfig *m_nuisconfigInstance;
+};
+
+namespace Config {
+nuisconfig &Get();
+
+std::string GetPar(std::string const &name);
+bool HasPar(std::string const &name);
+std::string GetParS(std::string const &name);
+bool GetParB(std::string const &name);
+int GetParI(std::string const &name);
+float GetParF(std::string const &name);
+double GetParD(std::string const &name);
+
+void SetPar(std::string const &name, std::string const &val);
+void SetPar(std::string const &name, char const *val);
+void SetPar(std::string const &name, bool val);
+void SetPar(std::string const &name, int val);
+void SetPar(std::string const &name, float val);
+void SetPar(std::string const &name, double val);
+}
+
+namespace FitPar {
+nuisconfig &Config();
+std::string GetDataBase();
+}
+
+/*! @} */
+#endif
diff --git a/src/Config/NuisKey.cxx b/src/Config/NuisKey.cxx
new file mode 100644
index 0000000..75b90ff
--- /dev/null
+++ b/src/Config/NuisKey.cxx
@@ -0,0 +1,140 @@
+#include "NuisKey.h"
+#include "GeneralUtils.h"
+#include "NuisConfig.h"
+
+nuiskey::nuiskey(std::string const &name) {
+  fNode = Config::Get().CreateNode(name);
+}
+
+std::string nuiskey::GetS(std::string const &name) {
+  return Config::Get().GetS(fNode, name);
+};
+
+void nuiskey::Print() { Config::Get().PrintXML(fNode); }
+
+int nuiskey::GetI(std::string const &name) {
+  return Config::Get().GetI(fNode, name);
+};
+
+double nuiskey::GetD(std::string const &name) {
+  return Config::Get().GetD(fNode, name);
+};
+
+bool nuiskey::GetB(std::string const &name) {
+  return Config::Get().GetB(fNode, name);
+};
+
+void nuiskey::Set(std::string const &name, std::string const &newval) {
+  Config::Get().SetS(fNode, name, newval);
+}
+void nuiskey::Set(std::string const &name, int newval) {
+  Config::Get().SetI(fNode, name, newval);
+}
+void nuiskey::Set(std::string const &name, double newval) {
+  Config::Get().SetD(fNode, name, newval);
+}
+void nuiskey::Set(std::string const &name, bool newval) {
+  Config::Get().SetB(fNode, name, newval);
+}
+
+void nuiskey::SetS(std::string const &name, std::string const &newval) {
+  Config::Get().SetS(fNode, name, newval);
+}
+void nuiskey::Set(std::string const &name, char const *newval) {
+  Config::Get().SetS(fNode, name, newval);
+}
+void nuiskey::SetI(std::string const &name, int newval) {
+  Config::Get().SetI(fNode, name, newval);
+}
+void nuiskey::SetD(std::string const &name, double newval) {
+  Config::Get().SetD(fNode, name, newval);
+}
+void nuiskey::SetB(std::string const &name, bool newval) {
+  Config::Get().SetB(fNode, name, newval);
+}
+
+std::vector<std::string> nuiskey::GetAllKeys() {
+  return Config::Get().GetAllKeysForNode(fNode);
+}
+
+std::vector<nuiskey> nuiskey::GetListOfChildNodes(std::string const &filter) {
+  std::vector<XMLNodePointer_t> nodelist =
+      Config::Get().GetNodes(fNode, filter);
+  std::vector<nuiskey> keylist;
+  for (size_t n_it = 0; n_it < nodelist.size(); ++n_it) {
+    keylist.push_back(nuiskey(nodelist[n_it]));
+  }
+  return keylist;
+}
+
+std::vector<std::string> nuiskey::GetVS(std::string const &name,
+                                        const char *del) {
+  return Config::Get().GetVS(fNode, name, del);
+};
+
+std::vector<int> nuiskey::GetVI(std::string const &name, const char *del) {
+  return Config::Get().GetVI(fNode, name, del);
+};
+
+std::vector<double> nuiskey::GetVD(std::string const &name, const char *del) {
+  return Config::Get().GetVD(fNode, name, del);
+};
+
+std::vector<nuiskey> Config::QueryKeys(std::string const &type,
+                                       std::string const &test1) {
+  // Get Vector of nodes
+  std::vector<XMLNodePointer_t> nodelist = Config::Get().GetNodes(type);
+
+  // Convert List into a key list for easier access
+  std::vector<nuiskey> keylist;
+  for (std::vector<XMLNodePointer_t>::const_iterator iter = nodelist.begin();
+       iter != nodelist.end(); iter++) {
+    // Create new key
+    nuiskey newkey = nuiskey(*iter);
+
+    // Add test1
+    if (!test1.empty()) {
+      std::vector<std::string> testvect = GeneralUtils::ParseToStr(test1, "=");
+      if (testvect.size() < 2) continue;
+      if (newkey.GetS(testvect[0]) != testvect[1]) continue;
+    }
+
+    // Save node as nuiskey
+    keylist.push_back(newkey);
+  }
+
+  // Return list of keys
+  return keylist;
+}
+
+nuiskey Config::QueryLastKey(std::string const &type,
+                             std::string const &test1) {
+  // Loop over all for now because I'm lazy...
+  std::vector<nuiskey> allkeys = Config::QueryKeys(type, test1);
+  if (allkeys.size() < 1)
+    return nuiskey();
+  else
+    return allkeys[allkeys.size() - 1];
+}
+
+nuiskey Config::QueryFirstKey(std::string const &type,
+                              std::string const &test1) {
+  // Loop over all for now because I'm lazy...
+  std::vector<nuiskey> allkeys = Config::QueryKeys(type, test1);
+  if (allkeys.size() < 1)
+    return nuiskey();
+  else
+    return allkeys[allkeys.size() - 1];
+}
+
+bool nuiskey::Has(std::string const &name) {
+  return Config::Get().Has(fNode, name);
+}
+
+std::string nuiskey::GetElementName() {
+  return Config::Get().GetElementName(fNode);
+}
+
+nuiskey Config::CreateKey(std::string const &name) {
+  return nuiskey(Config::Get().CreateNode(name));
+}
diff --git a/src/Config/NuisKey.h b/src/Config/NuisKey.h
new file mode 100644
index 0000000..38d3165
--- /dev/null
+++ b/src/Config/NuisKey.h
@@ -0,0 +1,62 @@
+#ifndef NUISKEY_H
+#define NUISKEY_H
+
+#include <algorithm>
+#include <map>
+
+#include "TFile.h"
+#include "TXMLEngine.h"
+
+class nuiskey {
+ public:
+  nuiskey(){};
+
+  nuiskey(XMLNodePointer_t node) { fNode = node; };
+  nuiskey(std::string const &name);
+
+  void Print();
+
+  ~nuiskey(){};
+
+  std::string GetS(std::string const &name);
+  int GetI(std::string const &name);
+  double GetD(std::string const &name);
+  bool GetB(std::string const &name);
+
+  std::vector<std::string> GetVS(std::string const &name, const char *del);
+  std::vector<int> GetVI(std::string const &name, const char *del);
+  std::vector<double> GetVD(std::string const &name, const char *del);
+
+  void SetS(std::string const &name, std::string const &newval);
+  void SetI(std::string const &name, int newval);
+  void SetD(std::string const &name, double newval);
+  void SetB(std::string const &name, bool newval);
+
+  void Set(std::string const &name, std::string const &newval);
+  void Set(std::string const &name, char const *newval);
+  void Set(std::string const &name, int newval);
+  void Set(std::string const &name, double newval);
+  void Set(std::string const &name, bool newval);
+
+  bool Has(std::string const &name);
+
+  std::string GetElementName();
+
+  std::vector<std::string> GetAllKeys();
+
+  std::vector<nuiskey> GetListOfChildNodes(std::string const &filter = "");
+
+  XMLNodePointer_t fNode;  ///< XML Node in Config::Get().fXML for this key
+};
+
+namespace Config {
+
+// Return a vector of keys for use
+std::vector<nuiskey> QueryKeys(std::string const &name,
+                               std::string const &test1 = "");
+nuiskey QueryFirstKey(std::string const &name, std::string const &test1 = "");
+nuiskey QueryLastKey(std::string const &name, std::string const &test1 = "");
+
+nuiskey CreateKey(std::string const &name);
+}
+#endif
diff --git a/src/FCN/JointFCN.cxx b/src/FCN/#JointFCN.cxx#
similarity index 99%
copy from src/FCN/JointFCN.cxx
copy to src/FCN/#JointFCN.cxx#
index dee225c..cc31fe4 100755
--- a/src/FCN/JointFCN.cxx
+++ b/src/FCN/#JointFCN.cxx#
@@ -1,1014 +1,1016 @@
 #include "JointFCN.h"
 #include <stdio.h>
 #include "FitUtils.h"
 
 
 //***************************************************
 JointFCN::JointFCN(TFile* outfile) {
 //***************************************************
 
   fOutputDir = gDirectory;
   if (outfile) FitPar::Config().out = outfile;
 
   std::vector<nuiskey> samplekeys = Config::QueryKeys("sample");
   LoadSamples(samplekeys);
 
   std::vector<nuiskey> covarkeys = Config::QueryKeys("covar");
   LoadPulls(covarkeys);
 
   fCurIter = 0;
   fMCFilled = false;
 
   fIterationTree = false;
   fDialVals = NULL;
   fNDials = 0;
 
   fUsingEventManager = FitPar::Config().GetParB("EventManager");
   fOutputDir->cd();
 }
 
 //***************************************************
 JointFCN::JointFCN(std::vector<nuiskey> samplekeys, TFile* outfile) {
 //***************************************************
 
   fOutputDir = gDirectory;
   if (outfile) FitPar::Config().out = outfile;
 
   LoadSamples(samplekeys);
 
   fCurIter = 0;
   fMCFilled = false;
 
   fOutputDir->cd();
 
   fIterationTree = false;
   fDialVals = NULL;
   fNDials = 0;
 
   fUsingEventManager = FitPar::Config().GetParB("EventManager");
   fOutputDir->cd();
 }
 
 //***************************************************
 JointFCN::~JointFCN() {
   //***************************************************
 
   // Delete Samples
   for (MeasListConstIter iter = fSamples.begin(); iter != fSamples.end();
        iter++) {
     MeasurementBase* exp = *iter;
     delete exp;
   }
 
   for (PullListConstIter iter = fPulls.begin(); iter != fPulls.end(); iter++) {
     ParamPull* pull = *iter;
     delete pull;
   }
 
   // Sort Tree
   if (fIterationTree) DestroyIterationTree();
   if (fDialVals) delete fDialVals;
   if (fSampleLikes) delete fSampleLikes;
 };
 
 //***************************************************
 void JointFCN::CreateIterationTree(std::string name, FitWeight* rw) {
 //***************************************************
 
   LOG(FIT) << " Creating new iteration container! " << std::endl;
   DestroyIterationTree();
   fIterationTreeName = name;
 
   // Add sample likelihoods and ndof
   for (MeasListConstIter iter = fSamples.begin();
        iter != fSamples.end();
        iter++) {
 
     MeasurementBase* exp = *iter;
     std::string name = exp->GetName();
 
     std::string liketag = name + "_likelihood";
     fNameValues.push_back(liketag);
     fCurrentValues.push_back(0.0);
 
     std::string ndoftag = name + "_ndof";
     fNameValues.push_back(ndoftag);
     fCurrentValues.push_back(0.0);
   }
 
   // Add Pull terms
   for (PullListConstIter iter = fPulls.begin();
        iter != fPulls.end(); iter++) {
 
     ParamPull* pull = *iter;
     std::string name = pull->GetName();
 
     std::string liketag = name + "_likelihood";
     fNameValues.push_back(liketag);
     fCurrentValues.push_back(0.0);
 
     std::string ndoftag = name + "_ndof";
     fNameValues.push_back(ndoftag);
     fCurrentValues.push_back(0.0);
   }
 
   // Add Likelihoods
   fNameValues.push_back("total_likelihood");
   fCurrentValues.push_back(0.0);
 
   fNameValues.push_back("total_ndof");
   fCurrentValues.push_back(0.0);
 
-  // Setup Containers
+  // Setup Containers 
   fSampleN     = fSamples.size() + fPulls.size();
   fSampleLikes = new double[fSampleN];
   fSampleNDOF  = new int[fSampleN];
 
   // Add Dials
   std::vector<std::string> dials = rw->GetDialNames();
   for (size_t i = 0; i < dials.size(); i++){
     fNameValues.push_back( dials[i] );
     fCurrentValues.push_back( 0.0 );
   }
   fNDials   = dials.size();
-  fDialVals = new double[fNDials];
+  fDialVals = new double[fNDials];  
 
   // Set IterationTree Flag
   fIterationTree = true;
-
+ 
 }
 
 //***************************************************
 void JointFCN::DestroyIterationTree() {
 //***************************************************
 
   fIterationCount.clear();
   fCurrentValues.clear();
   fNameValues.clear();
   fIterationValues.clear();
 
 }
 
 //***************************************************
 void JointFCN::WriteIterationTree() {
 //***************************************************
   LOG(FIT) << "Writing iteration tree" << std::endl;
 
   // Make a new TTree
   TTree* itree = new TTree(fIterationTreeName.c_str(),
                            fIterationTreeName.c_str());
 
   double* vals = new double[fNameValues.size()];
   int count = 0;
 
   itree->Branch("iteration",&count,"Iteration/I");
   for (int i = 0; i < fNameValues.size(); i++) {
     itree->Branch( fNameValues[i].c_str(),
                    &vals[i],
                    (fNameValues[i] + "/D").c_str() );
   }
 
   // Fill Iterations
   for (size_t i = 0; i < fIterationValues.size(); i++){
     std::vector<double> itervals = fIterationValues[i];
 
     // Fill iteration state
     count = fIterationCount[i];
     for (size_t j = 0; j < itervals.size(); j++){
       vals[j] = itervals[j];
     }
 
     // Save to TTree
     itree->Fill();
   }
 
   // Write to file
+  std::cout << "Writing iteration tree" << std::endl;
   itree->Write();
+  std::cout << "Written iteration tree" << std::endl;
 }
 
 //***************************************************
 void JointFCN::FillIterationTree(FitWeight* rw) {
 //***************************************************
 
   // Loop over samples count
   int count = 0;
   for (int i = 0; i < fSampleN; i++){
     fCurrentValues[count++] = fSampleLikes[i];
     fCurrentValues[count++] = double(fSampleNDOF[i]);
   }
 
   // Fill Totals
   fCurrentValues[count++] = fLikelihood;
   fCurrentValues[count++] = double(fNDOF);
 
   // Loop Over Parameter Counts
   rw->GetAllDials(fDialVals, fNDials);
   for (int i = 0; i < fNDials; i++){
     fCurrentValues[count++] = double(fDialVals[i]);
   }
 
   // Push Back Into Container
   fIterationCount.push_back( fCurIter );
   fIterationValues.push_back(fCurrentValues);
 }
 
 //***************************************************
 double JointFCN::DoEval(const double* x) {
   //***************************************************
 
   // WEIGHT ENGINE
   fDialChanged = FitBase::GetRW()->HasRWDialChanged(x);
   FitBase::GetRW()->UpdateWeightEngine(x);
   if (fDialChanged) {
     FitBase::GetRW()->Reconfigure();
     FitBase::EvtManager().ResetWeightFlags();
   }
   if (LOG_LEVEL(REC)) {
     FitBase::GetRW()->Print();
   }
 
   // SORT SAMPLES
   ReconfigureSamples();
 
   // GET TEST STAT
   fLikelihood = GetLikelihood();
   fNDOF       = GetNDOF();
-
+  
   // PRINT PROGRESS
   LOG(FIT) << "Current Stat (iter. " << this->fCurIter << ") = " << fLikelihood
            << std::endl;
 
   // UPDATE TREE
   if (fIterationTree) FillIterationTree(FitBase::GetRW());
 
   return fLikelihood;
 }
 
 //***************************************************
 int JointFCN::GetNDOF() {
   //***************************************************
 
   int totaldof = 0;
   int count = 0;
 
   // Total number of Free bins in each MC prediction
   for (MeasListConstIter iter = fSamples.begin(); iter != fSamples.end();
        iter++) {
     MeasurementBase* exp = *iter;
     int dof = exp->GetNDOF();
 
     // Save Seperate DOF
     if (fIterationTree) {
       fSampleNDOF[count] = dof;
     }
 
     // Add to total
     totaldof += dof;
     count++;
   }
 
   // Loop over pulls
   for (PullListConstIter iter = fPulls.begin(); iter != fPulls.end(); iter++) {
     ParamPull* pull = *iter;
     double dof = pull->GetLikelihood();
 
     // Save seperate DOF
     if (fIterationTree) {
       fSampleNDOF[count] = dof;
     }
 
     // Add to total
     totaldof += dof;
     count++;
   }
 
   // Set Data Variable
   if (fIterationTree){
   fSampleNDOF[count] = totaldof;
   }
   return totaldof;
 }
 
 //***************************************************
 double JointFCN::GetLikelihood() {
   //***************************************************
 
   LOG(MIN) << std::left << std::setw(43) << "Getting likelihoods..."
            << " : "
            << "-2logL" << std::endl;
 
   // Loop and add up likelihoods in an uncorrelated way
   double like = 0.0;
   int count = 0;
   for (MeasListConstIter iter = fSamples.begin(); iter != fSamples.end();
        iter++) {
     MeasurementBase* exp = *iter;
     double newlike = exp->GetLikelihood();
     int ndof = exp->GetNDOF();
     // Save seperate likelihoods
     if (fIterationTree) {
       fSampleLikes[count] = newlike;
     }
 
     LOG(MIN) << "-> " << std::left << std::setw(40) << exp->GetName() << " : "
              << newlike << "/" << ndof << std::endl;
 
     // Add Weight Scaling
     // like *= FitBase::GetRW()->GetSampleLikelihoodWeight(exp->GetName());
 
     // Add to total
     like += newlike;
     count++;
   }
 
   // Loop over pulls
   for (PullListConstIter iter = fPulls.begin(); iter != fPulls.end(); iter++) {
     ParamPull* pull = *iter;
     double newlike = pull->GetLikelihood();
 
     // Save seperate likelihoods
     if (fIterationTree) {
       fSampleLikes[count] = newlike;
     }
 
     // Add to total
     like += newlike;
     count++;
   }
 
   // Set Data Variable
   fLikelihood = like;
   if (fIterationTree){
     fSampleLikes[count] = fLikelihood;
   }
 
   return like;
 };
 
 void JointFCN::LoadSamples(std::vector<nuiskey> samplekeys) {
   LOG(MIN) << "Loading Samples : " << samplekeys.size() << std::endl;
   for (size_t i = 0; i < samplekeys.size(); i++) {
     nuiskey key = samplekeys[i];
 
     // Get Sample Options
     std::string samplename = key.GetS("name");
     std::string samplefile = key.GetS("input");
     std::string sampletype = key.GetS("type");
     std::string fakeData = "";
 
     LOG(MIN) << "Loading Sample : " << samplename << std::endl;
 
     fOutputDir->cd();
     MeasurementBase* NewLoadedSample = SampleUtils::CreateSample(key);
 
     if (!NewLoadedSample) {
       ERR(FTL) << "Could not load sample provided: " << samplename << std::endl;
       ERR(FTL) << "Check spelling with that in src/FCN/SampleList.cxx"
                << std::endl;
       throw;
     } else {
       fSamples.push_back(NewLoadedSample);
     }
   }
 }
 
 //***************************************************
 void JointFCN::LoadPulls(std::vector<nuiskey> pullkeys) {
 //***************************************************
   for (size_t i = 0; i < pullkeys.size(); i++) {
     nuiskey key = pullkeys[i];
 
     std::string pullname = key.GetS("name");
     std::string pullfile = key.GetS("input");
     std::string pulltype = key.GetS("type");
 
     fOutputDir->cd();
     fPulls.push_back(new ParamPull(pullname, pullfile, pulltype));
   }
 }
 
 //***************************************************
 void JointFCN::ReconfigureSamples(bool fullconfig) {
 //***************************************************
 
   int starttime = time(NULL);
   LOG(REC) << "Starting Reconfigure iter. " << this->fCurIter << std::endl;
   // std::cout << fUsingEventManager << " " << fullconfig << " " << fMCFilled <<
   // std::endl;
   // Event Manager Reconf
   if (fUsingEventManager) {
     if (!fullconfig and fMCFilled)
       ReconfigureFastUsingManager();
     else
       ReconfigureUsingManager();
 
   } else {
     // Loop over all Measurement Classes
     for (MeasListConstIter iter = fSamples.begin(); iter != fSamples.end();
          iter++) {
       MeasurementBase* exp = *iter;
 
       // If RW Either do signal or full reconfigure.
       if (fDialChanged or !fMCFilled or fullconfig) {
         if (!fullconfig and fMCFilled)
           exp->ReconfigureFast();
         else
           exp->Reconfigure();
 
         // If RW Not needed just do normalisation
       } else {
         exp->Renormalise();
       }
     }
   }
 
   // Loop over pulls and update
   for (PullListConstIter iter = fPulls.begin(); iter != fPulls.end(); iter++) {
     ParamPull* pull = *iter;
     pull->Reconfigure();
   }
 
   fMCFilled = true;
   LOG(MIN) << "Finished Reconfigure iter. " << fCurIter << " in "
            << time(NULL) - starttime << "s" << std::endl;
 
   fCurIter++;
 }
 
 //***************************************************
 void JointFCN::ReconfigureSignal() {
 //***************************************************
   ReconfigureSamples(false);
 }
 
 //***************************************************
 void JointFCN::ReconfigureAllEvents() {
   //***************************************************
   FitBase::GetRW()->Reconfigure();
   FitBase::EvtManager().ResetWeightFlags();
   ReconfigureSamples(true);
 }
 
 std::vector<InputHandlerBase*> JointFCN::GetInputList() {
   std::vector<InputHandlerBase*> InputList;
   fIsAllSplines = true;
 
   MeasListConstIter iterSam = fSamples.begin();
   for (; iterSam != fSamples.end(); iterSam++) {
     MeasurementBase* exp = (*iterSam);
 
     std::vector<MeasurementBase*> subsamples = exp->GetSubSamples();
     for (size_t i = 0; i < subsamples.size(); i++) {
       InputHandlerBase* inp = subsamples[i]->GetInput();
       if (std::find(InputList.begin(), InputList.end(), inp) ==
           InputList.end()) {
         if (subsamples[i]->GetInput()->GetType() != kSPLINEPARAMETER)
           fIsAllSplines = false;
 
         InputList.push_back(subsamples[i]->GetInput());
       }
     }
   }
 
   return InputList;
 }
 
 std::vector<MeasurementBase*> JointFCN::GetSubSampleList() {
   std::vector<MeasurementBase*> SampleList;
 
   MeasListConstIter iterSam = fSamples.begin();
   for (; iterSam != fSamples.end(); iterSam++) {
     MeasurementBase* exp = (*iterSam);
 
     std::vector<MeasurementBase*> subsamples = exp->GetSubSamples();
     for (size_t i = 0; i < subsamples.size(); i++) {
       SampleList.push_back(subsamples[i]);
     }
   }
 
   return SampleList;
 }
 
 //***************************************************
 void JointFCN::ReconfigureUsingManager() {
 //***************************************************
 
   // 'Slow' Event Manager Reconfigure
   LOG(REC) << "Event Manager Reconfigure" << std::endl;
   int timestart = time(NULL);
 
   // Reset all samples
   MeasListConstIter iterSam = fSamples.begin();
   for (; iterSam != fSamples.end(); iterSam++) {
     MeasurementBase* exp = (*iterSam);
     exp->ResetAll();
   }
 
   // If we are siving signal, reset all containers.
   bool savesignal = (FitPar::Config().GetParB("SignalReconfigures"));
 
   if (savesignal) {
     // Reset all of our event signal vectors
     fSignalEventBoxes.clear();
     fSignalEventFlags.clear();
     fSampleSignalFlags.clear();
     fSignalEventSplines.clear();
   }
 
   // Make sure we have a list of inputs
   if (fInputList.empty()) {
     fInputList = GetInputList();
     fSubSampleList = GetSubSampleList();
   }
 
   // If all inputs are splines make sure the readers are told
   // they need to be reconfigured.
   std::vector<InputHandlerBase*>::iterator inp_iter = fInputList.begin();
 
   if (fIsAllSplines) {
     for (; inp_iter != fInputList.end(); inp_iter++) {
       InputHandlerBase* curinput = (*inp_iter);
 
       // Tell reader in each BaseEvent it needs a Reconfigure next weight calc.
       BaseFitEvt* curevent = curinput->FirstBaseEvent();
       if (curevent->fSplineRead) {
         curevent->fSplineRead->SetNeedsReconfigure(true);
       }
     }
   }
 
   // MAIN INPUT LOOP ====================
 
   int fillcount = 0;
   int inputcount = 0;
   inp_iter = fInputList.begin();
 
   // Loop over each input in manager
   for (; inp_iter != fInputList.end(); inp_iter++) {
     InputHandlerBase* curinput = (*inp_iter);
 
     // Get event information
     FitEvent* curevent = curinput->FirstNuisanceEvent();
     curinput->CreateCache();
 
     int i = 0;
     int nevents = curinput->GetNEvents();
     int countwidth = nevents / 5;
 
     // Start event loop iterating until we get a NULL pointer.
     while (curevent) {
       // Get Event Weight
       curevent->RWWeight = FitBase::GetRW()->CalcWeight(curevent);
       curevent->Weight = curevent->RWWeight * curevent->InputWeight;
       double rwweight = curevent->Weight;
       // std::cout << "RWWeight = " << curevent->RWWeight  << " " <<
       // curevent->InputWeight << std::endl;
 
       // Logging
       // std::cout << CHECKLOG(1) << std::endl;
       if (LOGGING(REC)) {
         if (i % countwidth == 0) {
           QLOG(REC, curinput->GetName()
                << " : Processed " << i << " events. [M, W] = ["
                << curevent->Mode << ", " << rwweight << "]");
         }
       }
 
       // Setup flag for if signal found in at least one sample
       bool foundsignal = false;
 
       // Create a new signal bitset for this event
       std::vector<bool> signalbitset(fSubSampleList.size());
 
       // Create a new signal box vector for this event
       std::vector<MeasurementVariableBox*> signalboxes;
 
       // Start measurement iterator
       size_t measitercount = 0;
       std::vector<MeasurementBase*>::iterator meas_iter =
         fSubSampleList.begin();
 
       // Loop over all subsamples (sub in JointMeas)
       for (; meas_iter != fSubSampleList.end(); meas_iter++) {
         MeasurementBase* curmeas = (*meas_iter);
 
         // Compare input pointers, to current input, skip if not.
         // Pointer tells us if it matches without doing ID checks.
         if (curinput != curmeas->GetInput()) {
           if (savesignal) {
             // Set bit to 0 as definitely not signal
             signalbitset[measitercount] = 0;
           }
 
           // Count up what measurement we are on.
           measitercount++;
 
           // Skip sample as input not signal.
           continue;
         }
 
         // Fill events for matching inputs.
         MeasurementVariableBox* box = curmeas->FillVariableBox(curevent);
 
         bool signal = curmeas->isSignal(curevent);
         curmeas->SetSignal(signal);
         curmeas->FillHistograms(curevent->Weight);
 
         // If its Signal tally up fills
         if (signal) {
           fillcount++;
         }
 
         // If we are saving signal/splines fill the bitset
         if (savesignal) {
           signalbitset[measitercount] = signal;
         }
 
         // If signal save a clone of the event box for use later.
         if (savesignal and signal) {
           foundsignal = true;
           signalboxes.push_back(box->CloneSignalBox());
         }
 
         // Keep track of Measurement we are on.
         measitercount++;
       }
 
       // Once we've filled the measurements, if saving signal
       // push back if any sample flagged this event as signal
       if (savesignal) {
         fSignalEventFlags.push_back(foundsignal);
       }
 
       // Save the vector of signal boxes for this event
       if (savesignal and foundsignal) {
         fSignalEventBoxes.push_back(signalboxes);
         fSampleSignalFlags.push_back(signalbitset);
       }
 
       // If all inputs are splines we can save the spline coefficients
       // for fast in memory reconfigures later.
       if (fIsAllSplines and savesignal and foundsignal) {
         // Make temp vector to push back with
         std::vector<float> coeff;
         for (size_t l = 0; l < (UInt_t)curevent->fSplineRead->GetNPar(); l++) {
           coeff.push_back(curevent->fSplineCoeff[l]);
         }
 
         // Push back to signal event splines. Kept in sync with
         // fSignalEventBoxes size.
         // int splinecount = fSignalEventSplines.size();
         fSignalEventSplines.push_back(coeff);
 
         // if (splinecount % 1000 == 0) {
         // std::cout << "Pushed Back Coeff " << splinecount << " : ";
         // for (size_t l = 0; l < fSignalEventSplines[splinecount].size(); l++)
         // {
         // std::cout << " " << fSignalEventSplines[splinecount][l];
         // }
         // std::cout << std::endl;
         // }
       }
 
       // Clean up vectors once done with this event
       signalboxes.clear();
       signalbitset.clear();
 
       // Iterate to the next event.
       curevent = curinput->NextNuisanceEvent();
       i++;
     }
 
-    curinput->RemoveCache();
+    //    curinput->RemoveCache();
 
     // Keep track of what input we are on.
     inputcount++;
   }
 
   // End of Event Loop ===============================
 
   // Now event loop is finished loop over all Measurements
   // Converting Binned events to XSec Distributions
   iterSam = fSamples.begin();
   for (; iterSam != fSamples.end(); iterSam++) {
     MeasurementBase* exp = (*iterSam);
     exp->ConvertEventRates();
   }
 
   // Print out statements on approximate memory usage for profiling.
   LOG(REC) << "Filled " << fillcount << " signal events." << std::endl;
   if (savesignal) {
     int mem =
       (  // sizeof(fSignalEventBoxes) +
         // fSignalEventBoxes.size() * sizeof(fSignalEventBoxes.at(0)) +
         sizeof(MeasurementVariableBox1D) * fillcount) *
       1E-6;
     LOG(REC) << " -> Saved " << fillcount
              << " signal boxes for faster access. (~" << mem << " MB)"
              << std::endl;
     if (fIsAllSplines and !fSignalEventSplines.empty()) {
       int splmem = sizeof(float) * fSignalEventSplines.size() *
                    fSignalEventSplines[0].size() * 1E-6;
       LOG(REC) << " -> Saved " << fillcount << " " << fSignalEventSplines.size()
                << " spline sets into memory. (~" << splmem << " MB)"
                << std::endl;
     }
   }
 
   LOG(REC) << "Time taken ReconfigureUsingManager() : "
            << time(NULL) - timestart << std::endl;
 
   // Check SignalReconfigures works for all samples
   if (savesignal) {
     double likefull = GetLikelihood();
     ReconfigureFastUsingManager();
     double likefast = GetLikelihood();
 
     if (fabs(likefull - likefast) > 0.0001)
     {
       ERROR(FTL, "Fast and Full Likelihoods DIFFER! : " << likefull << " : " << likefast);
       ERROR(FTL, "This means some samples you are using are not setup to use SignalReconfigures=1");
       ERROR(FTL, "Please turn OFF signal reconfigures.");
       throw;
     } else {
       LOG(FIT) << "Likelihoods for FULL and FAST match. Will use FAST next time." << std::endl;
     }
   }
 
   // End of reconfigure
   return;
 };
 
 //***************************************************
 void JointFCN::ReconfigureFastUsingManager() {
 //***************************************************
 
   LOG(FIT) << " -> Doing FAST using manager" << std::endl;
   // Get Start time for profilling
   int timestart = time(NULL);
 
   // Reset all samples
   MeasListConstIter iterSam = fSamples.begin();
   for (; iterSam != fSamples.end(); iterSam++) {
     MeasurementBase* exp = (*iterSam);
     exp->ResetAll();
   }
 
   // Check for saved variables if not do a full reconfigure.
   if (fSignalEventFlags.empty()) {
     ERR(WRN) << "Signal Flags Empty! Using normal manager." << std::endl;
     ReconfigureUsingManager();
     return;
   }
 
   bool fFillNuisanceEvent =
     FitPar::Config().GetParB("FullEventOnSignalReconfigure");
 
   // Setup fast vector iterators.
   std::vector<bool>::iterator inpsig_iter = fSignalEventFlags.begin();
   std::vector<std::vector<MeasurementVariableBox*> >::iterator box_iter =
     fSignalEventBoxes.begin();
   std::vector<std::vector<float> >::iterator spline_iter =
     fSignalEventSplines.begin();
   std::vector<std::vector<bool> >::iterator samsig_iter =
     fSampleSignalFlags.begin();
   int splinecount = 0;
 
   // Setup stuff for logging
   int fillcount = 0;
   int nevents = fSignalEventFlags.size();
   int countwidth = nevents / 20;
 
   // If All Splines tell splines they need a reconfigure.
   std::vector<InputHandlerBase*>::iterator inp_iter = fInputList.begin();
   if (fIsAllSplines) {
     LOG(REC) << "All Spline Inputs so using fast spline loop." << std::endl;
     for (; inp_iter != fInputList.end(); inp_iter++) {
       InputHandlerBase* curinput = (*inp_iter);
 
       // Tell each fSplineRead in BaseFitEvent to reconf next weight calc
       BaseFitEvt* curevent = curinput->FirstBaseEvent();
       if (curevent->fSplineRead)
         curevent->fSplineRead->SetNeedsReconfigure(true);
     }
   }
 
   // Loop over all possible spline inputs
   double* coreeventweights = new double[fSignalEventBoxes.size()];
   splinecount = 0;
 
   inp_iter = fInputList.begin();
   inpsig_iter = fSignalEventFlags.begin();
   spline_iter = fSignalEventSplines.begin();
 
   // Loop over all signal flags
   // For each valid signal flag add one to splinecount
   // Get Splines from that count and add to weight
   // Add splinecount
   int sigcount = 0;
   splinecount = 0;
 
   // #pragma omp parallel for shared(splinecount,sigcount)
   for (uint iinput = 0; iinput < fInputList.size(); iinput++) {
     InputHandlerBase* curinput = fInputList[iinput];
     BaseFitEvt* curevent = curinput->FirstBaseEvent();
 
     for (int i = 0; i < curinput->GetNEvents(); i++) {
       double rwweight = 0.0;
       if (fSignalEventFlags[sigcount]) {
         // Get Event Info
         if (!fIsAllSplines) {
           if (fFillNuisanceEvent)
             curinput->GetNuisanceEvent(i);
           else
             curevent = curinput->GetBaseEvent(i);
         } else {
           curevent->fSplineCoeff = &fSignalEventSplines[splinecount][0];
         }
 
         curevent->RWWeight = FitBase::GetRW()->CalcWeight(curevent);
         curevent->Weight = curevent->RWWeight * curevent->InputWeight;
         rwweight = curevent->Weight;
 
         coreeventweights[splinecount] = rwweight;
-        if (countwidth && ((splinecount % countwidth) == 0)) {
+        if (splinecount % countwidth == 0) {
           LOG(REC) << "Processed " << splinecount
                    << " event weights. W = " << rwweight << std::endl;
         }
 
         // #pragma omp atomic
         splinecount++;
       }
 
       // #pragma omp atomic
       sigcount++;
     }
   }
   LOG(SAM) << "Processed event weights." << std::endl;
 
   // #pragma omp barrier
 
   // Reset Iterators
   inpsig_iter = fSignalEventFlags.begin();
   spline_iter = fSignalEventSplines.begin();
   box_iter = fSignalEventBoxes.begin();
   samsig_iter = fSampleSignalFlags.begin();
   int nsplineweights = splinecount;
   splinecount = 0;
 
   // Start of Fast Event Loop ============================
 
   // Start input iterators
   // Loop over number of inputs
   for (int ispline = 0; ispline < nsplineweights; ispline++) {
     double rwweight = coreeventweights[ispline];
 
     // Get iterators for this event
     std::vector<bool>::iterator subsamsig_iter = (*samsig_iter).begin();
     std::vector<MeasurementVariableBox*>::iterator subbox_iter =
       (*box_iter).begin();
 
     // Loop over all sub measurements.
     std::vector<MeasurementBase*>::iterator meas_iter = fSubSampleList.begin();
     for (; meas_iter != fSubSampleList.end(); meas_iter++, subsamsig_iter++) {
       MeasurementBase* curmeas = (*meas_iter);
 
       // If event flagged as signal for this sample fill from the box.
       if (*subsamsig_iter) {
         curmeas->SetSignal(true);
         curmeas->FillHistogramsFromBox((*subbox_iter), rwweight);
 
         // Move onto next box if there is one.
         subbox_iter++;
         fillcount++;
       }
     }
 
     if (ispline % countwidth == 0) {
       LOG(REC) << "Filled " << ispline << " sample weights." << std::endl;
     }
 
     // Iterate over the main signal event containers.
     samsig_iter++;
     box_iter++;
     spline_iter++;
     splinecount++;
   }
   // End of Fast Event Loop ===================
 
   LOG(SAM) << "Filled sample distributions." << std::endl;
 
   // Now loop over all Measurements
   // Convert Binned events
   iterSam = fSamples.begin();
   for (; iterSam != fSamples.end(); iterSam++) {
     MeasurementBase* exp = (*iterSam);
     exp->ConvertEventRates();
   }
 
   // Cleanup coreeventweights
   if (fIsAllSplines) {
     delete coreeventweights;
   }
 
   // Print some reconfigure profiling.
   LOG(REC) << "Filled " << fillcount << " signal events." << std::endl;
   LOG(REC) << "Time taken ReconfigureFastUsingManager() : "
            << time(NULL) - timestart << std::endl;
 }
 
 //***************************************************
 void JointFCN::Write() {
 //***************************************************
 
   // Save a likelihood/ndof plot
   LOG(MIN) << "Writing likelihood plot.." << std::endl;
   std::vector<double> likes;
   std::vector<double> ndofs;
   std::vector<std::string> names;
   for (MeasListConstIter iter = fSamples.begin(); iter != fSamples.end();
        iter++) {
     MeasurementBase* exp = *iter;
     double like = exp->GetLikelihood();
     double ndof = exp->GetNDOF();
     std::string name = exp->GetName();
     likes.push_back(like);
     ndofs.push_back(ndof);
     names.push_back(name);
   }
   TH1D likehist = TH1D("likelihood_hist", "likelihood_hist",
                        likes.size(), 0.0, double(likes.size()));
   TH1D ndofhist  = TH1D("ndof_hist", "ndof_hist",
                         ndofs.size(), 0.0, double(ndofs.size()));
   TH1D divhist   = TH1D("likedivndof_hist", "likedivndof_hist",
                         likes.size(), 0.0, double(likes.size()));
   for (size_t i = 0; i < likehist.GetNbinsX(); i++) {
     likehist.SetBinContent(i + 1, likes[i]);
     ndofhist.SetBinContent(i + 1, ndofs[i]);
     if (ndofs[i] != 0.0) {
       divhist.SetBinContent(i + 1, likes[i] / ndofs[i]);
     }
     likehist.GetXaxis()->SetBinLabel(i + 1, names[i].c_str());
     ndofhist.GetXaxis()->SetBinLabel(i + 1, names[i].c_str());
     divhist.GetXaxis()->SetBinLabel(i + 1, names[i].c_str());
   }
   likehist.Write();
   ndofhist.Write();
   divhist.Write();
 
   // Loop over individual experiments and call Write
   LOG(MIN) << "Writing each of the data classes..." << std::endl;
   for (MeasListConstIter iter = fSamples.begin(); iter != fSamples.end();
        iter++) {
     MeasurementBase* exp = *iter;
     exp->Write();
   }
 
   // Save Pull Terms
   for (PullListConstIter iter = fPulls.begin(); iter != fPulls.end(); iter++) {
     ParamPull* pull = *iter;
     pull->Write();
   }
 
   if (FitPar::Config().GetParB("EventManager")) {
     // Get list of inputs
     std::map<int, InputHandlerBase*> fInputs =
       FitBase::EvtManager().GetInputs();
     std::map<int, InputHandlerBase*>::const_iterator iterInp;
 
     for (iterInp = fInputs.begin(); iterInp != fInputs.end(); iterInp++) {
       InputHandlerBase* input = (iterInp->second);
 
       input->GetFluxHistogram()->Write();
       input->GetXSecHistogram()->Write();
       input->GetEventHistogram()->Write();
     }
   }
 };
 
 //***************************************************
 void JointFCN::SetFakeData(std::string fakeinput) {
 //***************************************************
 
   LOG(MIN) << "Setting fake data from " << fakeinput << std::endl;
   for (MeasListConstIter iter = fSamples.begin(); iter != fSamples.end();
        iter++) {
     MeasurementBase* exp = *iter;
     exp->SetFakeDataValues(fakeinput);
   }
 
   return;
 }
 
 //***************************************************
 void JointFCN::ThrowDataToy() {
 //***************************************************
 
   for (MeasListConstIter iter = fSamples.begin(); iter != fSamples.end();
        iter++) {
     MeasurementBase* exp = *iter;
     exp->ThrowDataToy();
   }
 
   return;
 }
diff --git a/src/FCN/JointFCN.cxx b/src/FCN/JointFCN.cxx
index dee225c..f3eb4e6 100755
--- a/src/FCN/JointFCN.cxx
+++ b/src/FCN/JointFCN.cxx
@@ -1,1014 +1,1136 @@
 #include "JointFCN.h"
 #include <stdio.h>
 #include "FitUtils.h"
 
 
 //***************************************************
 JointFCN::JointFCN(TFile* outfile) {
 //***************************************************
 
   fOutputDir = gDirectory;
-  if (outfile) FitPar::Config().out = outfile;
+  if (outfile) Config::Get().out = outfile;
 
   std::vector<nuiskey> samplekeys = Config::QueryKeys("sample");
   LoadSamples(samplekeys);
 
   std::vector<nuiskey> covarkeys = Config::QueryKeys("covar");
   LoadPulls(covarkeys);
 
   fCurIter = 0;
   fMCFilled = false;
 
   fIterationTree = false;
   fDialVals = NULL;
   fNDials = 0;
 
   fUsingEventManager = FitPar::Config().GetParB("EventManager");
   fOutputDir->cd();
 }
 
 //***************************************************
 JointFCN::JointFCN(std::vector<nuiskey> samplekeys, TFile* outfile) {
 //***************************************************
 
   fOutputDir = gDirectory;
-  if (outfile) FitPar::Config().out = outfile;
+  if (outfile) Config::Get().out = outfile;
 
   LoadSamples(samplekeys);
 
   fCurIter = 0;
   fMCFilled = false;
 
   fOutputDir->cd();
 
   fIterationTree = false;
   fDialVals = NULL;
   fNDials = 0;
 
   fUsingEventManager = FitPar::Config().GetParB("EventManager");
   fOutputDir->cd();
 }
 
 //***************************************************
 JointFCN::~JointFCN() {
   //***************************************************
 
   // Delete Samples
   for (MeasListConstIter iter = fSamples.begin(); iter != fSamples.end();
        iter++) {
     MeasurementBase* exp = *iter;
     delete exp;
   }
 
   for (PullListConstIter iter = fPulls.begin(); iter != fPulls.end(); iter++) {
     ParamPull* pull = *iter;
     delete pull;
   }
 
   // Sort Tree
   if (fIterationTree) DestroyIterationTree();
   if (fDialVals) delete fDialVals;
   if (fSampleLikes) delete fSampleLikes;
 };
 
 //***************************************************
 void JointFCN::CreateIterationTree(std::string name, FitWeight* rw) {
 //***************************************************
 
   LOG(FIT) << " Creating new iteration container! " << std::endl;
   DestroyIterationTree();
   fIterationTreeName = name;
 
   // Add sample likelihoods and ndof
   for (MeasListConstIter iter = fSamples.begin();
        iter != fSamples.end();
        iter++) {
 
     MeasurementBase* exp = *iter;
     std::string name = exp->GetName();
 
     std::string liketag = name + "_likelihood";
     fNameValues.push_back(liketag);
     fCurrentValues.push_back(0.0);
 
     std::string ndoftag = name + "_ndof";
     fNameValues.push_back(ndoftag);
     fCurrentValues.push_back(0.0);
   }
 
   // Add Pull terms
   for (PullListConstIter iter = fPulls.begin();
        iter != fPulls.end(); iter++) {
 
     ParamPull* pull = *iter;
     std::string name = pull->GetName();
 
     std::string liketag = name + "_likelihood";
     fNameValues.push_back(liketag);
     fCurrentValues.push_back(0.0);
 
     std::string ndoftag = name + "_ndof";
     fNameValues.push_back(ndoftag);
     fCurrentValues.push_back(0.0);
   }
 
   // Add Likelihoods
   fNameValues.push_back("total_likelihood");
   fCurrentValues.push_back(0.0);
 
   fNameValues.push_back("total_ndof");
   fCurrentValues.push_back(0.0);
 
   // Setup Containers
   fSampleN     = fSamples.size() + fPulls.size();
   fSampleLikes = new double[fSampleN];
   fSampleNDOF  = new int[fSampleN];
 
   // Add Dials
   std::vector<std::string> dials = rw->GetDialNames();
-  for (size_t i = 0; i < dials.size(); i++){
+  for (size_t i = 0; i < dials.size(); i++) {
     fNameValues.push_back( dials[i] );
     fCurrentValues.push_back( 0.0 );
   }
   fNDials   = dials.size();
   fDialVals = new double[fNDials];
 
   // Set IterationTree Flag
   fIterationTree = true;
 
 }
 
 //***************************************************
 void JointFCN::DestroyIterationTree() {
 //***************************************************
 
   fIterationCount.clear();
   fCurrentValues.clear();
   fNameValues.clear();
   fIterationValues.clear();
 
 }
 
 //***************************************************
 void JointFCN::WriteIterationTree() {
 //***************************************************
   LOG(FIT) << "Writing iteration tree" << std::endl;
 
   // Make a new TTree
   TTree* itree = new TTree(fIterationTreeName.c_str(),
                            fIterationTreeName.c_str());
 
   double* vals = new double[fNameValues.size()];
   int count = 0;
 
-  itree->Branch("iteration",&count,"Iteration/I");
+  itree->Branch("iteration", &count, "Iteration/I");
   for (int i = 0; i < fNameValues.size(); i++) {
     itree->Branch( fNameValues[i].c_str(),
                    &vals[i],
                    (fNameValues[i] + "/D").c_str() );
   }
 
   // Fill Iterations
-  for (size_t i = 0; i < fIterationValues.size(); i++){
+  for (size_t i = 0; i < fIterationValues.size(); i++) {
     std::vector<double> itervals = fIterationValues[i];
 
     // Fill iteration state
     count = fIterationCount[i];
-    for (size_t j = 0; j < itervals.size(); j++){
+    for (size_t j = 0; j < itervals.size(); j++) {
       vals[j] = itervals[j];
     }
 
     // Save to TTree
     itree->Fill();
   }
 
   // Write to file
   itree->Write();
 }
 
 //***************************************************
 void JointFCN::FillIterationTree(FitWeight* rw) {
 //***************************************************
 
   // Loop over samples count
   int count = 0;
-  for (int i = 0; i < fSampleN; i++){
+  for (int i = 0; i < fSampleN; i++) {
     fCurrentValues[count++] = fSampleLikes[i];
     fCurrentValues[count++] = double(fSampleNDOF[i]);
   }
 
   // Fill Totals
   fCurrentValues[count++] = fLikelihood;
   fCurrentValues[count++] = double(fNDOF);
 
   // Loop Over Parameter Counts
   rw->GetAllDials(fDialVals, fNDials);
-  for (int i = 0; i < fNDials; i++){
+  for (int i = 0; i < fNDials; i++) {
     fCurrentValues[count++] = double(fDialVals[i]);
   }
 
   // Push Back Into Container
   fIterationCount.push_back( fCurIter );
   fIterationValues.push_back(fCurrentValues);
 }
 
 //***************************************************
 double JointFCN::DoEval(const double* x) {
   //***************************************************
 
   // WEIGHT ENGINE
   fDialChanged = FitBase::GetRW()->HasRWDialChanged(x);
   FitBase::GetRW()->UpdateWeightEngine(x);
   if (fDialChanged) {
     FitBase::GetRW()->Reconfigure();
     FitBase::EvtManager().ResetWeightFlags();
   }
   if (LOG_LEVEL(REC)) {
     FitBase::GetRW()->Print();
   }
 
   // SORT SAMPLES
   ReconfigureSamples();
 
   // GET TEST STAT
   fLikelihood = GetLikelihood();
   fNDOF       = GetNDOF();
 
   // PRINT PROGRESS
   LOG(FIT) << "Current Stat (iter. " << this->fCurIter << ") = " << fLikelihood
            << std::endl;
 
   // UPDATE TREE
   if (fIterationTree) FillIterationTree(FitBase::GetRW());
 
   return fLikelihood;
 }
 
 //***************************************************
 int JointFCN::GetNDOF() {
   //***************************************************
 
   int totaldof = 0;
   int count = 0;
 
   // Total number of Free bins in each MC prediction
   for (MeasListConstIter iter = fSamples.begin(); iter != fSamples.end();
        iter++) {
     MeasurementBase* exp = *iter;
     int dof = exp->GetNDOF();
 
     // Save Seperate DOF
     if (fIterationTree) {
       fSampleNDOF[count] = dof;
     }
 
     // Add to total
     totaldof += dof;
     count++;
   }
 
   // Loop over pulls
   for (PullListConstIter iter = fPulls.begin(); iter != fPulls.end(); iter++) {
     ParamPull* pull = *iter;
     double dof = pull->GetLikelihood();
 
     // Save seperate DOF
     if (fIterationTree) {
       fSampleNDOF[count] = dof;
     }
 
     // Add to total
     totaldof += dof;
     count++;
   }
 
   // Set Data Variable
-  if (fIterationTree){
-  fSampleNDOF[count] = totaldof;
+  if (fIterationTree) {
+    fSampleNDOF[count] = totaldof;
   }
   return totaldof;
 }
 
 //***************************************************
 double JointFCN::GetLikelihood() {
   //***************************************************
 
   LOG(MIN) << std::left << std::setw(43) << "Getting likelihoods..."
            << " : "
            << "-2logL" << std::endl;
 
   // Loop and add up likelihoods in an uncorrelated way
   double like = 0.0;
   int count = 0;
   for (MeasListConstIter iter = fSamples.begin(); iter != fSamples.end();
        iter++) {
     MeasurementBase* exp = *iter;
     double newlike = exp->GetLikelihood();
     int ndof = exp->GetNDOF();
     // Save seperate likelihoods
     if (fIterationTree) {
       fSampleLikes[count] = newlike;
     }
 
     LOG(MIN) << "-> " << std::left << std::setw(40) << exp->GetName() << " : "
              << newlike << "/" << ndof << std::endl;
 
     // Add Weight Scaling
     // like *= FitBase::GetRW()->GetSampleLikelihoodWeight(exp->GetName());
 
     // Add to total
     like += newlike;
     count++;
   }
 
   // Loop over pulls
   for (PullListConstIter iter = fPulls.begin(); iter != fPulls.end(); iter++) {
     ParamPull* pull = *iter;
     double newlike = pull->GetLikelihood();
 
     // Save seperate likelihoods
     if (fIterationTree) {
       fSampleLikes[count] = newlike;
     }
 
     // Add to total
     like += newlike;
     count++;
   }
 
   // Set Data Variable
   fLikelihood = like;
-  if (fIterationTree){
+  if (fIterationTree) {
     fSampleLikes[count] = fLikelihood;
   }
 
   return like;
 };
 
 void JointFCN::LoadSamples(std::vector<nuiskey> samplekeys) {
   LOG(MIN) << "Loading Samples : " << samplekeys.size() << std::endl;
   for (size_t i = 0; i < samplekeys.size(); i++) {
     nuiskey key = samplekeys[i];
 
     // Get Sample Options
     std::string samplename = key.GetS("name");
     std::string samplefile = key.GetS("input");
     std::string sampletype = key.GetS("type");
     std::string fakeData = "";
 
     LOG(MIN) << "Loading Sample : " << samplename << std::endl;
 
     fOutputDir->cd();
     MeasurementBase* NewLoadedSample = SampleUtils::CreateSample(key);
 
     if (!NewLoadedSample) {
       ERR(FTL) << "Could not load sample provided: " << samplename << std::endl;
       ERR(FTL) << "Check spelling with that in src/FCN/SampleList.cxx"
                << std::endl;
       throw;
     } else {
       fSamples.push_back(NewLoadedSample);
     }
   }
 }
 
 //***************************************************
 void JointFCN::LoadPulls(std::vector<nuiskey> pullkeys) {
 //***************************************************
   for (size_t i = 0; i < pullkeys.size(); i++) {
     nuiskey key = pullkeys[i];
 
     std::string pullname = key.GetS("name");
     std::string pullfile = key.GetS("input");
     std::string pulltype = key.GetS("type");
 
     fOutputDir->cd();
     fPulls.push_back(new ParamPull(pullname, pullfile, pulltype));
   }
 }
 
 //***************************************************
 void JointFCN::ReconfigureSamples(bool fullconfig) {
 //***************************************************
 
   int starttime = time(NULL);
   LOG(REC) << "Starting Reconfigure iter. " << this->fCurIter << std::endl;
   // std::cout << fUsingEventManager << " " << fullconfig << " " << fMCFilled <<
   // std::endl;
   // Event Manager Reconf
   if (fUsingEventManager) {
     if (!fullconfig and fMCFilled)
       ReconfigureFastUsingManager();
     else
       ReconfigureUsingManager();
 
   } else {
     // Loop over all Measurement Classes
     for (MeasListConstIter iter = fSamples.begin(); iter != fSamples.end();
          iter++) {
       MeasurementBase* exp = *iter;
 
       // If RW Either do signal or full reconfigure.
       if (fDialChanged or !fMCFilled or fullconfig) {
         if (!fullconfig and fMCFilled)
           exp->ReconfigureFast();
         else
           exp->Reconfigure();
 
         // If RW Not needed just do normalisation
       } else {
         exp->Renormalise();
       }
     }
   }
 
   // Loop over pulls and update
   for (PullListConstIter iter = fPulls.begin(); iter != fPulls.end(); iter++) {
     ParamPull* pull = *iter;
     pull->Reconfigure();
   }
 
   fMCFilled = true;
   LOG(MIN) << "Finished Reconfigure iter. " << fCurIter << " in "
            << time(NULL) - starttime << "s" << std::endl;
 
   fCurIter++;
 }
 
 //***************************************************
 void JointFCN::ReconfigureSignal() {
 //***************************************************
   ReconfigureSamples(false);
 }
 
 //***************************************************
 void JointFCN::ReconfigureAllEvents() {
   //***************************************************
   FitBase::GetRW()->Reconfigure();
   FitBase::EvtManager().ResetWeightFlags();
   ReconfigureSamples(true);
 }
 
 std::vector<InputHandlerBase*> JointFCN::GetInputList() {
   std::vector<InputHandlerBase*> InputList;
   fIsAllSplines = true;
 
   MeasListConstIter iterSam = fSamples.begin();
   for (; iterSam != fSamples.end(); iterSam++) {
     MeasurementBase* exp = (*iterSam);
 
     std::vector<MeasurementBase*> subsamples = exp->GetSubSamples();
     for (size_t i = 0; i < subsamples.size(); i++) {
       InputHandlerBase* inp = subsamples[i]->GetInput();
       if (std::find(InputList.begin(), InputList.end(), inp) ==
           InputList.end()) {
         if (subsamples[i]->GetInput()->GetType() != kSPLINEPARAMETER)
           fIsAllSplines = false;
 
         InputList.push_back(subsamples[i]->GetInput());
       }
     }
   }
 
   return InputList;
 }
 
 std::vector<MeasurementBase*> JointFCN::GetSubSampleList() {
   std::vector<MeasurementBase*> SampleList;
 
   MeasListConstIter iterSam = fSamples.begin();
   for (; iterSam != fSamples.end(); iterSam++) {
     MeasurementBase* exp = (*iterSam);
 
     std::vector<MeasurementBase*> subsamples = exp->GetSubSamples();
     for (size_t i = 0; i < subsamples.size(); i++) {
       SampleList.push_back(subsamples[i]);
     }
   }
 
   return SampleList;
 }
 
 //***************************************************
 void JointFCN::ReconfigureUsingManager() {
 //***************************************************
 
   // 'Slow' Event Manager Reconfigure
   LOG(REC) << "Event Manager Reconfigure" << std::endl;
   int timestart = time(NULL);
 
   // Reset all samples
   MeasListConstIter iterSam = fSamples.begin();
   for (; iterSam != fSamples.end(); iterSam++) {
     MeasurementBase* exp = (*iterSam);
     exp->ResetAll();
   }
 
   // If we are siving signal, reset all containers.
   bool savesignal = (FitPar::Config().GetParB("SignalReconfigures"));
 
   if (savesignal) {
     // Reset all of our event signal vectors
     fSignalEventBoxes.clear();
     fSignalEventFlags.clear();
     fSampleSignalFlags.clear();
     fSignalEventSplines.clear();
   }
 
   // Make sure we have a list of inputs
   if (fInputList.empty()) {
     fInputList = GetInputList();
     fSubSampleList = GetSubSampleList();
   }
 
   // If all inputs are splines make sure the readers are told
   // they need to be reconfigured.
   std::vector<InputHandlerBase*>::iterator inp_iter = fInputList.begin();
 
   if (fIsAllSplines) {
     for (; inp_iter != fInputList.end(); inp_iter++) {
       InputHandlerBase* curinput = (*inp_iter);
 
       // Tell reader in each BaseEvent it needs a Reconfigure next weight calc.
       BaseFitEvt* curevent = curinput->FirstBaseEvent();
       if (curevent->fSplineRead) {
         curevent->fSplineRead->SetNeedsReconfigure(true);
       }
     }
   }
 
   // MAIN INPUT LOOP ====================
 
   int fillcount = 0;
   int inputcount = 0;
   inp_iter = fInputList.begin();
 
   // Loop over each input in manager
   for (; inp_iter != fInputList.end(); inp_iter++) {
     InputHandlerBase* curinput = (*inp_iter);
 
     // Get event information
     FitEvent* curevent = curinput->FirstNuisanceEvent();
     curinput->CreateCache();
 
     int i = 0;
     int nevents = curinput->GetNEvents();
     int countwidth = nevents / 5;
 
     // Start event loop iterating until we get a NULL pointer.
     while (curevent) {
       // Get Event Weight
       curevent->RWWeight = FitBase::GetRW()->CalcWeight(curevent);
       curevent->Weight = curevent->RWWeight * curevent->InputWeight;
       double rwweight = curevent->Weight;
       // std::cout << "RWWeight = " << curevent->RWWeight  << " " <<
       // curevent->InputWeight << std::endl;
 
       // Logging
       // std::cout << CHECKLOG(1) << std::endl;
       if (LOGGING(REC)) {
         if (i % countwidth == 0) {
           QLOG(REC, curinput->GetName()
                << " : Processed " << i << " events. [M, W] = ["
                << curevent->Mode << ", " << rwweight << "]");
         }
       }
 
       // Setup flag for if signal found in at least one sample
       bool foundsignal = false;
 
       // Create a new signal bitset for this event
       std::vector<bool> signalbitset(fSubSampleList.size());
 
       // Create a new signal box vector for this event
       std::vector<MeasurementVariableBox*> signalboxes;
 
       // Start measurement iterator
       size_t measitercount = 0;
       std::vector<MeasurementBase*>::iterator meas_iter =
         fSubSampleList.begin();
 
       // Loop over all subsamples (sub in JointMeas)
       for (; meas_iter != fSubSampleList.end(); meas_iter++) {
         MeasurementBase* curmeas = (*meas_iter);
 
         // Compare input pointers, to current input, skip if not.
         // Pointer tells us if it matches without doing ID checks.
         if (curinput != curmeas->GetInput()) {
           if (savesignal) {
             // Set bit to 0 as definitely not signal
             signalbitset[measitercount] = 0;
           }
 
           // Count up what measurement we are on.
           measitercount++;
 
           // Skip sample as input not signal.
           continue;
         }
 
         // Fill events for matching inputs.
         MeasurementVariableBox* box = curmeas->FillVariableBox(curevent);
 
         bool signal = curmeas->isSignal(curevent);
         curmeas->SetSignal(signal);
         curmeas->FillHistograms(curevent->Weight);
 
         // If its Signal tally up fills
         if (signal) {
           fillcount++;
         }
 
         // If we are saving signal/splines fill the bitset
         if (savesignal) {
           signalbitset[measitercount] = signal;
         }
 
         // If signal save a clone of the event box for use later.
         if (savesignal and signal) {
           foundsignal = true;
           signalboxes.push_back(box->CloneSignalBox());
         }
 
         // Keep track of Measurement we are on.
         measitercount++;
       }
 
       // Once we've filled the measurements, if saving signal
       // push back if any sample flagged this event as signal
       if (savesignal) {
         fSignalEventFlags.push_back(foundsignal);
       }
 
       // Save the vector of signal boxes for this event
       if (savesignal and foundsignal) {
         fSignalEventBoxes.push_back(signalboxes);
         fSampleSignalFlags.push_back(signalbitset);
       }
 
       // If all inputs are splines we can save the spline coefficients
       // for fast in memory reconfigures later.
       if (fIsAllSplines and savesignal and foundsignal) {
         // Make temp vector to push back with
         std::vector<float> coeff;
         for (size_t l = 0; l < (UInt_t)curevent->fSplineRead->GetNPar(); l++) {
           coeff.push_back(curevent->fSplineCoeff[l]);
         }
 
         // Push back to signal event splines. Kept in sync with
         // fSignalEventBoxes size.
         // int splinecount = fSignalEventSplines.size();
         fSignalEventSplines.push_back(coeff);
 
         // if (splinecount % 1000 == 0) {
         // std::cout << "Pushed Back Coeff " << splinecount << " : ";
         // for (size_t l = 0; l < fSignalEventSplines[splinecount].size(); l++)
         // {
         // std::cout << " " << fSignalEventSplines[splinecount][l];
         // }
         // std::cout << std::endl;
         // }
       }
 
       // Clean up vectors once done with this event
       signalboxes.clear();
       signalbitset.clear();
 
       // Iterate to the next event.
       curevent = curinput->NextNuisanceEvent();
       i++;
     }
 
-    curinput->RemoveCache();
+    //    curinput->RemoveCache();
 
     // Keep track of what input we are on.
     inputcount++;
   }
 
   // End of Event Loop ===============================
 
   // Now event loop is finished loop over all Measurements
   // Converting Binned events to XSec Distributions
   iterSam = fSamples.begin();
   for (; iterSam != fSamples.end(); iterSam++) {
     MeasurementBase* exp = (*iterSam);
     exp->ConvertEventRates();
   }
 
   // Print out statements on approximate memory usage for profiling.
   LOG(REC) << "Filled " << fillcount << " signal events." << std::endl;
   if (savesignal) {
     int mem =
       (  // sizeof(fSignalEventBoxes) +
         // fSignalEventBoxes.size() * sizeof(fSignalEventBoxes.at(0)) +
         sizeof(MeasurementVariableBox1D) * fillcount) *
       1E-6;
     LOG(REC) << " -> Saved " << fillcount
              << " signal boxes for faster access. (~" << mem << " MB)"
              << std::endl;
     if (fIsAllSplines and !fSignalEventSplines.empty()) {
       int splmem = sizeof(float) * fSignalEventSplines.size() *
                    fSignalEventSplines[0].size() * 1E-6;
       LOG(REC) << " -> Saved " << fillcount << " " << fSignalEventSplines.size()
                << " spline sets into memory. (~" << splmem << " MB)"
                << std::endl;
     }
   }
 
   LOG(REC) << "Time taken ReconfigureUsingManager() : "
            << time(NULL) - timestart << std::endl;
 
   // Check SignalReconfigures works for all samples
   if (savesignal) {
     double likefull = GetLikelihood();
     ReconfigureFastUsingManager();
     double likefast = GetLikelihood();
 
     if (fabs(likefull - likefast) > 0.0001)
     {
       ERROR(FTL, "Fast and Full Likelihoods DIFFER! : " << likefull << " : " << likefast);
       ERROR(FTL, "This means some samples you are using are not setup to use SignalReconfigures=1");
       ERROR(FTL, "Please turn OFF signal reconfigures.");
       throw;
     } else {
       LOG(FIT) << "Likelihoods for FULL and FAST match. Will use FAST next time." << std::endl;
     }
   }
 
   // End of reconfigure
   return;
 };
 
 //***************************************************
 void JointFCN::ReconfigureFastUsingManager() {
 //***************************************************
 
   LOG(FIT) << " -> Doing FAST using manager" << std::endl;
   // Get Start time for profilling
   int timestart = time(NULL);
 
   // Reset all samples
   MeasListConstIter iterSam = fSamples.begin();
   for (; iterSam != fSamples.end(); iterSam++) {
     MeasurementBase* exp = (*iterSam);
     exp->ResetAll();
   }
 
   // Check for saved variables if not do a full reconfigure.
   if (fSignalEventFlags.empty()) {
     ERR(WRN) << "Signal Flags Empty! Using normal manager." << std::endl;
     ReconfigureUsingManager();
     return;
   }
 
   bool fFillNuisanceEvent =
     FitPar::Config().GetParB("FullEventOnSignalReconfigure");
 
   // Setup fast vector iterators.
   std::vector<bool>::iterator inpsig_iter = fSignalEventFlags.begin();
   std::vector<std::vector<MeasurementVariableBox*> >::iterator box_iter =
     fSignalEventBoxes.begin();
   std::vector<std::vector<float> >::iterator spline_iter =
     fSignalEventSplines.begin();
   std::vector<std::vector<bool> >::iterator samsig_iter =
     fSampleSignalFlags.begin();
   int splinecount = 0;
 
   // Setup stuff for logging
   int fillcount = 0;
   int nevents = fSignalEventFlags.size();
   int countwidth = nevents / 20;
 
   // If All Splines tell splines they need a reconfigure.
   std::vector<InputHandlerBase*>::iterator inp_iter = fInputList.begin();
   if (fIsAllSplines) {
     LOG(REC) << "All Spline Inputs so using fast spline loop." << std::endl;
     for (; inp_iter != fInputList.end(); inp_iter++) {
       InputHandlerBase* curinput = (*inp_iter);
 
       // Tell each fSplineRead in BaseFitEvent to reconf next weight calc
       BaseFitEvt* curevent = curinput->FirstBaseEvent();
       if (curevent->fSplineRead)
         curevent->fSplineRead->SetNeedsReconfigure(true);
     }
   }
 
   // Loop over all possible spline inputs
   double* coreeventweights = new double[fSignalEventBoxes.size()];
   splinecount = 0;
 
   inp_iter = fInputList.begin();
   inpsig_iter = fSignalEventFlags.begin();
   spline_iter = fSignalEventSplines.begin();
 
   // Loop over all signal flags
   // For each valid signal flag add one to splinecount
   // Get Splines from that count and add to weight
   // Add splinecount
   int sigcount = 0;
   splinecount = 0;
 
   // #pragma omp parallel for shared(splinecount,sigcount)
   for (uint iinput = 0; iinput < fInputList.size(); iinput++) {
     InputHandlerBase* curinput = fInputList[iinput];
     BaseFitEvt* curevent = curinput->FirstBaseEvent();
 
     for (int i = 0; i < curinput->GetNEvents(); i++) {
       double rwweight = 0.0;
       if (fSignalEventFlags[sigcount]) {
         // Get Event Info
         if (!fIsAllSplines) {
           if (fFillNuisanceEvent)
             curinput->GetNuisanceEvent(i);
           else
             curevent = curinput->GetBaseEvent(i);
         } else {
           curevent->fSplineCoeff = &fSignalEventSplines[splinecount][0];
         }
 
         curevent->RWWeight = FitBase::GetRW()->CalcWeight(curevent);
         curevent->Weight = curevent->RWWeight * curevent->InputWeight;
         rwweight = curevent->Weight;
 
         coreeventweights[splinecount] = rwweight;
         if (countwidth && ((splinecount % countwidth) == 0)) {
           LOG(REC) << "Processed " << splinecount
                    << " event weights. W = " << rwweight << std::endl;
         }
 
         // #pragma omp atomic
         splinecount++;
       }
 
       // #pragma omp atomic
       sigcount++;
     }
   }
   LOG(SAM) << "Processed event weights." << std::endl;
 
   // #pragma omp barrier
 
   // Reset Iterators
   inpsig_iter = fSignalEventFlags.begin();
   spline_iter = fSignalEventSplines.begin();
   box_iter = fSignalEventBoxes.begin();
   samsig_iter = fSampleSignalFlags.begin();
   int nsplineweights = splinecount;
   splinecount = 0;
 
   // Start of Fast Event Loop ============================
 
   // Start input iterators
   // Loop over number of inputs
   for (int ispline = 0; ispline < nsplineweights; ispline++) {
     double rwweight = coreeventweights[ispline];
 
     // Get iterators for this event
     std::vector<bool>::iterator subsamsig_iter = (*samsig_iter).begin();
     std::vector<MeasurementVariableBox*>::iterator subbox_iter =
       (*box_iter).begin();
 
     // Loop over all sub measurements.
     std::vector<MeasurementBase*>::iterator meas_iter = fSubSampleList.begin();
     for (; meas_iter != fSubSampleList.end(); meas_iter++, subsamsig_iter++) {
       MeasurementBase* curmeas = (*meas_iter);
 
       // If event flagged as signal for this sample fill from the box.
       if (*subsamsig_iter) {
         curmeas->SetSignal(true);
         curmeas->FillHistogramsFromBox((*subbox_iter), rwweight);
 
         // Move onto next box if there is one.
         subbox_iter++;
         fillcount++;
       }
     }
 
     if (ispline % countwidth == 0) {
       LOG(REC) << "Filled " << ispline << " sample weights." << std::endl;
     }
 
     // Iterate over the main signal event containers.
     samsig_iter++;
     box_iter++;
     spline_iter++;
     splinecount++;
   }
   // End of Fast Event Loop ===================
 
   LOG(SAM) << "Filled sample distributions." << std::endl;
 
   // Now loop over all Measurements
   // Convert Binned events
   iterSam = fSamples.begin();
   for (; iterSam != fSamples.end(); iterSam++) {
     MeasurementBase* exp = (*iterSam);
     exp->ConvertEventRates();
   }
 
   // Cleanup coreeventweights
   if (fIsAllSplines) {
     delete coreeventweights;
   }
 
   // Print some reconfigure profiling.
   LOG(REC) << "Filled " << fillcount << " signal events." << std::endl;
   LOG(REC) << "Time taken ReconfigureFastUsingManager() : "
            << time(NULL) - timestart << std::endl;
 }
 
 //***************************************************
 void JointFCN::Write() {
 //***************************************************
 
   // Save a likelihood/ndof plot
   LOG(MIN) << "Writing likelihood plot.." << std::endl;
   std::vector<double> likes;
   std::vector<double> ndofs;
   std::vector<std::string> names;
   for (MeasListConstIter iter = fSamples.begin(); iter != fSamples.end();
        iter++) {
     MeasurementBase* exp = *iter;
     double like = exp->GetLikelihood();
     double ndof = exp->GetNDOF();
     std::string name = exp->GetName();
     likes.push_back(like);
     ndofs.push_back(ndof);
     names.push_back(name);
   }
   TH1D likehist = TH1D("likelihood_hist", "likelihood_hist",
                        likes.size(), 0.0, double(likes.size()));
   TH1D ndofhist  = TH1D("ndof_hist", "ndof_hist",
                         ndofs.size(), 0.0, double(ndofs.size()));
   TH1D divhist   = TH1D("likedivndof_hist", "likedivndof_hist",
                         likes.size(), 0.0, double(likes.size()));
   for (size_t i = 0; i < likehist.GetNbinsX(); i++) {
     likehist.SetBinContent(i + 1, likes[i]);
     ndofhist.SetBinContent(i + 1, ndofs[i]);
     if (ndofs[i] != 0.0) {
       divhist.SetBinContent(i + 1, likes[i] / ndofs[i]);
     }
     likehist.GetXaxis()->SetBinLabel(i + 1, names[i].c_str());
     ndofhist.GetXaxis()->SetBinLabel(i + 1, names[i].c_str());
     divhist.GetXaxis()->SetBinLabel(i + 1, names[i].c_str());
   }
   likehist.Write();
   ndofhist.Write();
   divhist.Write();
 
   // Loop over individual experiments and call Write
   LOG(MIN) << "Writing each of the data classes..." << std::endl;
   for (MeasListConstIter iter = fSamples.begin(); iter != fSamples.end();
        iter++) {
     MeasurementBase* exp = *iter;
     exp->Write();
   }
 
   // Save Pull Terms
   for (PullListConstIter iter = fPulls.begin(); iter != fPulls.end(); iter++) {
     ParamPull* pull = *iter;
     pull->Write();
   }
 
   if (FitPar::Config().GetParB("EventManager")) {
     // Get list of inputs
     std::map<int, InputHandlerBase*> fInputs =
       FitBase::EvtManager().GetInputs();
     std::map<int, InputHandlerBase*>::const_iterator iterInp;
 
     for (iterInp = fInputs.begin(); iterInp != fInputs.end(); iterInp++) {
       InputHandlerBase* input = (iterInp->second);
 
       input->GetFluxHistogram()->Write();
       input->GetXSecHistogram()->Write();
       input->GetEventHistogram()->Write();
     }
   }
 };
 
 //***************************************************
 void JointFCN::SetFakeData(std::string fakeinput) {
 //***************************************************
 
   LOG(MIN) << "Setting fake data from " << fakeinput << std::endl;
   for (MeasListConstIter iter = fSamples.begin(); iter != fSamples.end();
        iter++) {
     MeasurementBase* exp = *iter;
     exp->SetFakeDataValues(fakeinput);
   }
 
   return;
 }
 
 //***************************************************
 void JointFCN::ThrowDataToy() {
 //***************************************************
 
   for (MeasListConstIter iter = fSamples.begin(); iter != fSamples.end();
        iter++) {
     MeasurementBase* exp = *iter;
     exp->ThrowDataToy();
   }
 
   return;
 }
+
+//***************************************************
+std::vector<std::string> JointFCN::GetAllNames() {
+//***************************************************
+
+  // Vect of all likelihoods and total
+  std::vector<std::string> namevect;
+
+  // Loop over samples first
+  for (MeasListConstIter iter = fSamples.begin();
+       iter != fSamples.end();
+       iter++) {
+    MeasurementBase* exp = *iter;
+
+    // Get Likelihoods and push to vector
+    namevect.push_back(exp->GetName());
+  }
+
+
+  // Loop over pulls second
+  for (PullListConstIter iter = fPulls.begin();
+       iter != fPulls.end();
+       iter++) {
+    ParamPull* pull = *iter;
+
+    // Push back to vector
+    namevect.push_back(pull->GetName());
+  }
+
+  // Finally add the total
+  namevect.push_back("total");
+
+  return namevect;
+}
+
+//***************************************************
+std::vector<double> JointFCN::GetAllLikelihoods() {
+//***************************************************
+
+  // Vect of all likelihoods and total
+  std::vector<double> likevect;
+  double total_likelihood = 0.0;
+  LOG(MIN) << "Likelihoods : " << std::endl;
+
+  // Loop over samples first
+  for (MeasListConstIter iter = fSamples.begin();
+       iter != fSamples.end();
+       iter++) {
+    MeasurementBase* exp = *iter;
+
+    // Get Likelihoods and push to vector
+    double singlelike = exp->GetLikelihood();
+    likevect.push_back(singlelike);
+    total_likelihood += singlelike;
+
+    // Print Out
+    LOG(MIN) << "-> " << std::left << std::setw(40) << exp->GetName() << " : "
+             << singlelike << std::endl;
+  }
+
+
+  // Loop over pulls second
+  for (PullListConstIter iter = fPulls.begin();
+       iter != fPulls.end();
+       iter++) {
+    ParamPull* pull = *iter;
+
+    // Push back to vector
+    double singlelike = pull->GetLikelihood();
+    likevect.push_back(singlelike);
+    total_likelihood += singlelike;
+
+    // Print Out
+    LOG(MIN) << "-> " << std::left << std::setw(40) << pull->GetName() << " : "
+             << singlelike << std::endl;
+
+  }
+
+  // Finally add the total likelihood
+  likevect.push_back(total_likelihood);
+
+  return likevect;
+}
+
+//***************************************************
+std::vector<int> JointFCN::GetAllNDOF() {
+//***************************************************
+
+  // Vect of all ndof and total
+  std::vector<int> ndofvect;
+  int total_ndof = 0;
+
+  // Loop over samples first
+  for (MeasListConstIter iter = fSamples.begin();
+       iter != fSamples.end();
+       iter++) {
+    MeasurementBase* exp = *iter;
+
+    // Get Likelihoods and push to vector
+    int singlendof = exp->GetNDOF();
+    ndofvect.push_back(singlendof);
+    total_ndof += singlendof;
+  }
+
+
+  // Loop over pulls second
+  for (PullListConstIter iter = fPulls.begin();
+       iter != fPulls.end();
+       iter++) {
+    ParamPull* pull = *iter;
+
+    // Push back to vector
+    int singlendof = pull->GetNDOF();
+    ndofvect.push_back(singlendof);
+    total_ndof += singlendof;
+  }
+
+  // Finally add the total ndof
+  ndofvect.push_back(total_ndof);
+
+  return ndofvect;
+}
diff --git a/src/FCN/JointFCN.h b/src/FCN/JointFCN.h
index bf87424..1f47f28 100755
--- a/src/FCN/JointFCN.h
+++ b/src/FCN/JointFCN.h
@@ -1,176 +1,180 @@
 #ifndef _JOINT_FCN_H_
 #define _JOINT_FCN_H_
 /*!
  *  \addtogroup FCN
  *  @{
  */
 
 #include <iostream>
 #include <vector>
 #include <fstream>
 #include <list>
 
 // ROOT headers
 #include "TTree.h"
 #include "TH1D.h"
 #include "TH2D.h"
 #include <TMatrixDSym.h>
 #include "TGraphErrors.h"
 #include <TVectorD.h>
 #include <TMath.h>
 
 #include "FitUtils.h"
 
 // External fitter headers
 #include "MeasurementBase.h"
 #include "SampleList.h"
 
 #define GetCurrentDir getcwd
 #include "EventManager.h"
 #include "Math/Functor.h"
 #include "ParamPull.h"
 
 #include "NuisConfig.h"
 #include "NuisKey.h"
 #include "MeasurementVariableBox.h"
 #include "MeasurementVariableBox1D.h"
 
 using namespace FitUtils;
 using namespace FitBase;
 //! Main FCN Class which ROOT's joint function needs to evaulate the chi2 at each stage of the fit.
 class JointFCN
 {
- public:
+public:
 
   //! Constructor
   //! cardfile = Path to input card file listing samples
-  JointFCN(std::vector<nuiskey> samplekeys, TFile* outfile=NULL);
-  JointFCN(TFile* outfile=NULL); // Loads from global config
+  JointFCN(std::vector<nuiskey> samplekeys, TFile* outfile = NULL);
+  JointFCN(TFile* outfile = NULL); // Loads from global config
   //! Destructor
   ~JointFCN();
 
   //! Create sample list from cardfile
   void LoadSamples(std::vector<nuiskey> samplekeys);
   void LoadPulls(std::vector<nuiskey> pullkeys);
 
   //! Main Likelihood evaluation FCN
   double DoEval(const double *x);
 
   //! Func Wrapper for ROOT
   inline double operator() (const std::vector<double> & x) {
     double* x_array = new double[x.size()];
     return this->DoEval(x_array);
   };
 
   //! Func Wrapper for ROOT
   inline double operator() (const double *x) {
     return this->DoEval(x);
   };
 
   //! Create a TTree to save all dial value iterations for this FCN
   void CreateIterationTree(std::string name, FitWeight* rw);
 
   //! Fills dial values and sample likelihoods into tree
   void FillIterationTree(FitWeight* rw);
 
   //! Writes TTree to fOutput directory
   void WriteIterationTree();
 
   //! Deletes TTree
   void DestroyIterationTree();
 
   //! Get Degrees of Freedom for samples (NBins)
   int GetNDOF();
 
   //! Return NDOF wrapper
   inline unsigned int NDim() {return this->GetNDOF();};
 
   //! Reconfigure samples where we force all events to be looped over.
   void ReconfigureAllEvents() ;
 
   //! Call Reconfigure on samples.
   //! Choice of reconfigure type depends on whether dials have changed
   //! and the MC has been filled.
   void ReconfigureSamples(bool fullconfig = false);
 
   //! Call reconfigure on only signal events (defaults to all events if CurIter=0)
   void ReconfigureSignal();
 
   //! Gets likelihood for all samples in FCN (assuming uncorrelated)
   double GetLikelihood();
 
   //! Returns list of pointers to the samples
-  inline std::list<MeasurementBase*> GetSampleList(){ return fSamples; }
+  inline std::list<MeasurementBase*> GetSampleList() { return fSamples; }
 
   //! Return list of pointers to all the pulls
-  inline std::list<ParamPull*> GetPullList(){ return fPulls; };
+  inline std::list<ParamPull*> GetPullList() { return fPulls; };
 
   //! Write all samples to output DIR
   void Write();
 
   //! Set Fake data from file/MC
   void SetFakeData(std::string fakeinput);
 
   //! Reconfigure looping over duplicate inputs
   void ReconfigureUsingManager();
 
   //! Reconfigure Fast looping over duplicate inputs
   void ReconfigureFastUsingManager();
 
 
   /// Throws data according to current stats
   void ThrowDataToy();
 
-std::vector<MeasurementBase*> GetSubSampleList();
-std::vector<InputHandlerBase*> GetInputList();
+  std::vector<MeasurementBase*> GetSubSampleList();
+  std::vector<InputHandlerBase*> GetInputList();
 
- private:
+  std::vector<std::string> GetAllNames();
+  std::vector<double> GetAllLikelihoods();
+  std::vector<int> GetAllNDOF();
+
+private:
 
   //! Append the experiments to include in the fit to this list
   std::list<MeasurementBase*> fSamples;
 
   //! Append parameter pull terms to include penalties in the fit to this list
   std::list<ParamPull*> fPulls;
 
   TDirectory *fOutputDir; //!< Directory to save contents
 
   std::string fCardFile; //!< Input Card text file
 
   bool fDialChanged;  //!< Flag for if RW dials changed
   UInt_t  fCurIter;   //!< Counter for how many times reconfigure called
   bool    fMCFilled;  //!< Check MC has at least been filled once
 
   bool  fIterationTree;  //!< Tree to save RW values on each function call
   int     fNDials;         //!< Number of RW Dials in FitWeight
   double* fDialVals;       //!< Current Values of RW Dials
   double  fLikelihood;     //!< Current likelihood for joint sample likelihood
   double  fNDOF;           //!< Total NDOF
   double* fSampleLikes;    //!< Likelihoods for each individual measurement in list
   int *   fSampleNDOF;     //!< NDOF for each individual measurement in list
 
   bool fUsingEventManager; //!< Flag for doing joint comparisons
 
   std::vector< std::vector<float> > fSignalEventSplines;
   std::vector< std::vector<MeasurementVariableBox*> > fSignalEventBoxes;
   std::vector< bool > fSignalEventFlags;
   std::vector< std::vector<bool> > fSampleSignalFlags;
 
   std::vector<InputHandlerBase*> fInputList;
   std::vector<MeasurementBase*> fSubSampleList;
   bool fIsAllSplines;
 
 
   std::vector< int > fIterationCount;
   std::vector< double > fCurrentValues;
   std::vector< std::string > fNameValues;
   std::vector< std::vector<double> > fIterationValues;
   int fSampleN;
   std::string fIterationTreeName;
 
 
 
 
 };
 
 /*! @} */
 #endif // _JOINT_FCN_H_
diff --git a/src/FCN/SampleList.cxx b/src/FCN/SampleList.cxx
index 7de82f8..2e21eda 100644
--- a/src/FCN/SampleList.cxx
+++ b/src/FCN/SampleList.cxx
@@ -1,1046 +1,1056 @@
 #include "SampleList.h"
 
 #ifndef __NO_ANL__
 #include "ANL_CCQE_Evt_1DQ2_nu.h"
 #include "ANL_CCQE_XSec_1DEnu_nu.h"
 
 // ANL CC1ppip
 #include "ANL_CC1ppip_Evt_1DQ2_nu.h"
 #include "ANL_CC1ppip_Evt_1DcosmuStar_nu.h"
 #include "ANL_CC1ppip_Evt_1DcosmuStar_nu.h"
 #include "ANL_CC1ppip_Evt_1DcosthAdler_nu.h"
 #include "ANL_CC1ppip_Evt_1Dphi_nu.h"
 #include "ANL_CC1ppip_Evt_1Dppi_nu.h"
 #include "ANL_CC1ppip_Evt_1Dthpr_nu.h"
 #include "ANL_CC1ppip_XSec_1DEnu_nu.h"
 #include "ANL_CC1ppip_XSec_1DQ2_nu.h"
 // ANL CC1npip
 #include "ANL_CC1npip_Evt_1DQ2_nu.h"
 #include "ANL_CC1npip_Evt_1DcosmuStar_nu.h"
 #include "ANL_CC1npip_Evt_1Dppi_nu.h"
 #include "ANL_CC1npip_XSec_1DEnu_nu.h"
 // ANL CC1pi0
 #include "ANL_CC1pi0_Evt_1DQ2_nu.h"
 #include "ANL_CC1pi0_Evt_1DcosmuStar_nu.h"
 #include "ANL_CC1pi0_XSec_1DEnu_nu.h"
 // ANL NC1npip (mm, exotic!)
 #include "ANL_NC1npip_Evt_1Dppi_nu.h"
 // ANL NC1ppim (mm, exotic!)
 #include "ANL_NC1ppim_Evt_1DcosmuStar_nu.h"
 #include "ANL_NC1ppim_XSec_1DEnu_nu.h"
 // ANL CC2pi 1pim1pip (mm, even more exotic!)
 #include "ANL_CC2pi_1pim1pip_Evt_1Dpmu_nu.h"
 #include "ANL_CC2pi_1pim1pip_Evt_1Dppim_nu.h"
 #include "ANL_CC2pi_1pim1pip_Evt_1Dppip_nu.h"
 #include "ANL_CC2pi_1pim1pip_Evt_1Dpprot_nu.h"
 #include "ANL_CC2pi_1pim1pip_XSec_1DEnu_nu.h"
 // ANL CC2pi 1pip1pip (mm, even more exotic!)
 #include "ANL_CC2pi_1pip1pip_Evt_1Dpmu_nu.h"
 #include "ANL_CC2pi_1pip1pip_Evt_1Dpneut_nu.h"
 #include "ANL_CC2pi_1pip1pip_Evt_1DppipHigh_nu.h"
 #include "ANL_CC2pi_1pip1pip_Evt_1DppipLow_nu.h"
 #include "ANL_CC2pi_1pip1pip_XSec_1DEnu_nu.h"
 // ANL CC2pi 1pip1pi0 (mm, even more exotic!)
 #include "ANL_CC2pi_1pip1pi0_Evt_1Dpmu_nu.h"
 #include "ANL_CC2pi_1pip1pi0_Evt_1Dppi0_nu.h"
 #include "ANL_CC2pi_1pip1pi0_Evt_1Dppip_nu.h"
 #include "ANL_CC2pi_1pip1pi0_Evt_1Dpprot_nu.h"
 #include "ANL_CC2pi_1pip1pi0_XSec_1DEnu_nu.h"
 #endif
 
 #ifndef __NO_ArgoNeuT__
 // ArgoNeuT CC-inclusive
 #include "ArgoNeuT_CCInc_XSec_1Dpmu_antinu.h"
 #include "ArgoNeuT_CCInc_XSec_1Dpmu_nu.h"
 #include "ArgoNeuT_CCInc_XSec_1Dthetamu_antinu.h"
 #include "ArgoNeuT_CCInc_XSec_1Dthetamu_nu.h"
 #endif
 
 #ifndef __NO_BNL__
 // BNL CCQE
 #include "BNL_CCQE_Evt_1DQ2_nu.h"
 #include "BNL_CCQE_XSec_1DEnu_nu.h"
 // BNL CC1ppip
 #include "BNL_CC1ppip_Evt_1DQ2_nu.h"
 #include "BNL_CC1ppip_Evt_1DQ2_nu.h"
 #include "BNL_CC1ppip_Evt_1DcosthAdler_nu.h"
 #include "BNL_CC1ppip_Evt_1Dphi_nu.h"
 #include "BNL_CC1ppip_XSec_1DEnu_nu.h"
 // BNL CC1npip
 #include "BNL_CC1npip_Evt_1DQ2_nu.h"
 #include "BNL_CC1npip_XSec_1DEnu_nu.h"
 // BNL CC1pi0
 #include "BNL_CC1pi0_Evt_1DQ2_nu.h"
 #include "BNL_CC1pi0_XSec_1DEnu_nu.h"
 #endif
 
 #ifndef __NO_FNAL__
 // FNAL CCQE
 #include "FNAL_CCQE_Evt_1DQ2_nu.h"
 // FNAL CC1ppip
 #include "FNAL_CC1ppip_Evt_1DQ2_nu.h"
 #include "FNAL_CC1ppip_XSec_1DEnu_nu.h"
 #include "FNAL_CC1ppip_XSec_1DQ2_nu.h"
 // FNAL CC1ppim
 #include "FNAL_CC1ppim_XSec_1DEnu_antinu.h"
 #endif
 
 #ifndef __NO_BEBC__
 // BEBC CCQE
 #include "BEBC_CCQE_XSec_1DQ2_nu.h"
 // BEBC CC1ppip
 #include "BEBC_CC1ppip_XSec_1DEnu_nu.h"
 #include "BEBC_CC1ppip_XSec_1DQ2_nu.h"
 // BEBC CC1npip
 #include "BEBC_CC1npip_XSec_1DEnu_nu.h"
 #include "BEBC_CC1npip_XSec_1DQ2_nu.h"
 // BEBC CC1pi0
 #include "BEBC_CC1pi0_XSec_1DEnu_nu.h"
 #include "BEBC_CC1pi0_XSec_1DQ2_nu.h"
 // BEBC CC1npim
 #include "BEBC_CC1npim_XSec_1DEnu_antinu.h"
 #include "BEBC_CC1npim_XSec_1DQ2_antinu.h"
 // BEBC CC1ppim
 #include "BEBC_CC1ppim_XSec_1DEnu_antinu.h"
 #include "BEBC_CC1ppim_XSec_1DQ2_antinu.h"
 #endif
 
 #ifndef __NO_GGM__
 // GGM CC1ppip
 #include "GGM_CC1ppip_Evt_1DQ2_nu.h"
 #include "GGM_CC1ppip_XSec_1DEnu_nu.h"
 #endif
 
 #ifndef __NO_MiniBooNE__
 // MiniBooNE CCQE
 #include "MiniBooNE_CCQE_XSec_1DQ2_antinu.h"
 #include "MiniBooNE_CCQE_XSec_1DQ2_nu.h"
 #include "MiniBooNE_CCQE_XSec_2DTcos_antinu.h"
 #include "MiniBooNE_CCQE_XSec_2DTcos_antinu.h"
 #include "MiniBooNE_CCQE_XSec_2DTcos_nu.h"
 
 // MiniBooNE CC1pi+ 1D
 #include "MiniBooNE_CC1pip_XSec_1DEnu_nu.h"
 #include "MiniBooNE_CC1pip_XSec_1DQ2_nu.h"
 #include "MiniBooNE_CC1pip_XSec_1DTpi_nu.h"
 #include "MiniBooNE_CC1pip_XSec_1DTu_nu.h"
 // MiniBooNE CC1pi+ 2D
 #include "MiniBooNE_CC1pip_XSec_2DQ2Enu_nu.h"
 #include "MiniBooNE_CC1pip_XSec_2DTpiCospi_nu.h"
 #include "MiniBooNE_CC1pip_XSec_2DTpiEnu_nu.h"
 #include "MiniBooNE_CC1pip_XSec_2DTuCosmu_nu.h"
 #include "MiniBooNE_CC1pip_XSec_2DTuEnu_nu.h"
 
 // MiniBooNE CC1pi0
 #include "MiniBooNE_CC1pi0_XSec_1DEnu_nu.h"
 #include "MiniBooNE_CC1pi0_XSec_1DQ2_nu.h"
 #include "MiniBooNE_CC1pi0_XSec_1DTu_nu.h"
 #include "MiniBooNE_CC1pi0_XSec_1Dcosmu_nu.h"
 #include "MiniBooNE_CC1pi0_XSec_1Dcospi0_nu.h"
 #include "MiniBooNE_CC1pi0_XSec_1Dppi0_nu.h"
 #include "MiniBooNE_NC1pi0_XSec_1Dcospi0_antinu.h"
 #include "MiniBooNE_NC1pi0_XSec_1Dcospi0_nu.h"
 #include "MiniBooNE_NC1pi0_XSec_1Dppi0_antinu.h"
 #include "MiniBooNE_NC1pi0_XSec_1Dppi0_nu.h"
 
 // MiniBooNE NC1pi0
 //#include "MiniBooNE_NCpi0_XSec_1Dppi0_nu.h"
 
 // MiniBooNE NCEL
 #include "MiniBooNE_NCEL_XSec_Treco_nu.h"
 #endif
 
 #ifndef __NO_MINERvA__
 // MINERvA CCQE
 #include "MINERvA_CCQE_XSec_1DQ2_antinu.h"
 #include "MINERvA_CCQE_XSec_1DQ2_joint.h"
 #include "MINERvA_CCQE_XSec_1DQ2_nu.h"
 
 // MINERvA CC0pi
 #include "MINERvA_CC0pi_XSec_1DEe_nue.h"
 #include "MINERvA_CC0pi_XSec_1DQ2_nu_proton.h"
 #include "MINERvA_CC0pi_XSec_1DQ2_nue.h"
 #include "MINERvA_CC0pi_XSec_1DThetae_nue.h"
 
 // MINERvA CC1pi+
 #include "MINERvA_CC1pip_XSec_1DTpi_20deg_nu.h"
 #include "MINERvA_CC1pip_XSec_1DTpi_nu.h"
 #include "MINERvA_CC1pip_XSec_1Dth_20deg_nu.h"
 #include "MINERvA_CC1pip_XSec_1Dth_nu.h"
 // 2017 data update
 #include "MINERvA_CC1pip_XSec_1D_2017Update.h"
 
 // MINERvA CCNpi+
 #include "MINERvA_CCNpip_XSec_1DEnu_nu.h"
 #include "MINERvA_CCNpip_XSec_1DQ2_nu.h"
 #include "MINERvA_CCNpip_XSec_1DTpi_nu.h"
 #include "MINERvA_CCNpip_XSec_1Dpmu_nu.h"
 #include "MINERvA_CCNpip_XSec_1Dth_nu.h"
 #include "MINERvA_CCNpip_XSec_1Dthmu_nu.h"
 
 // MINERvA CC1pi0
 #include "MINERvA_CC1pi0_XSec_1DEnu_antinu.h"
 #include "MINERvA_CC1pi0_XSec_1DQ2_antinu.h"
 #include "MINERvA_CC1pi0_XSec_1DTpi0_antinu.h"
 #include "MINERvA_CC1pi0_XSec_1Dpmu_antinu.h"
 #include "MINERvA_CC1pi0_XSec_1Dppi0_antinu.h"
 #include "MINERvA_CC1pi0_XSec_1Dth_antinu.h"
 #include "MINERvA_CC1pi0_XSec_1Dthmu_antinu.h"
 
 // MINERvA CC1pi0 neutrino
 #include "MINERvA_CC1pi0_XSec_1D_nu.h"
 
 // MINERvA CCINC
 #include "MINERvA_CCinc_XSec_1DEnu_ratio.h"
 #include "MINERvA_CCinc_XSec_1Dx_ratio.h"
 #include "MINERvA_CCinc_XSec_2DEavq3_nu.h"
 
 // MINERvA CCDIS
 #include "MINERvA_CCDIS_XSec_1DEnu_ratio.h"
 #include "MINERvA_CCDIS_XSec_1Dx_ratio.h"
 
 // MINERvA CCCOH pion
 #include "MINERvA_CCCOHPI_XSec_1DEnu_antinu.h"
-#include "MINERvA_CCCOHPI_XSec_1DEnu_nu.h"
+#include "MINERvA_CCCOHPI_XSec_1DEnu_antinu.h"
 #include "MINERvA_CCCOHPI_XSec_1DEpi_antinu.h"
 #include "MINERvA_CCCOHPI_XSec_1DQ2_antinu.h"
 
 #include "MINERvA_CCCOHPI_XSec_1DEpi_nu.h"
-#include "MINERvA_CCCOHPI_XSec_1Dth_antinu.h"
+#include "MINERvA_CCCOHPI_XSec_1Dth_nu.h"
 #include "MINERvA_CCCOHPI_XSec_1Dth_nu.h"
 #include "MINERvA_CCCOHPI_XSec_1DQ2_nu.h"
 
+#include "MINERvA_CCCOHPI_XSec_joint.h"
+
 #include "MINERvA_CC0pi_XSec_1DQ2_TgtRatio_nu.h"
 #include "MINERvA_CC0pi_XSec_1DQ2_Tgt_nu.h"
 
 #include "MINERvA_CC0pi_XSec_2Dptpx_nu.h"
 #include "MINERvA_CC0pi_XSec_2Dptpx_antinu.h"
 
 #endif
 
 #ifndef __NO_T2K__
 // T2K CC0pi
 #include "T2K_CC0pi_XSec_2DPcos_nu.h"
 
 // T2K CC1pi+ on CH
 #include "T2K_CC1pip_CH_XSec_1DQ2_nu.h"
 #include "T2K_CC1pip_CH_XSec_1DWrec_nu.h"
 #include "T2K_CC1pip_CH_XSec_1Dpmu_nu.h"
 #include "T2K_CC1pip_CH_XSec_1Dppi_nu.h"
 #include "T2K_CC1pip_CH_XSec_1Dq3_nu.h"
 #include "T2K_CC1pip_CH_XSec_1Dthmupi_nu.h"
 #include "T2K_CC1pip_CH_XSec_1Dthpi_nu.h"
 #include "T2K_CC1pip_CH_XSec_1Dthq3pi_nu.h"
 
 // T2K CC1pi+ on H2O
 #include "T2K_CC1pip_H2O_XSec_1DEnuDelta_nu.h"
 #include "T2K_CC1pip_H2O_XSec_1DEnuMB_nu.h"
 #include "T2K_CC1pip_H2O_XSec_1Dcosmu_nu.h"
 #include "T2K_CC1pip_H2O_XSec_1Dcosmupi_nu.h"
 #include "T2K_CC1pip_H2O_XSec_1Dcospi_nu.h"
 #include "T2K_CC1pip_H2O_XSec_1Dpmu_nu.h"
 #include "T2K_CC1pip_H2O_XSec_1Dppi_nu.h"
 
 // T2K STV CC0pi
 #include "T2K_CC0pinp_STV_XSec_1Ddpt_nu.h"
 
 #include "T2K_CC0pi_XSec_2DPcos_nu_nonuniform.h"
 
 #endif
 
 #ifndef __NO_SciBooNE__
 
 // SciBooNE COH studies
 #include "SciBooNE_CCCOH_1TRK_1DQ2_nu.h"
 #include "SciBooNE_CCCOH_MuPiNoVA_1DQ2_nu.h"
 #include "SciBooNE_CCCOH_MuPiNoVA_1Dthetapi_nu.h"
 #include "SciBooNE_CCCOH_MuPiNoVA_1Dthetapr_nu.h"
 #include "SciBooNE_CCCOH_MuPiVA_1DQ2_nu.h"
 #include "SciBooNE_CCCOH_MuPr_1DQ2_nu.h"
 #include "SciBooNE_CCCOH_STOPFINAL_1DQ2_nu.h"
 #include "SciBooNE_CCCOH_STOP_NTrks_nu.h"
 #endif
 
 #ifndef __NO_K2K__
 // K2K NC1pi0
 #include "K2K_NC1pi0_Evt_1Dppi0_nu.h"
 #endif
 
 // MC Studies
 #include "ExpMultDist_CCQE_XSec_1DVar_FakeStudy.h"
 #include "ExpMultDist_CCQE_XSec_2DVar_FakeStudy.h"
 #include "MCStudy_CCQEHistograms.h"
 
 #include "GenericFlux_Tester.h"
 #include "GenericFlux_Vectors.h"
 
 #include "ElectronFlux_FlatTree.h"
 #include "ElectronScattering_DurhamData.h"
 #include "MCStudy_KaonPreSelection.h"
 #include "MCStudy_MuonValidation.h"
 
 #include "OfficialNIWGPlots.h"
 #include "T2K2017_FakeData.h"
 
 #include "Simple_Osc.h"
 #include "Smear_SVDUnfold_Propagation_Osc.h"
 
 #include "FitWeight.h"
 
 #include "NuisConfig.h"
 #include "NuisKey.h"
 
 
 
 //! Functions to make it easier for samples to be created and handled.
 namespace SampleUtils {
 
 //! Create a given sample given its name, file, type, fakdata(fkdt) file and the
 //! current rw engine and push it back into the list fChain.
 MeasurementBase* CreateSample(std::string name, std::string file,
                               std::string type, std::string fkdt,
                               FitWeight* rw) {
   nuiskey samplekey = Config::CreateKey("sample");
-  samplekey.AddS("name", name);
-  samplekey.AddS("input", file);
-  samplekey.AddS("type", type);
+  samplekey.Set("name", name);
+  samplekey.Set("input", file);
+  samplekey.Set("type", type);
 
   return CreateSample(samplekey);
 }
 
 MeasurementBase* CreateSample(nuiskey samplekey) {
   FitWeight* rw = FitBase::GetRW();
   std::string name = samplekey.GetS("name");
   std::string file = samplekey.GetS("input");
   std::string type = samplekey.GetS("type");
   std::string fkdt = "";
 
 /*
    ANL CCQE Samples
 */
 
 #ifndef __NO_ANL__
   if (!name.compare("ANL_CCQE_XSec_1DEnu_nu") ||
       !name.compare("ANL_CCQE_XSec_1DEnu_nu_PRD26") ||
       !name.compare("ANL_CCQE_XSec_1DEnu_nu_PRL31") ||
       !name.compare("ANL_CCQE_XSec_1DEnu_nu_PRD16")) {
     return (new ANL_CCQE_XSec_1DEnu_nu(samplekey));
   } else if (!name.compare("ANL_CCQE_Evt_1DQ2_nu") ||
              !name.compare("ANL_CCQE_Evt_1DQ2_nu_PRL31") ||
              !name.compare("ANL_CCQE_Evt_1DQ2_nu_PRD26") ||
              !name.compare("ANL_CCQE_Evt_1DQ2_nu_PRD16")) {
     return (new ANL_CCQE_Evt_1DQ2_nu(samplekey));
     /*
       ANL CC1ppip samples
     */
   } else if (!name.compare("ANL_CC1ppip_XSec_1DEnu_nu") ||
              !name.compare("ANL_CC1ppip_XSec_1DEnu_nu_W14Cut") ||
              !name.compare("ANL_CC1ppip_XSec_1DEnu_nu_Uncorr") ||
              !name.compare("ANL_CC1ppip_XSec_1DEnu_nu_W14Cut_Uncorr") ||
              !name.compare("ANL_CC1ppip_XSec_1DEnu_nu_W16Cut_Uncorr")) {
     return (new ANL_CC1ppip_XSec_1DEnu_nu(samplekey));
   } else if (!name.compare("ANL_CC1ppip_XSec_1DQ2_nu")) {
     return (new ANL_CC1ppip_XSec_1DQ2_nu(samplekey));
   } else if (!name.compare("ANL_CC1ppip_Evt_1DQ2_nu") ||
              !name.compare("ANL_CC1ppip_Evt_1DQ2_nu_W14Cut")) {
     return (new ANL_CC1ppip_Evt_1DQ2_nu(samplekey));
   } else if (!name.compare("ANL_CC1ppip_Evt_1Dppi_nu")) {
     return (new ANL_CC1ppip_Evt_1Dppi_nu(samplekey));
   } else if (!name.compare("ANL_CC1ppip_Evt_1Dthpr_nu")) {
     return (new ANL_CC1ppip_Evt_1Dthpr_nu(samplekey));
   } else if (!name.compare("ANL_CC1ppip_Evt_1DcosmuStar_nu")) {
     return (new ANL_CC1ppip_Evt_1DcosmuStar_nu(samplekey));
   } else if (!name.compare("ANL_CC1ppip_Evt_1DcosthAdler_nu")) {
     return (new ANL_CC1ppip_Evt_1DcosthAdler_nu(samplekey));
   } else if (!name.compare("ANL_CC1ppip_Evt_1Dphi_nu")) {
     return (new ANL_CC1ppip_Evt_1Dphi_nu(samplekey));
     /*
       ANL CC1npip sample
     */
   } else if (!name.compare("ANL_CC1npip_XSec_1DEnu_nu") ||
              !name.compare("ANL_CC1npip_XSec_1DEnu_nu_W14Cut") ||
              !name.compare("ANL_CC1npip_XSec_1DEnu_nu_Uncorr") ||
              !name.compare("ANL_CC1npip_XSec_1DEnu_nu_W14Cut_Uncorr") ||
              !name.compare("ANL_CC1npip_XSec_1DEnu_nu_W16Cut_Uncorr")) {
     return (new ANL_CC1npip_XSec_1DEnu_nu(samplekey));
   } else if (!name.compare("ANL_CC1npip_Evt_1DQ2_nu") ||
              !name.compare("ANL_CC1npip_Evt_1DQ2_nu_W14Cut")) {
     return (new ANL_CC1npip_Evt_1DQ2_nu(samplekey));
   } else if (!name.compare("ANL_CC1npip_Evt_1Dppi_nu")) {
     return (new ANL_CC1npip_Evt_1Dppi_nu(samplekey));
   } else if (!name.compare("ANL_CC1npip_Evt_1DcosmuStar_nu")) {
     return (new ANL_CC1npip_Evt_1DcosmuStar_nu(samplekey));
     /*
       ANL CC1pi0 sample
     */
   } else if (!name.compare("ANL_CC1pi0_XSec_1DEnu_nu") ||
              !name.compare("ANL_CC1pi0_XSec_1DEnu_nu_W14Cut") ||
              !name.compare("ANL_CC1pi0_XSec_1DEnu_nu_Uncorr") ||
              !name.compare("ANL_CC1pi0_XSec_1DEnu_nu_W14Cut_Uncorr") ||
              !name.compare("ANL_CC1pi0_XSec_1DEnu_nu_W16Cut_Uncorr")) {
     return (new ANL_CC1pi0_XSec_1DEnu_nu(samplekey));
   } else if (!name.compare("ANL_CC1pi0_Evt_1DQ2_nu") ||
              !name.compare("ANL_CC1pi0_Evt_1DQ2_nu_W14Cut")) {
     return (new ANL_CC1pi0_Evt_1DQ2_nu(samplekey));
   } else if (!name.compare("ANL_CC1pi0_Evt_1DcosmuStar_nu")) {
     return (new ANL_CC1pi0_Evt_1DcosmuStar_nu(samplekey));
     /*
       ANL NC1npip sample
     */
   } else if (!name.compare("ANL_NC1npip_Evt_1Dppi_nu")) {
     return (new ANL_NC1npip_Evt_1Dppi_nu(samplekey));
     /*
       ANL NC1ppim sample
     */
   } else if (!name.compare("ANL_NC1ppim_XSec_1DEnu_nu")) {
     return (new ANL_NC1ppim_XSec_1DEnu_nu(samplekey));
   } else if (!name.compare("ANL_NC1ppim_Evt_1DcosmuStar_nu")) {
     return (new ANL_NC1ppim_Evt_1DcosmuStar_nu(samplekey));
     /*
       ANL CC2pi sample
     */
   } else if (!name.compare("ANL_CC2pi_1pim1pip_XSec_1DEnu_nu")) {
     return (new ANL_CC2pi_1pim1pip_XSec_1DEnu_nu(samplekey));
   } else if (!name.compare("ANL_CC2pi_1pim1pip_Evt_1Dpmu_nu")) {
     return (new ANL_CC2pi_1pim1pip_Evt_1Dpmu_nu(samplekey));
   } else if (!name.compare("ANL_CC2pi_1pim1pip_Evt_1Dppip_nu")) {
     return (new ANL_CC2pi_1pim1pip_Evt_1Dppip_nu(samplekey));
   } else if (!name.compare("ANL_CC2pi_1pim1pip_Evt_1Dppim_nu")) {
     return (new ANL_CC2pi_1pim1pip_Evt_1Dppim_nu(samplekey));
   } else if (!name.compare("ANL_CC2pi_1pim1pip_Evt_1Dpprot_nu")) {
     return (new ANL_CC2pi_1pim1pip_Evt_1Dpprot_nu(samplekey));
 
   } else if (!name.compare("ANL_CC2pi_1pip1pip_XSec_1DEnu_nu")) {
     return (new ANL_CC2pi_1pip1pip_XSec_1DEnu_nu(samplekey));
   } else if (!name.compare("ANL_CC2pi_1pip1pip_Evt_1Dpmu_nu")) {
     return (new ANL_CC2pi_1pip1pip_Evt_1Dpmu_nu(samplekey));
   } else if (!name.compare("ANL_CC2pi_1pip1pip_Evt_1Dpneut_nu")) {
     return (new ANL_CC2pi_1pip1pip_Evt_1Dpneut_nu(samplekey));
   } else if (!name.compare("ANL_CC2pi_1pip1pip_Evt_1DppipHigh_nu")) {
     return (new ANL_CC2pi_1pip1pip_Evt_1DppipHigh_nu(samplekey));
   } else if (!name.compare("ANL_CC2pi_1pip1pip_Evt_1DppipLow_nu")) {
     return (new ANL_CC2pi_1pip1pip_Evt_1DppipLow_nu(samplekey));
 
   } else if (!name.compare("ANL_CC2pi_1pip1pi0_XSec_1DEnu_nu")) {
     return (new ANL_CC2pi_1pip1pi0_XSec_1DEnu_nu(samplekey));
   } else if (!name.compare("ANL_CC2pi_1pip1pi0_Evt_1Dpmu_nu")) {
     return (new ANL_CC2pi_1pip1pi0_Evt_1Dpmu_nu(samplekey));
   } else if (!name.compare("ANL_CC2pi_1pip1pi0_Evt_1Dppip_nu")) {
     return (new ANL_CC2pi_1pip1pi0_Evt_1Dppip_nu(samplekey));
   } else if (!name.compare("ANL_CC2pi_1pip1pi0_Evt_1Dppi0_nu")) {
     return (new ANL_CC2pi_1pip1pi0_Evt_1Dppi0_nu(samplekey));
   } else if (!name.compare("ANL_CC2pi_1pip1pi0_Evt_1Dpprot_nu")) {
     return (new ANL_CC2pi_1pip1pi0_Evt_1Dpprot_nu(samplekey));
 
     /*
       ArgoNeut Samples
     */
   } else
 #endif
 #ifndef __NO_ArgoNeuT__
       if (!name.compare("ArgoNeuT_CCInc_XSec_1Dpmu_antinu")) {
     return (new ArgoNeuT_CCInc_XSec_1Dpmu_antinu(samplekey));
   } else if (!name.compare("ArgoNeuT_CCInc_XSec_1Dpmu_nu")) {
     return (new ArgoNeuT_CCInc_XSec_1Dpmu_nu(samplekey));
   } else if (!name.compare("ArgoNeuT_CCInc_XSec_1Dthetamu_antinu")) {
     return (new ArgoNeuT_CCInc_XSec_1Dthetamu_antinu(samplekey));
   } else if (!name.compare("ArgoNeuT_CCInc_XSec_1Dthetamu_nu")) {
     return (new ArgoNeuT_CCInc_XSec_1Dthetamu_nu(samplekey));
 
     /*
       BNL Samples
     */
   } else
 #endif
 #ifndef __NO_BNL__
       if (!name.compare("BNL_CCQE_XSec_1DEnu_nu")) {
     return (new BNL_CCQE_XSec_1DEnu_nu(samplekey));
   } else if (!name.compare("BNL_CCQE_Evt_1DQ2_nu")) {
     return (new BNL_CCQE_Evt_1DQ2_nu(samplekey));
 
     /*
       BNL CC1ppip samples
     */
   } else if (!name.compare("BNL_CC1ppip_XSec_1DEnu_nu") ||
              !name.compare("BNL_CC1ppip_XSec_1DEnu_nu_Uncorr") ||
              !name.compare("BNL_CC1ppip_XSec_1DEnu_nu_W14Cut") ||
              !name.compare("BNL_CC1ppip_XSec_1DEnu_nu_W14Cut_Uncorr")) {
     return (new BNL_CC1ppip_XSec_1DEnu_nu(samplekey));
   } else if (!name.compare("BNL_CC1ppip_Evt_1DQ2_nu") ||
              !name.compare("BNL_CC1ppip_Evt_1DQ2_nu_W14Cut")) {
     return (new BNL_CC1ppip_Evt_1DQ2_nu(samplekey));
   } else if (!name.compare("BNL_CC1ppip_Evt_1DcosthAdler_nu")) {
     return (new BNL_CC1ppip_Evt_1DcosthAdler_nu(samplekey));
   } else if (!name.compare("BNL_CC1ppip_Evt_1Dphi_nu")) {
     return (new BNL_CC1ppip_Evt_1Dphi_nu(samplekey));
 
     /*
       BNL CC1npip samples
     */
   } else if (!name.compare("BNL_CC1npip_XSec_1DEnu_nu") ||
              !name.compare("BNL_CC1npip_XSec_1DEnu_nu_Uncorr")) {
     return (new BNL_CC1npip_XSec_1DEnu_nu(samplekey));
   } else if (!name.compare("BNL_CC1npip_Evt_1DQ2_nu")) {
     return (new BNL_CC1npip_Evt_1DQ2_nu(samplekey));
     /*
       BNL CC1pi0 samples
     */
   } else if (!name.compare("BNL_CC1pi0_XSec_1DEnu_nu")) {
     return (new BNL_CC1pi0_XSec_1DEnu_nu(samplekey));
   } else if (!name.compare("BNL_CC1pi0_Evt_1DQ2_nu")) {
     return (new BNL_CC1pi0_Evt_1DQ2_nu(samplekey));
 
     /*
       FNAL Samples
     */
   } else
 #endif
 #ifndef __NO_FNAL__
       if (!name.compare("FNAL_CCQE_Evt_1DQ2_nu")) {
     return (new FNAL_CCQE_Evt_1DQ2_nu(samplekey));
     /*
       FNAL CC1ppip
     */
   } else if (!name.compare("FNAL_CC1ppip_XSec_1DEnu_nu")) {
     return (new FNAL_CC1ppip_XSec_1DEnu_nu(samplekey));
   } else if (!name.compare("FNAL_CC1ppip_XSec_1DQ2_nu")) {
     return (new FNAL_CC1ppip_XSec_1DQ2_nu(samplekey));
   } else if (!name.compare("FNAL_CC1ppip_Evt_1DQ2_nu")) {
     return (new FNAL_CC1ppip_Evt_1DQ2_nu(samplekey));
     /*
       FNAL CC1ppim
     */
   } else if (!name.compare("FNAL_CC1ppim_XSec_1DEnu_antinu")) {
     return (new FNAL_CC1ppim_XSec_1DEnu_antinu(samplekey));
 
     /*
       BEBC Samples
     */
   } else
 #endif
 #ifndef __NO_BEBC__
       if (!name.compare("BEBC_CCQE_XSec_1DQ2_nu")) {
     return (new BEBC_CCQE_XSec_1DQ2_nu(samplekey));
     /*
       BEBC CC1ppip samples
     */
   } else if (!name.compare("BEBC_CC1ppip_XSec_1DEnu_nu")) {
     return (new BEBC_CC1ppip_XSec_1DEnu_nu(samplekey));
   } else if (!name.compare("BEBC_CC1ppip_XSec_1DQ2_nu")) {
     return (new BEBC_CC1ppip_XSec_1DQ2_nu(samplekey));
     /*
       BEBC CC1npip samples
     */
   } else if (!name.compare("BEBC_CC1npip_XSec_1DEnu_nu")) {
     return (new BEBC_CC1npip_XSec_1DEnu_nu(samplekey));
   } else if (!name.compare("BEBC_CC1npip_XSec_1DQ2_nu")) {
     return (new BEBC_CC1npip_XSec_1DQ2_nu(samplekey));
     /*
       BEBC CC1pi0 samples
     */
   } else if (!name.compare("BEBC_CC1pi0_XSec_1DEnu_nu")) {
     return (new BEBC_CC1pi0_XSec_1DEnu_nu(samplekey));
   } else if (!name.compare("BEBC_CC1pi0_XSec_1DQ2_nu")) {
     return (new BEBC_CC1pi0_XSec_1DQ2_nu(samplekey));
     /*
       BEBC CC1npim samples
     */
   } else if (!name.compare("BEBC_CC1npim_XSec_1DEnu_antinu")) {
     return (new BEBC_CC1npim_XSec_1DEnu_antinu(samplekey));
   } else if (!name.compare("BEBC_CC1npim_XSec_1DQ2_antinu")) {
     return (new BEBC_CC1npim_XSec_1DQ2_antinu(samplekey));
     /*
       BEBC CC1ppim samples
     */
   } else if (!name.compare("BEBC_CC1ppim_XSec_1DEnu_antinu")) {
     return (new BEBC_CC1ppim_XSec_1DEnu_antinu(samplekey));
   } else if (!name.compare("BEBC_CC1ppim_XSec_1DQ2_antinu")) {
     return (new BEBC_CC1ppim_XSec_1DQ2_antinu(samplekey));
 
     /*
       GGM CC1ppip samples
     */
   } else
 #endif
 #ifndef __NO_GGM__
       if (!name.compare("GGM_CC1ppip_XSec_1DEnu_nu")) {
     return (new GGM_CC1ppip_XSec_1DEnu_nu(samplekey));
   } else if (!name.compare("GGM_CC1ppip_Evt_1DQ2_nu")) {
     return (new GGM_CC1ppip_Evt_1DQ2_nu(samplekey));
 
     /*
       MiniBooNE Samples
     */
     /*
       CCQE
     */
   } else
 #endif
 #ifndef __NO_MiniBooNE__
       if (!name.compare("MiniBooNE_CCQE_XSec_1DQ2_nu") ||
           !name.compare("MiniBooNE_CCQELike_XSec_1DQ2_nu")) {
     return (new MiniBooNE_CCQE_XSec_1DQ2_nu(samplekey));
   } else if (!name.compare("MiniBooNE_CCQE_XSec_1DQ2_antinu") ||
              !name.compare("MiniBooNE_CCQELike_XSec_1DQ2_antinu") ||
              !name.compare("MiniBooNE_CCQE_CTarg_XSec_1DQ2_antinu")) {
     return (new MiniBooNE_CCQE_XSec_1DQ2_antinu(samplekey));
 
   } else if (!name.compare("MiniBooNE_CCQE_XSec_2DTcos_nu") ||
              !name.compare("MiniBooNE_CCQELike_XSec_2DTcos_nu")) {
     return (new MiniBooNE_CCQE_XSec_2DTcos_nu(samplekey));
 
   } else if (!name.compare("MiniBooNE_CCQE_XSec_2DTcos_antinu") ||
              !name.compare("MiniBooNE_CCQELike_XSec_2DTcos_antinu")) {
     return (new MiniBooNE_CCQE_XSec_2DTcos_antinu(samplekey));
 
     /*
       MiniBooNE CC1pi+
     */
     // 1D
   } else if (!name.compare("MiniBooNE_CC1pip_XSec_1DEnu_nu")) {
     return (new MiniBooNE_CC1pip_XSec_1DEnu_nu(samplekey));
 
   } else if (!name.compare("MiniBooNE_CC1pip_XSec_1DQ2_nu")) {
     return (new MiniBooNE_CC1pip_XSec_1DQ2_nu(samplekey));
 
   } else if (!name.compare("MiniBooNE_CC1pip_XSec_1DTpi_nu")) {
     return (new MiniBooNE_CC1pip_XSec_1DTpi_nu(samplekey));
 
   } else if (!name.compare("MiniBooNE_CC1pip_XSec_1DTu_nu")) {
     return (new MiniBooNE_CC1pip_XSec_1DTu_nu(samplekey));
 
     // 2D
   } else if (!name.compare("MiniBooNE_CC1pip_XSec_2DQ2Enu_nu")) {
     return (new MiniBooNE_CC1pip_XSec_2DQ2Enu_nu(samplekey));
 
   } else if (!name.compare("MiniBooNE_CC1pip_XSec_2DTpiCospi_nu")) {
     return (new MiniBooNE_CC1pip_XSec_2DTpiCospi_nu(samplekey));
 
   } else if (!name.compare("MiniBooNE_CC1pip_XSec_2DTpiEnu_nu")) {
     return (new MiniBooNE_CC1pip_XSec_2DTpiEnu_nu(samplekey));
 
   } else if (!name.compare("MiniBooNE_CC1pip_XSec_2DTuCosmu_nu")) {
     return (new MiniBooNE_CC1pip_XSec_2DTuCosmu_nu(samplekey));
 
   } else if (!name.compare("MiniBooNE_CC1pip_XSec_2DTuEnu_nu")) {
     return (new MiniBooNE_CC1pip_XSec_2DTuEnu_nu(samplekey));
 
     /*
       MiniBooNE CC1pi0
     */
   } else if (!name.compare("MiniBooNE_CC1pi0_XSec_1DEnu_nu")) {
     return (new MiniBooNE_CC1pi0_XSec_1DEnu_nu(samplekey));
 
   } else if (!name.compare("MiniBooNE_CC1pi0_XSec_1DQ2_nu")) {
     return (new MiniBooNE_CC1pi0_XSec_1DQ2_nu(samplekey));
 
   } else if (!name.compare("MiniBooNE_CC1pi0_XSec_1DTu_nu")) {
     return (new MiniBooNE_CC1pi0_XSec_1DTu_nu(samplekey));
 
   } else if (!name.compare("MiniBooNE_CC1pi0_XSec_1Dcosmu_nu")) {
     return (new MiniBooNE_CC1pi0_XSec_1Dcosmu_nu(samplekey));
 
   } else if (!name.compare("MiniBooNE_CC1pi0_XSec_1Dcospi0_nu")) {
     return (new MiniBooNE_CC1pi0_XSec_1Dcospi0_nu(samplekey));
 
   } else if (!name.compare("MiniBooNE_CC1pi0_XSec_1Dppi0_nu")) {
     return (new MiniBooNE_CC1pi0_XSec_1Dppi0_nu(samplekey));
 
   } else if (!name.compare("MiniBooNE_NC1pi0_XSec_1Dcospi0_antinu") ||
              !name.compare("MiniBooNE_NC1pi0_XSec_1Dcospi0_rhc")) {
     return (new MiniBooNE_NC1pi0_XSec_1Dcospi0_antinu(samplekey));
 
   } else if (!name.compare("MiniBooNE_NC1pi0_XSec_1Dcospi0_nu") ||
              !name.compare("MiniBooNE_NC1pi0_XSec_1Dcospi0_fhc")) {
     return (new MiniBooNE_NC1pi0_XSec_1Dcospi0_nu(samplekey));
 
   } else if (!name.compare("MiniBooNE_NC1pi0_XSec_1Dppi0_antinu") ||
              !name.compare("MiniBooNE_NC1pi0_XSec_1Dppi0_rhc")) {
     return (new MiniBooNE_NC1pi0_XSec_1Dppi0_antinu(samplekey));
 
   } else if (!name.compare("MiniBooNE_NC1pi0_XSec_1Dppi0_nu") ||
              !name.compare("MiniBooNE_NC1pi0_XSec_1Dppi0_fhc")) {
     return (new MiniBooNE_NC1pi0_XSec_1Dppi0_nu(samplekey));
 
     /*
       MiniBooNE NCEL
     */
   } else if (!name.compare("MiniBooNE_NCEL_XSec_Treco_nu")) {
     return (new MiniBooNE_NCEL_XSec_Treco_nu(samplekey));
 
     /*
     MINERvA Samples
     */
   } else
 #endif
 #ifndef __NO_MINERvA__
       if (!name.compare("MINERvA_CCQE_XSec_1DQ2_nu") ||
           !name.compare("MINERvA_CCQE_XSec_1DQ2_nu_20deg") ||
           !name.compare("MINERvA_CCQE_XSec_1DQ2_nu_oldflux") ||
           !name.compare("MINERvA_CCQE_XSec_1DQ2_nu_20deg_oldflux")) {
     return (new MINERvA_CCQE_XSec_1DQ2_nu(samplekey));
 
   } else if (!name.compare("MINERvA_CCQE_XSec_1DQ2_antinu") ||
              !name.compare("MINERvA_CCQE_XSec_1DQ2_antinu_20deg") ||
              !name.compare("MINERvA_CCQE_XSec_1DQ2_antinu_oldflux") ||
              !name.compare("MINERvA_CCQE_XSec_1DQ2_antinu_20deg_oldflux")) {
     return (new MINERvA_CCQE_XSec_1DQ2_antinu(samplekey));
 
   } else if (!name.compare("MINERvA_CCQE_XSec_1DQ2_joint_oldflux") ||
              !name.compare("MINERvA_CCQE_XSec_1DQ2_joint_20deg_oldflux") ||
              !name.compare("MINERvA_CCQE_XSec_1DQ2_joint") ||
              !name.compare("MINERvA_CCQE_XSec_1DQ2_joint_20deg")) {
     return (new MINERvA_CCQE_XSec_1DQ2_joint(samplekey));
 
   } else if (!name.compare("MINERvA_CC0pi_XSec_1DEe_nue")) {
     return (new MINERvA_CC0pi_XSec_1DEe_nue(samplekey));
 
   } else if (!name.compare("MINERvA_CC0pi_XSec_1DQ2_nue")) {
     return (new MINERvA_CC0pi_XSec_1DQ2_nue(samplekey));
 
   } else if (!name.compare("MINERvA_CC0pi_XSec_1DThetae_nue")) {
     return (new MINERvA_CC0pi_XSec_1DThetae_nue(samplekey));
 
   } else if (!name.compare("MINERvA_CC0pi_XSec_1DQ2_nu_proton")) {
     return (new MINERvA_CC0pi_XSec_1DQ2_nu_proton(samplekey));
 
   } else if (!name.compare("MINERvA_CC0pi_XSec_1DQ2_TgtC_nu") ||
 	     !name.compare("MINERvA_CC0pi_XSec_1DQ2_TgtCH_nu") ||
              !name.compare("MINERvA_CC0pi_XSec_1DQ2_TgtFe_nu") ||
              !name.compare("MINERvA_CC0pi_XSec_1DQ2_TgtPb_nu")) {
     return (new MINERvA_CC0pi_XSec_1DQ2_Tgt_nu(samplekey));
 
   } else if (!name.compare("MINERvA_CC0pi_XSec_1DQ2_TgtRatioC_nu") ||
              !name.compare("MINERvA_CC0pi_XSec_1DQ2_TgtRatioFe_nu") ||
              !name.compare("MINERvA_CC0pi_XSec_1DQ2_TgtRatioPb_nu")) {
     return (new MINERvA_CC0pi_XSec_1DQ2_TgtRatio_nu(samplekey));
     
   } else if (!name.compare("MINERvA_CC0pi_XSec_2Dptpx_nu")){
 	return (new MINERvA_CC0pi_XSec_2Dptpx_nu(samplekey));
 
   } else if (!name.compare("MINERvA_CC0pi_XSec_2Dptpx_antinu")){
 	return (new MINERvA_CC0pi_XSec_2Dptpx_antinu(samplekey));
 
     /*
       CC1pi+
     */
     // DONE
   } else if (!name.compare("MINERvA_CC1pip_XSec_1DTpi_nu") ||
              !name.compare("MINERvA_CC1pip_XSec_1DTpi_nu_20deg") ||
              !name.compare("MINERvA_CC1pip_XSec_1DTpi_nu_fluxcorr") ||
              !name.compare("MINERvA_CC1pip_XSec_1DTpi_nu_20deg_fluxcorr")) {
     return (new MINERvA_CC1pip_XSec_1DTpi_nu(samplekey));
 
     // DONE
   } else if (!name.compare("MINERvA_CC1pip_XSec_1Dth_nu") ||
              !name.compare("MINERvA_CC1pip_XSec_1Dth_nu_20deg") ||
              !name.compare("MINERvA_CC1pip_XSec_1Dth_nu_fluxcorr") ||
              !name.compare("MINERvA_CC1pip_XSec_1Dth_nu_20deg_fluxcorr")) {
     return (new MINERvA_CC1pip_XSec_1Dth_nu(samplekey));
 
   } else if (!name.compare("MINERvA_CC1pip_XSec_1DTpi_nu_2017") ||
              !name.compare("MINERvA_CC1pip_XSec_1Dth_nu_2017") ||
              !name.compare("MINERvA_CC1pip_XSec_1Dpmu_nu_2017") ||
              !name.compare("MINERvA_CC1pip_XSec_1Dthmu_nu_2017") ||
              !name.compare("MINERvA_CC1pip_XSec_1DQ2_nu_2017") ||
              !name.compare("MINERvA_CC1pip_XSec_1DEnu_nu_2017")) {
     return (new MINERvA_CC1pip_XSec_1D_2017Update(samplekey));
     /*
       CCNpi+
     */
   } else if (!name.compare("MINERvA_CCNpip_XSec_1Dth_nu") ||
              !name.compare("MINERvA_CCNpip_XSec_1Dth_nu_2015") ||
              !name.compare("MINERvA_CCNpip_XSec_1Dth_nu_2016") ||
              !name.compare("MINERvA_CCNpip_XSec_1Dth_nu_2015_20deg") ||
              !name.compare("MINERvA_CCNpip_XSec_1Dth_nu_2015_fluxcorr") ||
              !name.compare("MINERvA_CCNpip_XSec_1Dth_nu_2015_20deg_fluxcorr")) {
     return (new MINERvA_CCNpip_XSec_1Dth_nu(samplekey));
 
   } else if (!name.compare("MINERvA_CCNpip_XSec_1DTpi_nu") ||
              !name.compare("MINERvA_CCNpip_XSec_1DTpi_nu_2015") ||
              !name.compare("MINERvA_CCNpip_XSec_1DTpi_nu_2016") ||
              !name.compare("MINERvA_CCNpip_XSec_1DTpi_nu_2015_20deg") ||
              !name.compare("MINERvA_CCNpip_XSec_1DTpi_nu_2015_fluxcorr") ||
-             !name.compare(
-                 "MINERvA_CCNpip_XSec_1DTpi_nu_2015_20deg_fluxcorr")) {
+             !name.compare("MINERvA_CCNpip_XSec_1DTpi_nu_2015_20deg_fluxcorr")) {
     return (new MINERvA_CCNpip_XSec_1DTpi_nu(samplekey));
 
     // Done
   } else if (!name.compare("MINERvA_CCNpip_XSec_1Dthmu_nu")) {
     return (new MINERvA_CCNpip_XSec_1Dthmu_nu(samplekey));
 
     // Done
   } else if (!name.compare("MINERvA_CCNpip_XSec_1Dpmu_nu")) {
     return (new MINERvA_CCNpip_XSec_1Dpmu_nu(samplekey));
 
     // Done
   } else if (!name.compare("MINERvA_CCNpip_XSec_1DQ2_nu")) {
     return (new MINERvA_CCNpip_XSec_1DQ2_nu(samplekey));
 
     // Done
   } else if (!name.compare("MINERvA_CCNpip_XSec_1DEnu_nu")) {
     return (new MINERvA_CCNpip_XSec_1DEnu_nu(samplekey));
 
     /*
       MINERvA CC1pi0 anti-nu
     */
     // Done
   } else if (!name.compare("MINERvA_CC1pi0_XSec_1Dth_antinu") ||
              !name.compare("MINERvA_CC1pi0_XSec_1Dth_antinu_2015") ||
              !name.compare("MINERvA_CC1pi0_XSec_1Dth_antinu_2016") ||
              !name.compare("MINERvA_CC1pi0_XSec_1Dth_antinu_fluxcorr") ||
              !name.compare("MINERvA_CC1pi0_XSec_1Dth_antinu_2015_fluxcorr") ||
              !name.compare("MINERvA_CC1pi0_XSec_1Dth_antinu_2016_fluxcorr")) {
     return (new MINERvA_CC1pi0_XSec_1Dth_antinu(samplekey));
 
   } else if (!name.compare("MINERvA_CC1pi0_XSec_1Dppi0_antinu") ||
              !name.compare("MINERvA_CC1pi0_XSec_1Dppi0_antinu_fluxcorr")) {
     return (new MINERvA_CC1pi0_XSec_1Dppi0_antinu(samplekey));
 
   } else if (!name.compare("MINERvA_CC1pi0_XSec_1DTpi0_antinu")) {
     return (new MINERvA_CC1pi0_XSec_1DTpi0_antinu(samplekey));
 
     // Done
   } else if (!name.compare("MINERvA_CC1pi0_XSec_1DQ2_antinu")) {
     return (new MINERvA_CC1pi0_XSec_1DQ2_antinu(samplekey));
 
     // Done
   } else if (!name.compare("MINERvA_CC1pi0_XSec_1Dthmu_antinu")) {
     return (new MINERvA_CC1pi0_XSec_1Dthmu_antinu(samplekey));
 
     // Done
   } else if (!name.compare("MINERvA_CC1pi0_XSec_1Dpmu_antinu")) {
     return (new MINERvA_CC1pi0_XSec_1Dpmu_antinu(samplekey));
 
     // Done
   } else if (!name.compare("MINERvA_CC1pi0_XSec_1DEnu_antinu")) {
     return (new MINERvA_CC1pi0_XSec_1DEnu_antinu(samplekey));
 
     // MINERvA CC1pi0 nu
   } else if (!name.compare("MINERvA_CC1pi0_XSec_1DTpi_nu") ||
              !name.compare("MINERvA_CC1pi0_XSec_1Dth_nu") ||
              !name.compare("MINERvA_CC1pi0_XSec_1Dpmu_nu") ||
              !name.compare("MINERvA_CC1pi0_XSec_1Dthmu_nu") ||
              !name.compare("MINERvA_CC1pi0_XSec_1DQ2_nu") ||
              !name.compare("MINERvA_CC1pi0_XSec_1DEnu_nu") ||
              !name.compare("MINERvA_CC1pi0_XSec_1DWexp_nu") ||
              !name.compare("MINERvA_CC1pi0_XSec_1DPPi0Mass_nu") ||
              !name.compare("MINERvA_CC1pi0_XSec_1DPPi0MassDelta_nu") ||
              !name.compare("MINERvA_CC1pi0_XSec_1DCosAdler_nu") ||
              !name.compare("MINERvA_CC1pi0_XSec_1DPhiAdler_nu")) {
     return (new MINERvA_CC1pi0_XSec_1D_nu(samplekey));
 
     /*
       CCINC
     */
   } else if (!name.compare("MINERvA_CCinc_XSec_2DEavq3_nu")) {
     return (new MINERvA_CCinc_XSec_2DEavq3_nu(samplekey));
 
   } else if (!name.compare("MINERvA_CCinc_XSec_1Dx_ratio_C12_CH") ||
              !name.compare("MINERvA_CCinc_XSec_1Dx_ratio_Fe56_CH") ||
              !name.compare("MINERvA_CCinc_XSec_1Dx_ratio_Pb208_CH")) {
     return (new MINERvA_CCinc_XSec_1Dx_ratio(samplekey));
 
   } else if (!name.compare("MINERvA_CCinc_XSec_1DEnu_ratio_C12_CH") ||
 	     !name.compare("MINERvA_CCinc_XSec_1DEnu_ratio_Fe56_CH") ||
              !name.compare("MINERvA_CCinc_XSec_1DEnu_ratio_Pb208_CH")) {
 	return (new MINERvA_CCinc_XSec_1DEnu_ratio(samplekey));
     /*
       CCDIS
     */
   } else if (!name.compare("MINERvA_CCDIS_XSec_1Dx_ratio_C12_CH") ||
 	     !name.compare("MINERvA_CCDIS_XSec_1Dx_ratio_Fe56_CH") ||
 	     !name.compare("MINERvA_CCDIS_XSec_1Dx_ratio_Pb208_CH")) {
 	return (new MINERvA_CCDIS_XSec_1Dx_ratio(samplekey));
 
   } else if (!name.compare("MINERvA_CCDIS_XSec_1DEnu_ratio_C12_CH") ||
 	     !name.compare("MINERvA_CCDIS_XSec_1DEnu_ratio_Fe56_CH") ||
 	     !name.compare("MINERvA_CCDIS_XSec_1DEnu_ratio_Pb208_CH")) {
 	return (new MINERvA_CCDIS_XSec_1DEnu_ratio(samplekey));
 
     /*
       CC-COH
     */
   } else if (!name.compare("MINERvA_CCCOHPI_XSec_1DEnu_nu")) {
     return (new MINERvA_CCCOHPI_XSec_1DEnu_nu(samplekey));
   } else if (!name.compare("MINERvA_CCCOHPI_XSec_1DEpi_nu")) {
     return (new MINERvA_CCCOHPI_XSec_1DEpi_nu(samplekey));
   } else if (!name.compare("MINERvA_CCCOHPI_XSec_1Dth_nu")) {
     return (new MINERvA_CCCOHPI_XSec_1Dth_nu(samplekey));
   } else if (!name.compare("MINERvA_CCCOHPI_XSec_1DQ2_nu")) {
     return (new MINERvA_CCCOHPI_XSec_1DQ2_nu(samplekey));
   } else if (!name.compare("MINERvA_CCCOHPI_XSec_1DEnu_antinu")) {
     return (new MINERvA_CCCOHPI_XSec_1DEnu_antinu(samplekey));
   } else if (!name.compare("MINERvA_CCCOHPI_XSec_1DEpi_antinu")) {
     return (new MINERvA_CCCOHPI_XSec_1DEpi_antinu(samplekey));
   } else if (!name.compare("MINERvA_CCCOHPI_XSec_1Dth_antinu")) {
     return (new MINERvA_CCCOHPI_XSec_1Dth_antinu(samplekey));
   } else if (!name.compare("MINERvA_CCCOHPI_XSec_1DQ2_antinu")) {
     return (new MINERvA_CCCOHPI_XSec_1DQ2_antinu(samplekey));
 
+  } else if (!name.compare("MINERvA_CCCOHPI_XSec_1DEnu_joint")) {
+    return (new MINERvA_CCCOHPI_XSec_joint(samplekey));
+  } else if (!name.compare("MINERvA_CCCOHPI_XSec_1DEpi_joint")) {
+    return (new MINERvA_CCCOHPI_XSec_joint(samplekey));
+  } else if (!name.compare("MINERvA_CCCOHPI_XSec_1Dth_joint")) {
+    return (new MINERvA_CCCOHPI_XSec_joint(samplekey));
+  } else if (!name.compare("MINERvA_CCCOHPI_XSec_1DQ2_joint")) {
+    return (new MINERvA_CCCOHPI_XSec_joint(samplekey));
+
     /*
     T2K Samples
     */
 
   } else
 #endif
 #ifndef __NO_T2K__
       if (!name.compare("T2K_CC0pi_XSec_2DPcos_nu") ||
           !name.compare("T2K_CC0pi_XSec_2DPcos_nu_I") ||
           !name.compare("T2K_CC0pi_XSec_2DPcos_nu_II")) {
     return (new T2K_CC0pi_XSec_2DPcos_nu(samplekey));
 
   } else if (!name.compare("T2K_CC0pi_XSec_2DPcos_nu_nonuniform")) {
     return (new T2K_CC0pi_XSec_2DPcos_nu_nonuniform(samplekey));
 
     /*
       T2K CC1pi+ CH samples
     */
     // Comment these out for now because we don't have the proper data
     /*
 
     } else if (!name.compare("T2K_CC1pip_CH_XSec_1Dpmu_nu")) {
     return (new T2K_CC1pip_CH_XSec_1Dpmu_nu(file, rw, type, fkdt));
 
     } else if (!name.compare("T2K_CC1pip_CH_XSec_1Dppi_nu")) {
     return (new T2K_CC1pip_CH_XSec_1Dppi_nu(file, rw, type, fkdt));
 
     } else if (!name.compare("T2K_CC1pip_CH_XSec_1DQ2_nu")) {
     return (new T2K_CC1pip_CH_XSec_1DQ2_nu(file, rw, type, fkdt));
 
     } else if (!name.compare("T2K_CC1pip_CH_XSec_1Dq3_nu")) {
     return (new T2K_CC1pip_CH_XSec_1Dq3_nu(file, rw, type, fkdt));
 
     } else if (!name.compare("T2K_CC1pip_CH_XSec_1Dthmupi_nu")) {
     return (new T2K_CC1pip_CH_XSec_1Dthmupi_nu(file, rw, type, fkdt));
 
     } else if (!name.compare("T2K_CC1pip_CH_XSec_1Dthpi_nu")) {
     return (new T2K_CC1pip_CH_XSec_1Dthpi_nu(file, rw, type, fkdt));
 
     } else if (!name.compare("T2K_CC1pip_CH_XSec_1Dthq3pi_nu")) {
     return (new T2K_CC1pip_CH_XSec_1Dthq3pi_nu(file, rw, type, fkdt));
 
     } else if (!name.compare("T2K_CC1pip_CH_XSec_1DWrec_nu")) {
     return (new T2K_CC1pip_CH_XSec_1DWrec_nu(file, rw, type, fkdt));
     */
 
     /*
       T2K CC1pi+ H2O samples
     */
   } else if (!name.compare("T2K_CC1pip_H2O_XSec_1DEnuDelta_nu")) {
     return (new T2K_CC1pip_H2O_XSec_1DEnuDelta_nu(samplekey));
 
   } else if (!name.compare("T2K_CC1pip_H2O_XSec_1DEnuMB_nu")) {
     return (new T2K_CC1pip_H2O_XSec_1DEnuMB_nu(samplekey));
 
   } else if (!name.compare("T2K_CC1pip_H2O_XSec_1Dcosmu_nu")) {
     return (new T2K_CC1pip_H2O_XSec_1Dcosmu_nu(samplekey));
 
   } else if (!name.compare("T2K_CC1pip_H2O_XSec_1Dcosmupi_nu")) {
     return (new T2K_CC1pip_H2O_XSec_1Dcosmupi_nu(samplekey));
 
   } else if (!name.compare("T2K_CC1pip_H2O_XSec_1Dcospi_nu")) {
     return (new T2K_CC1pip_H2O_XSec_1Dcospi_nu(samplekey));
 
   } else if (!name.compare("T2K_CC1pip_H2O_XSec_1Dpmu_nu")) {
     return (new T2K_CC1pip_H2O_XSec_1Dpmu_nu(samplekey));
 
   } else if (!name.compare("T2K_CC1pip_H2O_XSec_1Dppi_nu")) {
     return (new T2K_CC1pip_H2O_XSec_1Dppi_nu(samplekey));
 
     /*
       T2K CC0pi + np CH samples
     */
   } else if (!name.compare("T2K_CC0pinp_STV_XSec_1Ddpt_nu")) {
     return (new T2K_CC0pinp_STV_XSec_1Ddpt_nu(samplekey));
 
     // SciBooNE COH studies
   } else
 #endif
 #ifndef __NO_SciBooNE__
       if (!name.compare("SciBooNE_CCCOH_STOP_NTrks_nu")) {
     return (new SciBooNE_CCCOH_STOP_NTrks_nu(samplekey));
   } else if (!name.compare("SciBooNE_CCCOH_1TRK_1DQ2_nu")) {
     return (new SciBooNE_CCCOH_1TRK_1DQ2_nu(samplekey));
   } else if (!name.compare("SciBooNE_CCCOH_MuPr_1DQ2_nu")) {
     return (new SciBooNE_CCCOH_MuPr_1DQ2_nu(samplekey));
   } else if (!name.compare("SciBooNE_CCCOH_MuPiVA_1DQ2_nu")) {
     return (new SciBooNE_CCCOH_MuPiVA_1DQ2_nu(samplekey));
   } else if (!name.compare("SciBooNE_CCCOH_MuPiNoVA_1DQ2_nu")) {
     return (new SciBooNE_CCCOH_MuPiNoVA_1DQ2_nu(samplekey));
   } else if (!name.compare("SciBooNE_CCCOH_MuPiNoVA_1Dthetapr_nu")) {
     return (new SciBooNE_CCCOH_MuPiNoVA_1Dthetapr_nu(samplekey));
   } else if (!name.compare("SciBooNE_CCCOH_MuPiNoVA_1Dthetapi_nu")) {
     return (new SciBooNE_CCCOH_MuPiNoVA_1Dthetapi_nu(samplekey));
   } else if (!name.compare("SciBooNE_CCCOH_STOPFINAL_1DQ2_nu")) {
     return (new SciBooNE_CCCOH_STOPFINAL_1DQ2_nu(samplekey));
 
     /*
     K2K Samples
     */
     /*
       NC1pi0
     */
   } else
 #endif
 #ifndef __NO_K2K__
       if (!name.compare("K2K_NC1pi0_Evt_1Dppi0_nu")) {
     return (new K2K_NC1pi0_Evt_1Dppi0_nu(samplekey));
 
     /*
     Fake Studies
     */
 
   } else
 #endif
       if (name.find("ExpMultDist_CCQE_XSec_1D") != std::string::npos &&
           name.find("_FakeStudy") != std::string::npos) {
     return (
         new ExpMultDist_CCQE_XSec_1DVar_FakeStudy(name, file, rw, type, fkdt));
 
   } else if (name.find("ExpMultDist_CCQE_XSec_2D") != std::string::npos &&
              name.find("_FakeStudy") != std::string::npos) {
     return (
         new ExpMultDist_CCQE_XSec_2DVar_FakeStudy(name, file, rw, type, fkdt));
 
   } else if (name.find("GenericFlux_") != std::string::npos) {
     return (new GenericFlux_Tester(name, file, rw, type, fkdt));
 
   } else if (name.find("GenericVectors_") != std::string::npos) {
     return (new GenericFlux_Vectors(name, file, rw, type, fkdt));
 
   } else if (!name.compare("T2K2017_FakeData")) {
     return (new T2K2017_FakeData(samplekey));
 
   } else if (!name.compare("MCStudy_CCQE")) {
     return (new MCStudy_CCQEHistograms(name, file, rw, type, fkdt));
 
   } else if (!name.compare("ElectronFlux_FlatTree")) {
     return (new ElectronFlux_FlatTree(name, file, rw, type, fkdt));
 
   } else if (name.find("ElectronData_") != std::string::npos) {
     return new ElectronScattering_DurhamData(samplekey);
 
   } else if (name.find("MuonValidation_") != std::string::npos) {
     return (new MCStudy_MuonValidation(name, file, rw, type, fkdt));
 
   } else if (!name.compare("NIWGOfficialPlots")) {
     return (new OfficialNIWGPlots(samplekey));
 
   }else if (!name.compare("Simple_Osc")) {
     return (new Simple_Osc(samplekey));
 
   }else if (!name.compare("Smear_SVDUnfold_Propagation_Osc")) {
     return (new Smear_SVDUnfold_Propagation_Osc(samplekey));
 
   }
    else {
     ERR(FTL) << "Error: No such sample: " << name << std::endl;
     exit(-1);
     return NULL;
   }
 
   // Return NULL if no sample loaded.
   return NULL;
 }
 }
diff --git a/src/FitBase/CMakeLists.txt b/src/FitBase/CMakeLists.txt
index 543bcb2..91bfe86 100644
--- a/src/FitBase/CMakeLists.txt
+++ b/src/FitBase/CMakeLists.txt
@@ -1,72 +1,76 @@
 # Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret
 
 ################################################################################
 #    This file is part of NUISANCE.
 #
 #    NUISANCE is free software: you can redistribute it and/or modify
 #    it under the terms of the GNU General Public License as published by
 #    the Free Software Foundation, either version 3 of the License, or
 #    (at your option) any later version.
 #
 #    NUISANCE is distributed in the hope that it will be useful,
 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 #    GNU General Public License for more details.
 #
 #    You should have received a copy of the GNU General Public License
 #    along with NUISANCE.  If not, see <http://www.gnu.org/licenses/>.
 ################################################################################
 set(IMPLFILES
 ParamPull.cxx
 EventManager.cxx
 Measurement1D.cxx
 Measurement2D.cxx
 JointMeas1D.cxx
 MeasurementBase.cxx
 TemplateMeas1D.cxx
 SampleSettings.cxx
 MeasurementVariableBox.cxx
 MeasurementVariableBox2D.cxx
 MeasurementVariableBox1D.cxx
 CustomVariableBoxes.h
+StandardStacks.cxx
+StackBase.cxx
 )
 
 set(HEADERFILES
 ParamPull.h
 JointMeas1D.h
 Measurement2D.h
 EventManager.h
 MeasurementBase.h
 Measurement1D.h
 TemplateMeas1D.h
 SampleSettings.h
 MeasurementVariableBox.h
 MeasurementVariableBox2D.h
 MeasurementVariableBox1D.h
 CustomVariableBoxes.h
+StandardStacks.h
+StackBase.h
 )
 
 set(LIBNAME FitBase)
 
 if(CMAKE_BUILD_TYPE MATCHES DEBUG)
   add_library(${LIBNAME} STATIC ${IMPLFILES})
 else(CMAKE_BUILD_TYPE MATCHES RELEASE)
   add_library(${LIBNAME} SHARED ${IMPLFILES})
 endif()
 
 include_directories(${MINIMUM_INCLUDE_DIRECTORIES})
 cmessage(DEBUG "FitBase includes: ${MINIMUM_INCLUDE_DIRECTORIES}")
 
 set_target_properties(${LIBNAME} PROPERTIES VERSION
   "${NUISANCE_VERSION_MAJOR}.${NUISANCE_VERSION_MINOR}.${NUISANCE_VERSION_REVISION}")
 #set_target_properties(${LIBNAME} PROPERTIES LINK_FLAGS ${ROOT_LD_FLAGS})
 
 if(DEFINED PROJECTWIDE_EXTRA_DEPENDENCIES)
   add_dependencies(${LIBNAME} ${PROJECTWIDE_EXTRA_DEPENDENCIES})
 endif()
 
 install(TARGETS ${LIBNAME} DESTINATION lib)
 #Can uncomment this to install the headers... but is it really neccessary?
 install(FILES ${HEADERFILES} DESTINATION include)
 
 set(MODULETargets ${MODULETargets} ${LIBNAME} PARENT_SCOPE)
diff --git a/src/FitBase/JointMeas1D.h b/src/FitBase/JointMeas1D.h
index cada32a..01a51b0 100644
--- a/src/FitBase/JointMeas1D.h
+++ b/src/FitBase/JointMeas1D.h
@@ -1,688 +1,688 @@
 // Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret
 
 /*******************************************************************************
 *    This file is part of NUISANCE.
 *
 *    NUISANCE is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    NUISANCE is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with NUISANCE.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
 
 #ifndef JOINTMEASUREMENT_1D_H_SEEN
 #define JOINTMEASUREMENT_1D_H_SEEN
 /*!
  *  \addtogroup FitBase
  *  @{
  */
 
 #include <math.h>
 #include <stdlib.h>
 #include <deque>
 #include <iomanip>
 #include <iostream>
 #include <list>
 #include <numeric>
 #include <sstream>
 #include <string>
 
 // ROOT includes
 #include <TArrayF.h>
 #include <TCanvas.h>
 #include <TCut.h>
 #include <TDecompChol.h>
 #include <TDecompSVD.h>
 #include <TGraph.h>
 #include <TGraphErrors.h>
 #include <TH1D.h>
 #include <TH2D.h>
 #include <TMatrixDSym.h>
 #include <TROOT.h>
 #include <TSystem.h>
 #include "Measurement1D.h"
 
 // External data fit includes
 #include "FitEvent.h"
-#include "FitParameters.h"
+
 #include "FitUtils.h"
 #include "MeasurementBase.h"
 #include "PlotUtils.h"
 #include "StatUtils.h"
 
 
 //********************************************************************
 /// 1D Measurement base class. Histogram handling is done in this base layer.
 class JointMeas1D : public MeasurementBase {
 //********************************************************************
 
 public:
   /*
     Constructor/Deconstuctor
   */
   JointMeas1D(void);
   virtual ~JointMeas1D(void);
 
   /*
     Setup Functions
   */
 
 
   SampleSettings LoadSampleSettings(nuiskey samplekey);
 
 
   /// \brief Setup all configs once initialised
   ///
   /// Should be called after all configs have been setup inside fSettings container.
   /// Handles the processing of inputs and setting up of types.
   /// Replaces the old 'SetupMeasurement' function.
   void FinaliseSampleSettings();
 
 
   /// \brief Read 1D data inputs from a text file.
   ///
   /// Inputfile should have the format: \n
   /// low_binedge_1    bin_content_1  bin_error_1 \n
   /// low_binedge_2    bin_content_2  bin_error_2 \n
   /// ....             ....           ....        \n
   /// high_bin_edge_N  0.0            0.0
   virtual void SetDataFromTextFile(std::string datafile);
 
   /// \brief Read 1D data inputs from a root file.
   ///
   /// inhistfile specifies the path to the root file
   /// histname specifies the name of the histogram.
   ///
   /// If no histogram name is given the inhistfile value
   /// is automatically parsed with ';' so that: \n
   /// 'myhistfile.root;myhistname' \n
   /// will also work.
   virtual void SetDataFromRootFile(std::string inhistfile, std::string histname = "");
 
 
   /// \brief Set data bin errors to sqrt(entries)
   ///
   /// \warning REQUIRES DATA HISTOGRAM TO BE SET FIRST
   ///
   /// Sets the data errors as the sqrt of the bin contents
   /// Should be use for counting experiments
   virtual void SetPoissonErrors();
 
   /// \brief Make diagonal covariance from data
   ///
   /// \warning If no histogram passed, data must be setup first!
   /// Setup the covariance inputs by taking the data histogram
   /// errors and setting up a diagonal covariance matrix.
   ///
   /// If no data is supplied, fDataHist is used if already set.
   virtual void SetCovarFromDiagonal(TH1D* data = NULL);
 
   /// \brief Read the data covariance from a text file.
   ///
   /// Inputfile should have the format: \n
   /// covariance_11  covariance_12  covariance_13 ... \n
   /// covariance_21  covariance_22  covariance_23 ... \n
   /// ...            ...            ...           ... \n
   ///
   /// If no dimensions are given, it is assumed from the number
   /// entries in the first line of covfile.
   virtual void SetCovarFromTextFile(std::string covfile, int dim = -1);
 
   virtual void SetCovarFromMultipleTextFiles(std::string covfiles, int dim = -1);
 
   /// \brief Read the data covariance from a ROOT file.
   ///
   /// - covfile specifies the full path to the file
   /// - histname specifies the name of the covariance object. Both TMatrixDSym and TH2D are supported.
   ///
   /// If no histogram name is given the inhistfile value
   /// is automatically parsed with ; so that: \n
   /// mycovfile.root;myhistname \n
   /// will also work.
   virtual void SetCovarFromRootFile(std::string covfile, std::string histname);
 
   /// \brief Read the inverted data covariance from a text file.
   ///
   /// Inputfile should have similar format to that shown
   /// in SetCovarFromTextFile.
   ///
   /// If no dimensions are given, it is assumed from the number
   /// entries in the first line of covfile.
   virtual void SetCovarInvertFromTextFile(std::string covfile, int dim = -1);
 
 
   /// \brief Read the inverted data covariance from a ROOT file.
   ///
   /// Inputfile should have similar format to that shown
   /// in SetCovarFromRootFile.
   ///
   /// If no histogram name is given the inhistfile value
   /// is automatically parsed with ; so that: \n
   /// mycovfile.root;myhistname \n
   /// will also work.
   virtual void SetCovarInvertFromRootFile(std::string covfile, std::string histname);
 
   /// \brief Read the data correlations from a text file.
   ///
   /// \warning REQUIRES DATA HISTOGRAM TO BE SET FIRST
   ///
   /// Inputfile should have similar format to that shown
   /// in SetCovarFromTextFile.
   ///
   /// If no dimensions are given, it is assumed from the number
   /// entries in the first line of covfile.
   virtual void SetCorrelationFromTextFile(std::string covfile, int dim = -1);
 
   /// \brief Read the data correlations from multiple text files.
   ///
   /// \warning REQUIRES DATA HISTOGRAM TO BE SET FIRST
   ///
   /// Inputfile should have similar format to that shown
   /// in SetCovarFromTextFile.
   ///
   /// If no dimensions are given, it is assumed from the number
   /// entries in the first line of first covfile.
   virtual void SetCorrelationFromMultipleTextFiles(std::string corrfiles, int dim = -1);
 
   /// \brief Read the data correlations from a ROOT file.
   ///
   /// \warning REQUIRES DATA TO BE SET FIRST
   ///
   /// Inputfile should have similar format to that shown
   /// in SetCovarFromRootFile.
   ///
   /// If no histogram name is given the inhistfile value
   /// is automatically parsed with ; so that: \n
   /// mycovfile.root;myhistname \n
   /// will also work.
   virtual void SetCorrelationFromRootFile(std::string covfile, std::string histname);
 
   /// \brief Try to extract a shape-only matrix from the existing covariance
   virtual void SetShapeCovar();
 
   /// \brief Read the cholesky decomposed covariance from a text file and turn it into a covariance
   ///
   /// Inputfile should have similar format to that shown
   /// in SetCovarFromTextFile.
   ///
   /// If no dimensions are given, it is assumed from the number
   /// entries in the first line of covfile.
   virtual void SetCholDecompFromTextFile(std::string covfile, int dim = -1);
 
 
   /// \brief Read the cholesky decomposed covariance from a ROOT file and turn it into a covariance
   ///
   /// Inputfile should have similar format to that shown
   /// in SetCovarFromRootFile.
   ///
   /// If no histogram name is given the inhistfile value
   /// is automatically parsed with ; so that: \n
   /// mycovfile.root;myhistname \n
   /// will also work.
   virtual void SetCholDecompFromRootFile(std::string covfile, std::string histname);
 
 
   /// \brief Scale the data by some scale factor
   virtual void ScaleData(double scale);
 
 
   /// \brief Scale the covariaince and its invert/decomp by some scale factor.
   virtual void ScaleCovar(double scale);
 
 
 
   /// \brief Setup a bin masking histogram and apply masking to data
   ///
   /// \warning REQUIRES DATA HISTOGRAM TO BE SET FIRST
   ///
   /// Reads in a list of bins in a text file to be masked. Format is: \n
   /// bin_index_1  1 \n
   /// bin_index_2  1 \n
   /// bin_index_3  1 \n
   ///
   /// If 0 is given then a bin entry will NOT be masked. So for example: \n\n
   /// 1  1 \n
   /// 2  1 \n
   /// 3  0 \n
   /// 4  1 \n\n
   /// Will mask only the 1st, 2nd, and 4th bins.
   ///
   /// Masking can be turned on by specifiying the MASK option when creating a sample.
   /// When this is passed NUISANCE will look in the following locations for the mask file:
   /// - FitPar::Config().GetParS(fName + ".mask")
   /// - "data/masks/" + fName + ".mask";
   virtual void SetBinMask(std::string maskfile);
 
 
   /// \brief Final constructor setup
   /// \warning Should be called right at the end of the constructor.
   ///
   /// Contains a series of checks to ensure the data and inputs have been setup.
   /// Also creates the MC histograms needed for fitting.
   virtual void FinaliseMeasurement();
 
 
 
   /// \brief Set the current fit options from a string.
   ///
   /// This is called twice for each sample, once to set the default
   /// and once to set the current setting (if anything other than default given)
   ///
   /// For this to work properly it requires the default and allowed types to be
   /// set correctly. These should be specified as a string listing options.
   ///
   /// To split up options so that NUISANCE can automatically detect ones that
   /// are conflicting. Any options seperated with the '/' symbol are non conflicting
   /// and can be given together, whereas any seperated with the ',' symbol cannot
   /// be specified by the end user at the same time.
   ///
   /// Default Type Examples:
   /// - DIAG/FIX = Default option will be a diagonal covariance, with FIXED norm.
   /// - MASK/SHAPE = Default option will be a masked hist, with SHAPE always on.
   ///
   /// Allowed Type examples:
   /// - 'FULL/DIAG/NORM/MASK' = Any of these options can be specified.
   /// - 'FULL,FREE,SHAPE/MASK/NORM' = User can give either FULL, FREE, or SHAPE as on option.
   /// MASK and NORM can also be included as options.
   virtual void SetFitOptions(std::string opt);
 
 
   /*
     Smearing
   */
   /// \brief Read in smearing matrix from file
   ///
   /// Set the smearing matrix from a text file given the size of the matrix
   virtual void SetSmearingMatrix(std::string smearfile, int truedim,
                                  int recodim);
 
   /// \brief Apply smearing to MC true to get MC reco
   ///
   /// Apply smearing matrix to fMCHist using fSmearingMatrix
   virtual void ApplySmearingMatrix(void);
 
 
 
   /*
     Reconfigure Functions
   */
 
   /// \brief Create a Measurement1D box
   ///
   /// Creates a new 1D variable box containing just fXVar.
   ///
   /// This box is the bare minimum required by the JointFCN when
   /// running fast reconfigures during a routine.
   /// If for some reason a sample needs extra variables to be saved then
   /// it should override this function creating its own MeasurementVariableBox
   /// that contains the extra variables.
   virtual MeasurementVariableBox* CreateBox() {return new MeasurementVariableBox1D();};
 
   /// \brief Reset all MC histograms
   ///
   /// Resets all standard histograms and those registered to auto
   /// process to zero.
   ///
   /// If extra histograms are not included in auto processing, then they must be reset
   /// by overriding this function and doing it manually if required.
   virtual void ResetAll(void);
 
   /// \brief Fill MC Histograms from XVar
   ///
   /// Fill standard histograms using fXVar, Weight read from the variable box.
   ///
   /// WARNING : Any extra MC histograms need to be filled by overriding this function,
   /// even if they have been set to auto process.
   virtual void FillHistograms(void);
 
   // \brief Convert event rates to final histogram
   ///
   /// Apply standard scaling procedure to standard mc histograms to convert from
   /// raw events to xsec prediction.
   ///
   /// If any distributions have been set to auto process
   /// that is done during this function call, and a differential xsec is assumed.
   /// If that is not the case this function must be overriden.
   virtual void ScaleEvents(void);
 
   /// \brief Scale MC by a factor=1/norm
   ///
   /// Apply a simple normalisation scaling if the option FREE or a norm_parameter
   /// has been specified in the NUISANCE routine.
   virtual void ApplyNormScale(double norm);
 
 
   /*
     Statistical Functions
   */
 
   /// \brief Get Number of degrees of freedom
   ///
   /// Returns the number bins inside the data histogram accounting for
   /// any bin masking applied.
   virtual int GetNDOF(void);
 
   /// \brief Return Data/MC Likelihood at current state
   ///
   /// Returns the likelihood of the data given the current MC prediction.
   /// Diferent likelihoods definitions are used depending on the FitOptions.
   virtual double GetLikelihood(void);
 
 
   /*
     Fake Data
   */
 
   /// \brief Set the fake data values from either a file, or MC
   ///
   /// - Setting from a file "path": \n
   /// When reading from a file the full path must be given to a standard
   /// nuisance output. The standard MC histogram should have a name that matches
   /// this sample for it to be read in.
   /// \n\n
   /// - Setting from "MC": \n
   /// If the MC option is given the current MC prediction is used as fake data.
   virtual void SetFakeDataValues(std::string fakeOption);
 
   /// \brief Reset fake data back to starting fake data
   ///
   /// Reset the fake data back to original fake data (Reset back to before
   /// ThrowCovariance was first called)
   virtual void ResetFakeData(void);
 
   /// \brief Reset fake data back to original data
   ///
   /// Reset the data histogram back to the true original dataset for this sample
   /// before any fake data was defined.
   virtual void ResetData(void);
 
   /// \brief Generate fake data by throwing the covariance.
   ///
   /// Can be used on fake MC data or just the original dataset.
   /// Call ResetFakeData or ResetData to return to values before the throw.
   virtual void ThrowCovariance(void);
 
 
   /// \brief Throw the data by its assigned errors and assign this to MC
   ///
   /// Used when creating data toys by assign the MC to this thrown data
   /// so that the likelihood is calculated between data and thrown data
   virtual void ThrowDataToy(void);
 
   /*
     Access Functions
   */
 
   /// \brief Returns nicely formatted MC Histogram
   ///
   /// Format options can also be given in the samplesettings:
   /// - linecolor
   /// - linestyle
   /// - linewidth
   /// - fillcolor
   /// - fillstyle
   ///
   /// So to have a sample line colored differently in the xml cardfile put: \n
   /// <sample name="MiniBooNE_CCQE_XSec_1DQ2_nu" input="NEUT:input.root"
   /// linecolor="2" linestyle="7"  linewidth="2" />
   virtual TH1D* GetMCHistogram(void);
 
   /// \brief Returns nicely formatted data Histogram
   ///
   /// Format options can also be given in the samplesettings:
   /// - datacolor
   /// - datastyle
   /// - datawidth
   ///
   /// So to have a sample data colored differently in the xml cardfile put: \n
   /// <sample name="MiniBooNE_CCQE_XSec_1DQ2_nu" input="NEUT:input.root"
   /// datacolor="2" datastyle="7"  datawidth="2" />
   virtual TH1D* GetDataHistogram(void);
 
   /// \brief Returns a list of all MC histograms.
   ///
   /// Override this if you have extra histograms that need to be
   /// accessed outside of the Measurement1D class.
   virtual std::vector<TH1*> GetMCList(void);
 
 
   /// \brief Returns a list of all Data histograms.
   ///
   /// Override this if you have extra histograms that need to be
   /// accessed outside of the Measurement1D class.
   virtual std::vector<TH1*> GetDataList(void);
 
 
   /// \brief Returns a list of all Mask histograms.
   ///
   /// Override this if you have extra histograms that need to be
   /// accessed outside of the Measurement1D class.
   virtual std::vector<TH1*> GetMaskList(void);
 
 
   /// \brief Returns a list of all Fine histograms.
   ///
   /// Override this if you have extra histograms that need to be
   /// accessed outside of the Measurement1D class.
 virtual std::vector<TH1*> GetFineList(void);
 
   /*
     Write Functions
   */
   /// \brief Save the current state to the current TFile directory \n
   ///
   /// Data/MC are both saved by default.
   /// A range of other histograms can be saved by setting the
   /// config option 'drawopts'.
   ///
   /// Possible options: \n
   /// - FINE    = Write Fine Histogram \n
   /// - WEIGHTS = Write Weighted MC Histogram (before scaling) \n
   /// - FLUX    = Write Flux Histogram from MC Input \n
   /// - EVT     = Write Event Histogram from MC Input \n
   /// - XSEC    = Write XSec Histogram from MC Input \n
   /// - MASK    = Write Mask Histogram \n
   /// - COV     = Write Covariance Histogram \n
   /// - INVCOV  = Write Inverted Covariance Histogram \n
   /// - DECMOP  = Write Decomp. Covariance Histogram \n
   /// - RESIDUAL= Write Resudial Histograms \n
   /// - RATIO   = Write Data/MC Ratio Histograms \n
   /// - SHAPE   = Write MC Shape Histograms norm. to Data \n
   /// - CANVMC  = Build MC Canvas Showing Data, MC, Shape \n
   /// - MODES   = Write PDG Stack \n
   /// - CANVPDG = Build MC Canvas Showing Data, PDGStack \n
   ///
   /// So to save a range of these in parameters/config.xml set: \n
   /// <config drawopts='FINE/COV/SHAPE/RATIO' />
   virtual void Write(std::string drawOpt);
 
 
 
   virtual void WriteRatioPlot();
 
 
 
 
   virtual void WriteShapePlot();
   virtual void WriteShapeRatioPlot();
 
 
   double TotalIntegratedFlux(std::string intOpt, double low,
                              double high);
 
   //*
   // OLD DEFUNCTIONS
   //
 
   /// OLD FUNCTION
   virtual void SetupMeasurement(std::string input, std::string type,
                                 FitWeight* rw, std::string fkdt);
 
   /// OLD FUNCTION
   virtual void SetupDefaultHist(void);
 
   /// OLD FUNCTION
   virtual void SetDataValues(std::string dataFile);
 
   /// OLD FUNCTION
   virtual void SetDataFromFile(std::string inhistfile, std::string histname);
   /// OLD FUNCTION
   virtual void SetDataFromDatabase(std::string inhistfile,
                                    std::string histname);
 
   /// OLD FUNCTION
   virtual void SetCovarMatrix(std::string covarFile);
   /// OLD FUNCTION
   virtual void SetCovarMatrixFromText(std::string covarFile, int dim,
                                       double scale = 1.0);
   /// OLD FUNCTION
   virtual void SetCovarMatrixFromCorrText(std::string covarFile, int dim);
 
 
   /// OLD FUNCTION
   virtual void SetCovarFromDataFile(std::string covarFile, std::string covName,
                                     bool FullUnits = false);
 
 
 
 
 
   ////// JOINT MEAS1D Functions //////
 
   /*
     Reconfigure Functions
   */
 
   /// Call reconfigure on every sub sample
   virtual void Reconfigure();
 
   /// Stitch the sub sample plots together to make a final fMCHist after
   /// reconfigure has been called
   virtual void MakePlots();
 
 
   virtual std::vector<MeasurementBase*> GetSubSamples();
   virtual void ConvertEventRates();
 
   /*
     Access Functions
   */
   virtual std::vector<TH1*> GetFluxList();
   virtual std::vector<TH1*> GetEventRateList();
   virtual std::vector<TH1*> GetXSecList();
 
   //! Return a flux integrated across all sub samples
   virtual TH1D* GetCombinedFlux();
 
   //! Return an event rate integrated across all sub samples
   virtual TH1D* GetCombinedEventRate();
 
   virtual TH1D* GetEventHistogram() { return GetCombinedEventRate(); };
   virtual TH1D* GetXSecHistogram() {
     ERR(WRN)
         << "XSec histogram not properly implemented for joint measurements.";
     return MeasurementBase::GetXSecHistogram();
   };
   virtual TH1D* GetFluxHistogram() { return GetCombinedFlux(); };
 
 
 protected:
 
   // Data
   TH1D* fDataHist;  ///< default data histogram
   TH1D* fDataOrig;  ///< histogram to store original data before throws.
   TH1D* fDataTrue;  ///< histogram to store true dataset
   std::string fPlotTitles;  ///< Plot title x and y for the histograms
 
 
   // MC
   TH1D* fMCHist;     ///< default MC Histogram used in the chi2 fits
   TH1D* fMCFine;     ///< finely binned MC histogram
   TH1D* fMCStat;     ///< histogram with unweighted events to properly calculate
   TH1D* fMCWeighted; ///< Weighted histogram before xsec scaling
 
   TH1I* fMaskHist;   ///< Mask histogram for neglecting specific bins
   TMatrixD* fSmearMatrix;   ///< Smearing matrix (note, this is not symmetric)
 
   TrueModeStack* fMCHist_Modes; ///< Optional True Mode Stack
 
 
   // Statistical
   TMatrixDSym* covar;       ///< Inverted Covariance
   TMatrixDSym* fFullCovar;  ///< Full Covariance
   TMatrixDSym* fDecomp;     ///< Decomposed Covariance
   TMatrixDSym* fCorrel;     ///< Correlation Matrix
   TMatrixDSym* fShapeCovar;  ///< Shape-only covariance
 
   TMatrixDSym* fCovar;    ///< New FullCovar
   TMatrixDSym* fInvert;   ///< New covar
 
   double fNormError;        ///< Sample norm error
 
 
   // Fake Data
   bool fIsFakeData;            ///< Flag: is the current data fake from MC
   std::string fFakeDataInput;  ///< Input fake data file path
   TFile* fFakeDataFile;        ///< Input fake data file
 
 
   // Fit specific flags
   std::string fFitType;       ///< Current fit type
   std::string fAllowedTypes;  ///< Fit Types Possible
   std::string fDefaultTypes;  ///< Starting Default Fit Types
 
   bool fIsShape;      ///< Flag : Perform Shape-only fit
   bool fIsFree;       ///< Flag : Perform normalisation free fit
   bool fIsDiag;       ///< Flag : only include uncorrelated diagonal errors
   bool fIsMask;       ///< Flag : Apply bin masking
   bool fIsRawEvents;  ///< Flag : Are bin contents just event rates
   bool fIsEnu1D;      ///< Flag : Perform Flux Unfolded Scaling
   bool fIsChi2SVD;    ///< Flag : Use alternative Chi2 SVD Method (Do not use)
   bool fAddNormPen;   ///< Flag : Add a normalisation penalty term to the chi2.
   bool fIsFix;        ///< Flag : keeping norm fixed
   bool fIsFull;       ///< Flag : using full covariaince
   bool fIsDifXSec;    ///< Flag : creating a dif xsec
   bool fIsChi2;       ///< Flag : using Chi2 over LL methods
   bool fIsSmeared;    ///< Flag : Apply smearing?
 
 
 
 
   /// OLD STUFF TO REMOVE
   TH1D* fMCHist_PDG[61]; ///< REMOVE OLD MC PDG Plot
 
   // Arrays for data entries
   Double_t* fXBins;       ///< REMOVE xBin edges
   Double_t* fDataValues;  ///< REMOVE data bin contents
   Double_t* fDataErrors;  ///< REMOVE data bin errors
   Int_t fNDataPointsX;    ///< REMOVE number of data points
 
 
 
 
   //// JOINT MEAS1D OBJECTS ////
   std::vector<MeasurementBase*> fSubChain;  //!< Vector of experimental classes
   //! that are the sub measurements
   std::vector<std::string>
   fSubInFiles;  //!< vector of input files for each of the sub measurements.
 
   bool fIsRatio;      //!< Flag: is this sample a hist1/hist2 ratio sample
   bool fIsSummed;     //!< Flag: is this sample a combination hist1 + hist2
   bool fSaveSubMeas;  //!< Flag: Save each of the histograms from the sub
   //! samples as well as this joint samples plots
 
 
   double   fLikelihood;
 };
 
 
 
 /*! @} */
 #endif
diff --git a/src/FitBase/Measurement1D.cxx b/src/FitBase/Measurement1D.cxx
index e1c9936..0028d0f 100644
--- a/src/FitBase/Measurement1D.cxx
+++ b/src/FitBase/Measurement1D.cxx
@@ -1,1903 +1,1903 @@
 // Copyright 2016 L. Pickering, P. Stowell, R. Terri, C. Wilkinson, C. Wret
 
 /*******************************************************************************
 *    This ile is part of NUISANCE.
 *
 *    NUISANCE is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    NUISANCE is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with NUISANCE.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
 #include "Measurement1D.h"
 
 
 //********************************************************************
 Measurement1D::Measurement1D(void) {
 //********************************************************************
 
   // XSec Scalings
   fScaleFactor = -1.0;
   fCurrentNorm = 1.0;
 
   // Histograms
   fDataHist = NULL;
   fDataTrue = NULL;
 
   fMCHist = NULL;
   fMCFine = NULL;
   fMCWeighted = NULL;
 
   fMaskHist = NULL;
 
   // Covar
   covar = NULL;
   fFullCovar = NULL;
   fShapeCovar = NULL;
 
   fCovar  = NULL;
   fInvert = NULL;
   fDecomp = NULL;
 
   // Fake Data
   fFakeDataInput = "";
   fFakeDataFile  = NULL;
 
   // Options
   fDefaultTypes = "FIX/FULL/CHI2";
   fAllowedTypes =
     "FIX,FREE,SHAPE/FULL,DIAG/CHI2/NORM/ENUCORR/Q2CORR/ENU1D/MASK/NOWIDTH";
 
   fIsFix = false;
   fIsShape = false;
   fIsFree = false;
   fIsDiag = false;
   fIsFull = false;
   fAddNormPen = false;
   fIsMask = false;
   fIsChi2SVD = false;
   fIsRawEvents = false;
   fIsNoWidth = false;
   fIsDifXSec = false;
   fIsEnu1D = false;
 
   // Inputs
   fInput = NULL;
   fRW = NULL;
 
   // Extra Histograms
   fMCHist_Modes = NULL;
 
 }
 
 //********************************************************************
 Measurement1D::~Measurement1D(void) {
 //********************************************************************
 
   if (fDataHist)   delete fDataHist;
   if (fDataTrue)   delete fDataTrue;
   if (fMCHist)     delete fMCHist;
   if (fMCFine)     delete fMCFine;
   if (fMCWeighted) delete fMCWeighted;
   if (fMaskHist)   delete fMaskHist;
   if (covar)       delete covar;
   if (fFullCovar)  delete fFullCovar;
   if (fShapeCovar) delete fShapeCovar;
   if (fCovar)      delete fCovar;
   if (fInvert)     delete fInvert;
   if (fDecomp)     delete fDecomp;
 
 }
 
 //********************************************************************
 void Measurement1D::FinaliseSampleSettings() {
 //********************************************************************
 
   MeasurementBase::FinaliseSampleSettings();
 
   // Setup naming + renaming
   fName = fSettings.GetName();
   fSettings.SetS("originalname", fName);
   if (fSettings.Has("rename")) {
     fName = fSettings.GetS("rename");
     fSettings.SetS("name", fName);
   }
 
   // Setup all other options
   LOG(SAM) << "Finalising Sample Settings: " << fName << std::endl;
 
   if ((fSettings.GetS("originalname").find("Evt") != std::string::npos)) {
     fIsRawEvents = true;
     LOG(SAM) << "Found event rate measurement but using poisson likelihoods."
              << std::endl;
   }
 
   if (fSettings.GetS("originalname").find("XSec_1DEnu") != std::string::npos) {
     fIsEnu1D = true;
     LOG(SAM) << "::" << fName << "::" << std::endl;
     LOG(SAM) << "Found XSec Enu measurement, applying flux integrated scaling, "
              << "not flux averaged!" << std::endl;
   }
 
   if (fIsEnu1D && fIsRawEvents) {
     LOG(SAM) << "Found 1D Enu XSec distribution AND fIsRawEvents, is this "
              "really correct?!"
              << std::endl;
     LOG(SAM) << "Check experiment constructor for " << fName
              << " and correct this!" << std::endl;
     LOG(SAM) << "I live in " << __FILE__ << ":" << __LINE__ << std::endl;
     exit(-1);
   }
 
   if (!fRW) fRW = FitBase::GetRW();
   if (!fInput and !fIsJoint) SetupInputs(fSettings.GetS("input"));
 
   // Setup options
   SetFitOptions(fDefaultTypes); // defaults
   SetFitOptions(fSettings.GetS("type")); // user specified
 
   EnuMin = GeneralUtils::StrToDbl(fSettings.GetS("enu_min"));
   EnuMax = GeneralUtils::StrToDbl(fSettings.GetS("enu_max"));
 
   if (fAddNormPen) {
     if (fNormError <= 0.0) {
       ERR(WRN) << "Norm error for class " << fName << " is 0.0!" << std::endl;
       ERR(WRN) << "If you want to use it please add fNormError=VAL" << std::endl;
       throw;
     }
   }
 
 }
 
 //********************************************************************
 void Measurement1D::CreateDataHistogram(int dimx, double* binx) {
 //********************************************************************
 
   if (fDataHist) delete fDataHist;
 
   fDataHist = new TH1D( (fSettings.GetName() + "_data").c_str(), (fSettings.GetFullTitles()).c_str(),
                         dimx, binx) ;
 
 }
 
 
 //********************************************************************
 void Measurement1D::SetDataFromTextFile(std::string datafile) {
 //********************************************************************
 
   LOG(SAM) << "Reading data from text file: " << datafile << std::endl;
   fDataHist = PlotUtils::GetTH1DFromFile(datafile,
                                          fSettings.GetName() + "_data",
                                          fSettings.GetFullTitles());
 }
 
 //********************************************************************
 void Measurement1D::SetDataFromRootFile(std::string datafile,
                                         std::string histname) {
 //********************************************************************
 
   LOG(SAM) << "Reading data from root file: " << datafile << ";" << histname << std::endl;
   fDataHist = PlotUtils::GetTH1DFromRootFile(datafile, histname);
   fDataHist->SetNameTitle((fSettings.GetName() + "_data").c_str(),
                           (fSettings.GetFullTitles()).c_str());
 
   return;
 };
 
 //********************************************************************
 void Measurement1D::SetEmptyData(){
 //********************************************************************
 
   fDataHist = new TH1D("EMPTY_DATA","EMPTY_DATA",1,0.0,1.0);
 }
 
 //********************************************************************
 void Measurement1D::SetPoissonErrors() {
 //********************************************************************
 
   if (!fDataHist) {
     ERR(FTL) << "Need a data hist to setup possion errors! " << std::endl;
     ERR(FTL) << "Setup Data First!" << std::endl;
     throw;
   }
 
   for (int i = 0; i < fDataHist->GetNbinsX() + 1; i++) {
     fDataHist->SetBinError(i + 1, sqrt(fDataHist->GetBinContent(i + 1)));
   }
 }
 
 //********************************************************************
 void Measurement1D::SetCovarFromDiagonal(TH1D* data) {
 //********************************************************************
 
   if (!data and fDataHist) {
     data = fDataHist;
   }
 
   if (data) {
     LOG(SAM) << "Setting diagonal covariance for: " << data->GetName() << std::endl;
     fFullCovar = StatUtils::MakeDiagonalCovarMatrix(data);
     covar      = StatUtils::GetInvert(fFullCovar);
     fDecomp    = StatUtils::GetDecomp(fFullCovar);
   } else {
     ERR(FTL) << "No data input provided to set diagonal covar from!" << std::endl;
 
   }
 
   // if (!fIsDiag) {
   //   ERR(FTL) << "SetCovarMatrixFromDiag called for measurement "
   //            << "that is not set as diagonal." << std::endl;
   //   throw;
   // }
 
 }
 
 //********************************************************************
 void Measurement1D::SetCovarFromTextFile(std::string covfile, int dim) {
 //********************************************************************
 
   if (dim == -1) {
     dim = fDataHist->GetNbinsX();
   }
 
   LOG(SAM) << "Reading covariance from text file: " << covfile << std::endl;
   fFullCovar = StatUtils::GetCovarFromTextFile(covfile, dim);
   covar      = StatUtils::GetInvert(fFullCovar);
   fDecomp    = StatUtils::GetDecomp(fFullCovar);
 
 }
 
 
 //********************************************************************
 void Measurement1D::SetCovarFromMultipleTextFiles(std::string covfiles, int dim) {
 //********************************************************************
 
   if (dim == -1) {
     dim = fDataHist->GetNbinsX();
   }
 
   std::vector<std::string> covList = GeneralUtils::ParseToStr(covfiles, ";");
 
   fFullCovar = new TMatrixDSym(dim);
   for (uint i = 0; i < covList.size(); ++i){
     LOG(SAM) << "Reading covariance from text file: " << covList[i] << std::endl;
     TMatrixDSym* temp_cov = StatUtils::GetCovarFromTextFile(covList[i], dim);
     (*fFullCovar) += (*temp_cov);
     delete temp_cov;
   }
   covar      = StatUtils::GetInvert(fFullCovar);
   fDecomp    = StatUtils::GetDecomp(fFullCovar);
 
 }
 
 
 //********************************************************************
 void Measurement1D::SetCovarFromRootFile(std::string covfile, std::string histname) {
 //********************************************************************
 
   LOG(SAM) << "Reading covariance from text file: " << covfile << ";" << histname << std::endl;
   fFullCovar = StatUtils::GetCovarFromRootFile(covfile, histname);
   covar      = StatUtils::GetInvert(fFullCovar);
   fDecomp    = StatUtils::GetDecomp(fFullCovar);
 
 }
 
 //********************************************************************
 void Measurement1D::SetCovarInvertFromTextFile(std::string covfile, int dim) {
 //********************************************************************
 
   if (dim == -1) {
     dim = fDataHist->GetNbinsX();
   }
 
   LOG(SAM) << "Reading inverted covariance from text file: " << covfile << std::endl;
   covar       = StatUtils::GetCovarFromTextFile(covfile, dim);
   fFullCovar  = StatUtils::GetInvert(covar);
   fDecomp     = StatUtils::GetDecomp(fFullCovar);
 
 }
 
 //********************************************************************
 void Measurement1D::SetCovarInvertFromRootFile(std::string covfile, std::string histname) {
 //********************************************************************
 
   LOG(SAM) << "Reading inverted covariance from text file: " << covfile << ";" << histname << std::endl;
   covar      = StatUtils::GetCovarFromRootFile(covfile, histname);
   fFullCovar = StatUtils::GetInvert(covar);
   fDecomp    = StatUtils::GetDecomp(fFullCovar);
 
 }
 
 //********************************************************************
 void Measurement1D::SetCorrelationFromTextFile(std::string covfile, int dim) {
 //********************************************************************
 
   if (dim == -1) dim = fDataHist->GetNbinsX();
   LOG(SAM) << "Reading data correlations from text file: " << covfile << ";" << dim << std::endl;
   TMatrixDSym* correlation = StatUtils::GetCovarFromTextFile(covfile, dim);
 
   if (!fDataHist) {
     ERR(FTL) << "Trying to set correlations from text file but there is no data to build it from. \n"
              << "In constructor make sure data is set before SetCorrelationFromTextFile is called. \n" << std::endl;
     throw;
   }
 
   // Fill covar from data errors and correlations
   fFullCovar = new TMatrixDSym(dim);
   for (int i = 0; i < fDataHist->GetNbinsX(); i++) {
     for (int j = 0; j < fDataHist->GetNbinsX(); j++) {
       (*fFullCovar)(i, j) = (*correlation)(i, j) * fDataHist->GetBinError(i + 1) * fDataHist->GetBinError(j + 1) * 1.E76;
     }
   }
 
   // Fill other covars.
   covar   = StatUtils::GetInvert(fFullCovar);
   fDecomp = StatUtils::GetDecomp(fFullCovar);
 
   delete correlation;
 }
 
 //********************************************************************
 void Measurement1D::SetCorrelationFromMultipleTextFiles(std::string corrfiles, int dim) {
 //********************************************************************
 
   if (dim == -1) {
     dim = fDataHist->GetNbinsX();
   }
 
   std::vector<std::string> corrList = GeneralUtils::ParseToStr(corrfiles, ";");
 
   fFullCovar = new TMatrixDSym(dim);
   for (uint i = 0; i < corrList.size(); ++i){
     LOG(SAM) << "Reading covariance from text file: " << corrList[i] << std::endl;
     TMatrixDSym* temp_cov = StatUtils::GetCovarFromTextFile(corrList[i], dim);
 
     for (int i = 0; i < fDataHist->GetNbinsX(); i++) {
       for (int j = 0; j < fDataHist->GetNbinsX(); j++) {
 	(*temp_cov)(i, j) = (*temp_cov)(i, j) * fDataHist->GetBinError(i + 1) * fDataHist->GetBinError(j + 1) * 1.E76;
       }
     }
 
     (*fFullCovar) += (*temp_cov);
     delete temp_cov;
   }
   covar      = StatUtils::GetInvert(fFullCovar);
   fDecomp    = StatUtils::GetDecomp(fFullCovar);
 
 }
 
 
 //********************************************************************
 void Measurement1D::SetCorrelationFromRootFile(std::string covfile, std::string histname) {
 //********************************************************************
 
   LOG(SAM) << "Reading data correlations from text file: " << covfile << ";" << histname << std::endl;
   TMatrixDSym* correlation = StatUtils::GetCovarFromRootFile(covfile, histname);
 
   if (!fDataHist) {
     ERR(FTL) << "Trying to set correlations from text file but there is no data to build it from. \n"
              << "In constructor make sure data is set before SetCorrelationFromTextFile is called. \n" << std::endl;
     throw;
   }
 
   // Fill covar from data errors and correlations
   fFullCovar = new TMatrixDSym(fDataHist->GetNbinsX());
   for (int i = 0; i < fDataHist->GetNbinsX(); i++) {
     for (int j = 0; j < fDataHist->GetNbinsX(); j++) {
       (*fFullCovar)(i, j) = (*correlation)(i, j) * fDataHist->GetBinError(i + 1) * fDataHist->GetBinError(j + 1) * 1.E76;
     }
   }
 
   // Fill other covars.
   covar   = StatUtils::GetInvert(fFullCovar);
   fDecomp = StatUtils::GetDecomp(fFullCovar);
 
   delete correlation;
 }
 
 
 //********************************************************************
 void Measurement1D::SetCholDecompFromTextFile(std::string covfile, int dim) {
 //********************************************************************
 
   if (dim == -1) {
     dim = fDataHist->GetNbinsX();
   }
 
   LOG(SAM) << "Reading cholesky from text file: " << covfile << std::endl;
   TMatrixD* temp = StatUtils::GetMatrixFromTextFile(covfile, dim, dim);
 
   TMatrixD* trans = (TMatrixD*)temp->Clone();
   trans->T();
   (*trans) *= (*temp);
 
   fFullCovar  = new TMatrixDSym(dim, trans->GetMatrixArray(), "");
   covar       = StatUtils::GetInvert(fFullCovar);
   fDecomp     = StatUtils::GetDecomp(fFullCovar);
 
   delete temp;
   delete trans;
 
 }
 
 //********************************************************************
 void Measurement1D::SetCholDecompFromRootFile(std::string covfile, std::string histname) {
 //********************************************************************
 
   LOG(SAM) << "Reading cholesky decomp from root file: " << covfile << ";" << histname << std::endl;
   TMatrixD* temp = StatUtils::GetMatrixFromRootFile(covfile, histname);
 
   TMatrixD* trans = (TMatrixD*)temp->Clone();
   trans->T();
   (*trans) *= (*temp);
 
   fFullCovar  = new TMatrixDSym(temp->GetNrows(), trans->GetMatrixArray(), "");
   covar       = StatUtils::GetInvert(fFullCovar);
   fDecomp     = StatUtils::GetDecomp(fFullCovar);
 
   delete temp;
   delete trans;
 }
 
 void Measurement1D::SetShapeCovar(){
 
   // Return if this is missing any pre-requisites
   if (!fFullCovar) return;
   if (!fDataHist) return;
 
   // Also return if it's bloody stupid under the circumstances
   if (fIsDiag) return;
 
   fShapeCovar = StatUtils::ExtractShapeOnlyCovar(fFullCovar, fDataHist);
   return;
 }
 
 //********************************************************************
 void Measurement1D::ScaleData(double scale) {
 //********************************************************************
   fDataHist->Scale(scale);
 }
 
 
 //********************************************************************
 void Measurement1D::ScaleDataErrors(double scale) {
 //********************************************************************
   for (int i = 0; i < fDataHist->GetNbinsX(); i++) {
     fDataHist->SetBinError(i + 1, fDataHist->GetBinError(i + 1) * scale);
   }
 }
 
 
 
 //********************************************************************
 void Measurement1D::ScaleCovar(double scale) {
 //********************************************************************
   (*fFullCovar) *= scale;
   (*covar) *= 1.0 / scale;
   (*fDecomp) *= sqrt(scale);
 }
 
 
 //********************************************************************
 void Measurement1D::SetBinMask(std::string maskfile) {
 //********************************************************************
 
   if (!fIsMask) return;
   LOG(SAM) << "Reading bin mask from file: " << maskfile << std::endl;
 
   // Create a mask histogram with dim of data
   int nbins = fDataHist->GetNbinsX();
   fMaskHist =
     new TH1I((fSettings.GetName() + "_BINMASK").c_str(),
              (fSettings.GetName() + "_BINMASK; Bin; Mask?").c_str(), nbins, 0, nbins);
   std::string line;
   std::ifstream mask(maskfile.c_str(), ifstream::in);
 
   if (!mask.is_open()) {
     LOG(FTL) << " Cannot find mask file." << std::endl;
     throw;
   }
 
   while (std::getline(mask >> std::ws, line, '\n')) {
     std::vector<int> entries = GeneralUtils::ParseToInt(line, " ");
 
     // Skip lines with poorly formatted lines
     if (entries.size() < 2) {
       LOG(WRN) << "Measurement1D::SetBinMask(), couldn't parse line: " << line
                << std::endl;
       continue;
     }
 
     // The first index should be the bin number, the second should be the mask
     // value.
     int val = 0;
     if (entries[1] > 0) val = 1;
     fMaskHist->SetBinContent(entries[0], val);
   }
 
   // Apply masking by setting masked data bins to zero
   PlotUtils::MaskBins(fDataHist, fMaskHist);
 
   return;
 }
 
 
 
 //********************************************************************
 void Measurement1D::FinaliseMeasurement() {
 //********************************************************************
 
   LOG(SAM) << "Finalising Measurement: " << fName << std::endl;
 
   if (fSettings.GetB("onlymc")){
     if (fDataHist) delete fDataHist;
     fDataHist = new TH1D("empty_data","empty_data",1,0.0,1.0);
   }
 
   // Make sure data is setup
   if (!fDataHist) {
     ERR(FTL) << "No data has been setup inside " << fName << " constructor!" << std::endl;
     throw;
   }
 
   // Make sure covariances are setup
   if (!fFullCovar) {
     fIsDiag = true;
     SetCovarFromDiagonal(fDataHist);
   }
 
   if (!covar) {
     covar = StatUtils::GetInvert(fFullCovar);
   }
 
   if (!fDecomp) {
     fDecomp = StatUtils::GetDecomp(fFullCovar);
   }
 
   // Push the diagonals of fFullCovar onto the data histogram
   // Comment this out until the covariance/data scaling is consistent!
   StatUtils::SetDataErrorFromCov(fDataHist, fFullCovar, 1E-38);
 
   // If shape only, set covar and fDecomp using the shape-only matrix (if set)
-  if (fIsShape && fShapeCovar){
+  if (fIsShape && fShapeCovar and FitPar::Config().GetParB("UseShapeCovar")){    
     if (covar) delete covar;
     covar = StatUtils::GetInvert(fShapeCovar);
     if (fDecomp) delete fDecomp;
     fDecomp = StatUtils::GetDecomp(fFullCovar);
   }
 
   // Setup fMCHist from data
   fMCHist = (TH1D*)fDataHist->Clone();
   fMCHist->SetNameTitle((fSettings.GetName() + "_MC").c_str(),
                         (fSettings.GetFullTitles()).c_str());
   fMCHist->Reset();
 
   // Setup fMCFine
   fMCFine = new TH1D("mcfine", "mcfine", fDataHist->GetNbinsX() * 8,
                      fMCHist->GetBinLowEdge(1),
                      fMCHist->GetBinLowEdge(fDataHist->GetNbinsX() + 1));
   fMCFine->SetNameTitle((fSettings.GetName() + "_MC_FINE").c_str(),
                         (fSettings.GetFullTitles()).c_str());
   fMCFine->Reset();
 
   // Setup MC Stat
   fMCStat = (TH1D*)fMCHist->Clone();
   fMCStat->Reset();
 
   // Search drawopts for possible types to include by default
   std::string drawopts = FitPar::Config().GetParS("drawopts");
   if (drawopts.find("MODES") != std::string::npos) {
     fMCHist_Modes = new TrueModeStack( (fSettings.GetName() + "_MODES").c_str(),
                                        ("True Channels"), fMCHist);
     SetAutoProcessTH1(fMCHist_Modes, kCMD_Reset, kCMD_Norm, kCMD_Write);
   }
 
   // Setup bin masks using sample name
   if (fIsMask) {
 
     std::string curname  = fName;
     std::string origname = fSettings.GetS("originalname");
 
     // Check rename.mask
     std::string maskloc = FitPar::Config().GetParDIR(curname + ".mask");
 
     // Check origname.mask
     if (maskloc.empty()) maskloc = FitPar::Config().GetParDIR(origname + ".mask");
 
     // Check database
     if (maskloc.empty()) {
       maskloc = FitPar::GetDataBase() + "/masks/" + origname + ".mask";
     }
 
     // Setup Bin Mask
     SetBinMask(maskloc);
   }
 
   if (fScaleFactor < 0) {
     ERR(FTL) << "I found a negative fScaleFactor in " << __FILE__ << ":" << __LINE__ << std::endl;
     ERR(FTL) << "fScaleFactor = " << fScaleFactor << std::endl;
     ERR(FTL) << "EXITING" << std::endl;
     throw;
   }
 
   // Create and fill Weighted Histogram
   if (!fMCWeighted) {
 
     fMCWeighted = (TH1D*)fMCHist->Clone();
     fMCWeighted->SetNameTitle((fName + "_MCWGHTS").c_str(),
                               (fName + "_MCWGHTS" + fPlotTitles).c_str());
     fMCWeighted->GetYaxis()->SetTitle("Weighted Events");
 
   }
 
 
 }
 
 //********************************************************************
 void Measurement1D::SetFitOptions(std::string opt) {
 //********************************************************************
 
   // Do nothing if default given
   if (opt == "DEFAULT") return;
 
   // CHECK Conflicting Fit Options
   std::vector<std::string> fit_option_allow =
     GeneralUtils::ParseToStr(fAllowedTypes, "/");
 
   for (UInt_t i = 0; i < fit_option_allow.size(); i++) {
     std::vector<std::string> fit_option_section =
       GeneralUtils::ParseToStr(fit_option_allow.at(i), ",");
 
     bool found_option = false;
 
     for (UInt_t j = 0; j < fit_option_section.size(); j++) {
       std::string av_opt = fit_option_section.at(j);
 
       if (!found_option and opt.find(av_opt) != std::string::npos) {
         found_option = true;
 
       } else if (found_option and opt.find(av_opt) != std::string::npos) {
         ERR(FTL) << "ERROR: Conflicting fit options provided: "
                  << opt << std::endl
                  << "Conflicting group = " << fit_option_section.at(i) << std::endl
                  << "You should only supply one of these options in card file." << std::endl;
         throw;
       }
     }
   }
 
   // Check all options are allowed
   std::vector<std::string> fit_options_input =
     GeneralUtils::ParseToStr(opt, "/");
   for (UInt_t i = 0; i < fit_options_input.size(); i++) {
     if (fAllowedTypes.find(fit_options_input.at(i)) == std::string::npos) {
       ERR(FTL) << "ERROR: Fit Option '" << fit_options_input.at(i)
                << "' Provided is not allowed for this measurement."
                << std::endl;
       ERR(FTL) << "Fit Options should be provided as a '/' seperated list "
                "(e.g. FREE/DIAG/NORM)"
                << std::endl;
       ERR(FTL) << "Available options for " << fName << " are '" << fAllowedTypes
                << "'" << std::endl;
 
       throw;
     }
   }
 
   // Set TYPE
   fFitType = opt;
 
   // FIX,SHAPE,FREE
   if (opt.find("FIX") != std::string::npos) {
     fIsFree = fIsShape = false;
     fIsFix = true;
   } else if (opt.find("SHAPE") != std::string::npos) {
     fIsFree = fIsFix = false;
     fIsShape = true;
   } else if (opt.find("FREE") != std::string::npos) {
     fIsFix = fIsShape = false;
     fIsFree = true;
   }
 
   // DIAG,FULL (or default to full)
   if (opt.find("DIAG") != std::string::npos) {
     fIsDiag = true;
     fIsFull = false;
   } else if (opt.find("FULL") != std::string::npos) {
     fIsDiag = false;
     fIsFull = true;
   }
 
   // CHI2/LL (OTHERS?)
   if (opt.find("LOG") != std::string::npos) {
     fIsChi2 = false;
 
     ERR(FTL) << "No other LIKELIHOODS properly supported!" << std::endl;
     ERR(FTL) << "Try to use a chi2!" << std::endl;
     throw;
 
   } else {
     fIsChi2 = true;
   }
 
   // EXTRAS
   if (opt.find("RAW") != std::string::npos) fIsRawEvents = true;
   if (opt.find("NOWIDTH") != std::string::npos) fIsNoWidth = true;
   if (opt.find("DIF") != std::string::npos) fIsDifXSec = true;
   if (opt.find("ENU1D") != std::string::npos) fIsEnu1D = true;
   if (opt.find("NORM") != std::string::npos) fAddNormPen = true;
   if (opt.find("MASK") != std::string::npos) fIsMask = true;
 
   return;
 };
 
 
 //********************************************************************
 void Measurement1D::SetSmearingMatrix(std::string smearfile, int truedim,
                                       int recodim) {
   //********************************************************************
 
   // The smearing matrix describes the migration from true bins (rows) to reco
   // bins (columns)
   // Counter over the true bins!
   int row = 0;
 
   std::string line;
   std::ifstream smear(smearfile.c_str(), ifstream::in);
 
   // Note that the smearing matrix may be rectangular.
   fSmearMatrix = new TMatrixD(truedim, recodim);
 
   if (smear.is_open())
     LOG(SAM) << "Reading smearing matrix from file: " << smearfile << std::endl;
   else
     ERR(FTL) << "Smearing matrix provided is incorrect: " << smearfile
              << std::endl;
 
   while (std::getline(smear >> std::ws, line, '\n')) {
     int column = 0;
 
     std::vector<double> entries = GeneralUtils::ParseToDbl(line, " ");
     for (std::vector<double>::iterator iter = entries.begin();
          iter != entries.end(); iter++) {
       (*fSmearMatrix)(row, column) =
         (*iter) / 100.;  // Convert to fraction from
       // percentage (this may not be
       // general enough)
       column++;
     }
     row++;
   }
   return;
 }
 
 //********************************************************************
 void Measurement1D::ApplySmearingMatrix() {
 //********************************************************************
 
   if (!fSmearMatrix) {
     ERR(WRN) << fName
              << ": attempted to apply smearing matrix, but none was set"
              << std::endl;
     return;
   }
 
   TH1D* unsmeared = (TH1D*)fMCHist->Clone();
   TH1D* smeared = (TH1D*)fMCHist->Clone();
   smeared->Reset();
 
   // Loop over reconstructed bins
   // true = row; reco = column
   for (int rbin = 0; rbin < fSmearMatrix->GetNcols(); ++rbin) {
     // Sum up the constributions from all true bins
     double rBinVal = 0;
 
     // Loop over true bins
     for (int tbin = 0; tbin < fSmearMatrix->GetNrows(); ++tbin) {
       rBinVal +=
         (*fSmearMatrix)(tbin, rbin) * unsmeared->GetBinContent(tbin + 1);
     }
     smeared->SetBinContent(rbin + 1, rBinVal);
   }
   fMCHist = (TH1D*)smeared->Clone();
 
   return;
 }
 
 /*
    Reconfigure LOOP
 */
 //********************************************************************
 void Measurement1D::ResetAll() {
 //********************************************************************
 
   fMCHist->Reset();
   fMCFine->Reset();
   fMCStat->Reset();
 
   return;
 };
 
 //********************************************************************
 void Measurement1D::FillHistograms() {
   //********************************************************************
 
   if (Signal) {
 
     fMCHist->Fill(fXVar, Weight);
     fMCFine->Fill(fXVar, Weight);
     fMCStat->Fill(fXVar, 1.0);
 
     if (fMCHist_Modes) fMCHist_Modes->Fill(Mode, fXVar, Weight);
   }
 
   return;
 };
 
 //********************************************************************
 void Measurement1D::ScaleEvents() {
 //********************************************************************
 
   // Fill MCWeighted;
   // for (int i = 0; i < fMCHist->GetNbinsX(); i++) {
   //   fMCWeighted->SetBinContent(i + 1, fMCHist->GetBinContent(i + 1));
   //   fMCWeighted->SetBinError(i + 1,   fMCHist->GetBinError(i + 1));
   // }
 
 
   // Setup Stat ratios for MC and MC Fine
   double* statratio     = new double[fMCHist->GetNbinsX()];
   for (int i = 0; i < fMCHist->GetNbinsX(); i++) {
     if (fMCHist->GetBinContent(i + 1) != 0) {
       statratio[i] = fMCHist->GetBinError(i + 1) / fMCHist->GetBinContent(i + 1);
     } else {
       statratio[i] = 0.0;
     }
   }
 
   double* statratiofine = new double[fMCFine->GetNbinsX()];
   for (int i = 0; i < fMCFine->GetNbinsX(); i++) {
     if (fMCFine->GetBinContent(i + 1) != 0) {
       statratiofine[i] = fMCFine->GetBinError(i + 1) / fMCFine->GetBinContent(i + 1);
     } else {
       statratiofine[i] = 0.0;
     }
   }
 
 
   // Scaling for raw event rates
   if (fIsRawEvents) {
     double datamcratio = fDataHist->Integral() / fMCHist->Integral();
 
     fMCHist->Scale(datamcratio);
     fMCFine->Scale(datamcratio);
 
     if (fMCHist_Modes) fMCHist_Modes->Scale(datamcratio);
 
     // Scaling for XSec as function of Enu
   } else if (fIsEnu1D) {
 
     PlotUtils::FluxUnfoldedScaling(fMCHist, GetFluxHistogram(),
                                    GetEventHistogram(), fScaleFactor,
                                    fNEvents);
     PlotUtils::FluxUnfoldedScaling(fMCFine, GetFluxHistogram(),
                                    GetEventHistogram(), fScaleFactor,
                                    fNEvents);
 
 
     // if (fMCHist_Modes) {
     // PlotUtils::FluxUnfoldedScaling(fMCHist_Modes, GetFluxHistogram(),
     // GetEventHistogram(), fScaleFactor,
     // fNEvents);
     // }
 
   } else if (fIsNoWidth) {
     fMCHist->Scale(fScaleFactor);
     fMCFine->Scale(fScaleFactor);
     if (fMCHist_Modes) fMCHist_Modes->Scale(fScaleFactor);
     // Any other differential scaling
   } else {
     fMCHist->Scale(fScaleFactor, "width");
     fMCFine->Scale(fScaleFactor, "width");
 
     if (fMCHist_Modes) fMCHist_Modes->Scale(fScaleFactor, "width");
   }
 
 
   // Proper error scaling - ROOT Freaks out with xsec weights sometimes
   for (int i = 0; i < fMCStat->GetNbinsX(); i++) {
     fMCHist->SetBinError(i + 1, fMCHist->GetBinContent(i + 1) * statratio[i]);
   }
 
   for (int i = 0; i < fMCFine->GetNbinsX(); i++) {
     fMCFine->SetBinError(i + 1, fMCFine->GetBinContent(i + 1) * statratiofine[i]);
   }
 
 
   // Clean up
   delete statratio;
   delete statratiofine;
 
   return;
 };
 
 //********************************************************************
 void Measurement1D::ApplyNormScale(double norm) {
 //********************************************************************
 
   fCurrentNorm = norm;
 
   fMCHist->Scale(1.0 / norm);
   fMCFine->Scale(1.0 / norm);
 
   return;
 };
 
 
 
 /*
    Statistic Functions - Outsources to StatUtils
 */
 
 //********************************************************************
 int Measurement1D::GetNDOF() {
   //********************************************************************
   int ndof = fDataHist->GetNbinsX();
   if (fMaskHist and fIsMask) ndof -= fMaskHist->Integral();
   return ndof;
 }
 
 //********************************************************************
 double Measurement1D::GetLikelihood() {
 //********************************************************************
 
   // If this is for a ratio, there is no data histogram to compare to!
   if (fNoData || !fDataHist) return 0.;
 
   // Apply Masking to MC if Required.
   if (fIsMask and fMaskHist) {
     PlotUtils::MaskBins(fMCHist, fMaskHist);
   }
 
 
   // Sort Shape Scaling
   double scaleF = 0.0;
   // TODO Include !fIsRawEvents
   if (fIsShape) {
     if (fMCHist->Integral(1, fMCHist->GetNbinsX(), "width")) {
       scaleF = fDataHist->Integral(1, fDataHist->GetNbinsX(), "width") /
       	fMCHist->Integral(1, fMCHist->GetNbinsX(), "width");
       fMCHist->Scale(scaleF);
       fMCFine->Scale(scaleF);
     }
   }
 
 
   // Likelihood Calculation
   double stat = 0.;
   if (fIsChi2) {
 
     if (fIsRawEvents) {
       stat = StatUtils::GetChi2FromEventRate(fDataHist, fMCHist, fMaskHist);
     } else if (fIsDiag) {
       stat = StatUtils::GetChi2FromDiag(fDataHist, fMCHist, fMaskHist);
     } else if (!fIsDiag and !fIsRawEvents) {
       stat = StatUtils::GetChi2FromCov(fDataHist, fMCHist, covar, fMaskHist);
     }
 
   }
 
   // Sort Penalty Terms
   if (fAddNormPen) {
     double penalty =
       (1. - fCurrentNorm) * (1. - fCurrentNorm) / (fNormError * fNormError);
 
     stat += penalty;
   }
 
   // Return to normal scaling
   if (fIsShape) { // and !FitPar::Config().GetParB("saveshapescaling")) {
     fMCHist->Scale(1. / scaleF);
     fMCFine->Scale(1. / scaleF);
   }
 
   fLikelihood = stat;
 
   return stat;
 }
 
 
 /*
   Fake Data Functions
 */
 //********************************************************************
 void Measurement1D::SetFakeDataValues(std::string fakeOption) {
 //********************************************************************
 
   // Setup original/datatrue
   TH1D* tempdata = (TH1D*) fDataHist->Clone();
 
   if (!fIsFakeData) {
     fIsFakeData = true;
 
     // Make a copy of the original data histogram.
     if (!fDataOrig) fDataOrig = (TH1D*)fDataHist->Clone((fName + "_data_original").c_str());
 
   } else {
     ResetFakeData();
 
   }
 
   // Setup Inputs
   fFakeDataInput = fakeOption;
   LOG(SAM) << "Setting fake data from : " << fFakeDataInput << std::endl;
 
   // From MC
   if (fFakeDataInput.compare("MC") == 0) {
     fDataHist = (TH1D*)fMCHist->Clone((fName + "_MC").c_str());
 
     // Fake File
   } else {
     if (!fFakeDataFile) fFakeDataFile = new TFile(fFakeDataInput.c_str(), "READ");
     fDataHist = (TH1D*)fFakeDataFile->Get((fName + "_MC").c_str());
 
   }
 
   // Setup Data Hist
   fDataHist->SetNameTitle((fName + "_FAKE").c_str(),
                           (fName + fPlotTitles).c_str());
 
   // Replace Data True
   if (fDataTrue) delete fDataTrue;
   fDataTrue = (TH1D*)fDataHist->Clone();
   fDataTrue->SetNameTitle((fName + "_FAKE_TRUE").c_str(),
                           (fName + fPlotTitles).c_str());
 
 
   // Make a new covariance for fake data hist.
   int nbins = fDataHist->GetNbinsX();
   double alpha_i = 0.0;
   double alpha_j = 0.0;
 
   for (int i = 0; i < nbins; i++) {
     for (int j = 0; j < nbins; j++) {
       alpha_i = fDataHist->GetBinContent(i + 1) / tempdata->GetBinContent(i + 1);
       alpha_j = fDataHist->GetBinContent(j + 1) / tempdata->GetBinContent(j + 1);
 
       (*fFullCovar)(i, j) = alpha_i * alpha_j * (*fFullCovar)(i, j);
     }
   }
 
   // Setup Covariances
   if (covar) delete covar;
   covar   = StatUtils::GetInvert(fFullCovar);
 
   if (fDecomp) delete fDecomp;
   fDecomp = StatUtils::GetInvert(fFullCovar);
 
   delete tempdata;
 
   return;
 };
 
 //********************************************************************
 void Measurement1D::ResetFakeData() {
 //********************************************************************
 
   if (fIsFakeData) {
     if (fDataHist) delete fDataHist;
     fDataHist = (TH1D*)fDataTrue->Clone((fSettings.GetName() + "_FKDAT").c_str());
   }
 
 }
 
 //********************************************************************
 void Measurement1D::ResetData() {
 //********************************************************************
 
   if (fIsFakeData) {
     if (fDataHist) delete fDataHist;
     fDataHist = (TH1D*)fDataOrig->Clone((fSettings.GetName() + "_data").c_str());
   }
 
   fIsFakeData = false;
 }
 
 //********************************************************************
 void Measurement1D::ThrowCovariance() {
 //********************************************************************
 
   // Take a fDecomposition and use it to throw the current dataset.
   // Requires fDataTrue also be set incase used repeatedly.
 
   if (!fDataTrue) fDataTrue = (TH1D*) fDataHist->Clone();
   if (fDataHist) delete fDataHist;
   fDataHist = StatUtils::ThrowHistogram(fDataTrue, fFullCovar);
 
   return;
 };
 
 
 //********************************************************************
 void Measurement1D::ThrowDataToy(){
 //********************************************************************
   if (!fDataTrue) fDataTrue = (TH1D*) fDataHist->Clone();
   if (fMCHist) delete fMCHist;
   fMCHist = StatUtils::ThrowHistogram(fDataTrue, fFullCovar);
 }
 
 /*
    Access Functions
 */
 
 //********************************************************************
 TH1D* Measurement1D::GetMCHistogram() {
 //********************************************************************
 
   if (!fMCHist) return fMCHist;
 
   std::ostringstream chi2;
   chi2 << std::setprecision(5) << this->GetLikelihood();
 
   int linecolor = kRed;
   int linestyle = 1;
   int linewidth = 1;
 
   int fillcolor = 0;
   int fillstyle = 1001;
 
   // if (fSettings.Has("linecolor")) linecolor = fSettings.GetI("linecolor");
   // if (fSettings.Has("linestyle")) linestyle = fSettings.GetI("linestyle");
   // if (fSettings.Has("linewidth")) linewidth = fSettings.GetI("linewidth");
 
   // if (fSettings.Has("fillcolor")) fillcolor = fSettings.GetI("fillcolor");
   // if (fSettings.Has("fillstyle")) fillstyle = fSettings.GetI("fillstyle");
 
   fMCHist->SetTitle(chi2.str().c_str());
 
   fMCHist->SetLineColor(linecolor);
   fMCHist->SetLineStyle(linestyle);
   fMCHist->SetLineWidth(linewidth);
 
   fMCHist->SetFillColor(fillcolor);
   fMCHist->SetFillStyle(fillstyle);
 
   return fMCHist;
 };
 
 //********************************************************************
 TH1D* Measurement1D::GetDataHistogram() {
 //********************************************************************
 
   if (!fDataHist) return fDataHist;
 
   int datacolor = kBlack;
   int datastyle = 1;
   int datawidth = 1;
 
   // if (fSettings.Has("datacolor")) datacolor = fSettings.GetI("datacolor");
   // if (fSettings.Has("datastyle")) datastyle = fSettings.GetI("datastyle");
   // if (fSettings.Has("datawidth")) datawidth = fSettings.GetI("datawidth");
 
   fDataHist->SetLineColor(datacolor);
   fDataHist->SetLineWidth(datawidth);
   fDataHist->SetMarkerStyle(datastyle);
 
   return fDataHist;
 };
 
 
 /*
    Write Functions
 */
 
 // Save all the histograms at once
 //********************************************************************
 void Measurement1D::Write(std::string drawOpt) {
 //********************************************************************
 
   // Get Draw Options
   drawOpt = FitPar::Config().GetParS("drawopts");
 
   // Write Settigns
   if (drawOpt.find("SETTINGS") != std::string::npos){
     fSettings.Set("#chi^{2}",fLikelihood);
     fSettings.Set("NDOF", this->GetNDOF() );
     fSettings.Set("#chi^{2}/NDOF", fLikelihood / this->GetNDOF() );
     fSettings.Write();
   }
 
   // Write Data/MC
   GetDataList().at(0)->Write();
   GetMCList().at(0)->Write();
 
   if(fEvtRateScaleFactor != 0xdeadbeef){
     TH1D * PredictedEvtRate = static_cast<TH1D *>(GetMCList().at(0)->Clone());
     PredictedEvtRate->Scale(fEvtRateScaleFactor);
     PredictedEvtRate->GetYaxis()->SetTitle("Predicted event rate");
     PredictedEvtRate->Write();
   }
 
 
   // Write Fine Histogram
   if (drawOpt.find("FINE") != std::string::npos)
     GetFineList().at(0)->Write();
 
   // Write Weighted Histogram
   if (drawOpt.find("WEIGHTS") != std::string::npos && fMCWeighted)
     fMCWeighted->Write();
 
 
   // Save Flux/Evt if no event manager
   if (!FitPar::Config().GetParB("EventManager")) {
 
     if (drawOpt.find("FLUX") != std::string::npos && GetFluxHistogram())
       GetFluxHistogram()->Write();
 
     if (drawOpt.find("EVT") != std::string::npos && GetEventHistogram())
       GetEventHistogram()->Write();
 
     if (drawOpt.find("XSEC") != std::string::npos && GetEventHistogram())
       GetXSecHistogram()->Write();
 
   }
 
   // Write Mask
   if (fIsMask && (drawOpt.find("MASK") != std::string::npos)) {
     fMaskHist->Write();
   }
 
 
   // Write Covariances
   if (drawOpt.find("COV") != std::string::npos && fFullCovar) {
     PlotUtils::GetFullCovarPlot(fFullCovar, fSettings.GetName());
   }
 
   if (drawOpt.find("INVCOV") != std::string::npos && covar) {
     PlotUtils::GetInvCovarPlot(covar, fSettings.GetName());
   }
 
   if (drawOpt.find("DECOMP") != std::string::npos && fDecomp) {
     PlotUtils::GetDecompCovarPlot(fDecomp, fSettings.GetName());
   }
 
   // // Likelihood residual plots
   // if (drawOpt.find("RESIDUAL") != std::string::npos) {
   //   WriteResidualPlots();
   // }
 
   // Ratio and Shape Plots
   if (drawOpt.find("RATIO") != std::string::npos) {
     WriteRatioPlot();
   }
 
   if (drawOpt.find("SHAPE") != std::string::npos) {
     WriteShapePlot();
     if (drawOpt.find("RATIO") != std::string::npos)
       WriteShapeRatioPlot();
   }
 
   // // RATIO
   // if (drawOpt.find("CANVMC") != std::string::npos) {
   //   TCanvas* c1 = WriteMCCanvas(fDataHist, fMCHist);
   //   c1->Write();
   //   delete c1;
   // }
 
   // // PDG
   // if (drawOpt.find("CANVPDG") != std::string::npos && fMCHist_Modes) {
   //   TCanvas* c2 = WritePDGCanvas(fDataHist, fMCHist, fMCHist_Modes);
   //   c2->Write();
   //   delete c2;
   // }
 
   // Write Extra Histograms
   AutoWriteExtraTH1();
   WriteExtraHistograms();
 
   // Returning
   LOG(SAM) << "Written Histograms: " << fName << std::endl;
   return;
 }
 
 //********************************************************************
 void Measurement1D::WriteRatioPlot() {
 //********************************************************************
 
   // Setup mc data ratios
   TH1D* dataRatio = (TH1D*)fDataHist->Clone((fName + "_data_RATIO").c_str());
   TH1D* mcRatio   = (TH1D*)fMCHist->Clone((fName + "_MC_RATIO").c_str());
 
   // Extra MC Data Ratios
   for (int i = 0; i < mcRatio->GetNbinsX(); i++) {
 
     dataRatio->SetBinContent(i + 1, fDataHist->GetBinContent(i + 1) / fMCHist->GetBinContent(i + 1));
     dataRatio->SetBinError(i + 1,   fDataHist->GetBinError(i + 1)   / fMCHist->GetBinContent(i + 1));
 
     mcRatio->SetBinContent(i + 1, fMCHist->GetBinContent(i + 1) / fMCHist->GetBinContent(i + 1));
     mcRatio->SetBinError(i + 1,   fMCHist->GetBinError(i + 1)   / fMCHist->GetBinContent(i + 1));
 
   }
 
   // Write ratios
   mcRatio->Write();
   dataRatio->Write();
 
   delete mcRatio;
   delete dataRatio;
 }
 
 
 //********************************************************************
 void Measurement1D::WriteShapePlot() {
 //********************************************************************
 
   TH1D* mcShape = (TH1D*)fMCHist->Clone((fName + "_MC_SHAPE").c_str());
 
   TH1D* dataShape = (TH1D*)fDataHist->Clone((fName + "_data_SHAPE").c_str());
   if (fShapeCovar) StatUtils::SetDataErrorFromCov(dataShape, fShapeCovar, 1E-38);
 
   double shapeScale = 1.0;
   if (fIsRawEvents) {
     shapeScale = fDataHist->Integral() / fMCHist->Integral();
   } else {
     shapeScale = fDataHist->Integral("width") / fMCHist->Integral("width");
   }
 
   mcShape->Scale(shapeScale);
 
   std::stringstream ss;
   ss << shapeScale;
   mcShape->SetTitle(ss.str().c_str());
 
   mcShape->SetLineWidth(3);
   mcShape->SetLineStyle(7);
 
   mcShape->Write();
   dataShape->Write();
 
   delete mcShape;
 
 }
 
 //********************************************************************
 void Measurement1D::WriteShapeRatioPlot() {
 //********************************************************************
 
   // Get a mcshape histogram
   TH1D* mcShape = (TH1D*)fMCHist->Clone((fName + "_MC_SHAPE").c_str());
 
   double shapeScale = 1.0;
   if (fIsRawEvents) {
     shapeScale = fDataHist->Integral() / fMCHist->Integral();
   } else {
     shapeScale = fDataHist->Integral("width") / fMCHist->Integral("width");
   }
 
   mcShape->Scale(shapeScale);
 
   // Create shape ratio histograms
   TH1D* mcShapeRatio   = (TH1D*)mcShape->Clone((fName + "_MC_SHAPE_RATIO").c_str());
   TH1D* dataShapeRatio = (TH1D*)fDataHist->Clone((fName + "_data_SHAPE_RATIO").c_str());
 
   // Divide the histograms
   mcShapeRatio->Divide(mcShape);
   dataShapeRatio->Divide(mcShape);
 
   // Colour the shape ratio plots
   mcShapeRatio->SetLineWidth(3);
   mcShapeRatio->SetLineStyle(7);
 
   mcShapeRatio->Write();
   dataShapeRatio->Write();
 
   delete mcShapeRatio;
   delete dataShapeRatio;
 
 }
 
 
 
 
 //// CRAP TO BE REMOVED
 
 
 //********************************************************************
 void Measurement1D::SetupMeasurement(std::string inputfile, std::string type,
                                      FitWeight * rw, std::string fkdt) {
   //********************************************************************
 
 
   nuiskey samplekey = Config::CreateKey("sample");
-  samplekey.AddS("name", fName);
-  samplekey.AddS("type",type);
-  samplekey.AddS("input",inputfile);
+  samplekey.Set("name", fName);
+  samplekey.Set("type",type);
+  samplekey.Set("input",inputfile);
   fSettings = LoadSampleSettings(samplekey);
 
   // Reset everything to NULL
   // Init();
 
   // Check if name contains Evt, indicating that it is a raw number of events
   // measurements and should thus be treated as once
   fIsRawEvents = false;
   if ((fName.find("Evt") != std::string::npos) && fIsRawEvents == false) {
     fIsRawEvents = true;
     LOG(SAM) << "Found event rate measurement but fIsRawEvents == false!"
              << std::endl;
     LOG(SAM) << "Overriding this and setting fIsRawEvents == true!"
              << std::endl;
   }
 
   fIsEnu1D = false;
   if (fName.find("XSec_1DEnu") != std::string::npos) {
     fIsEnu1D = true;
     LOG(SAM) << "::" << fName << "::" << std::endl;
     LOG(SAM) << "Found XSec Enu measurement, applying flux integrated scaling, "
              "not flux averaged!"
              << std::endl;
   }
 
   if (fIsEnu1D && fIsRawEvents) {
     LOG(SAM) << "Found 1D Enu XSec distribution AND fIsRawEvents, is this "
              "really correct?!"
              << std::endl;
     LOG(SAM) << "Check experiment constructor for " << fName
              << " and correct this!" << std::endl;
     LOG(SAM) << "I live in " << __FILE__ << ":" << __LINE__ << std::endl;
     exit(-1);
   }
 
   fRW = rw;
 
   if (!fInput and !fIsJoint) SetupInputs(inputfile);
 
   // Set Default Options
   SetFitOptions(fDefaultTypes);
 
   // Set Passed Options
   SetFitOptions(type);
 
   // Still adding support for flat flux inputs
   //  // Set Enu Flux Scaling
   //  if (isFlatFluxFolding) this->Input()->ApplyFluxFolding(
   //  this->defaultFluxHist );
 
   // FinaliseMeasurement();
 }
 
 //********************************************************************
 void Measurement1D::SetupDefaultHist() {
   //********************************************************************
 
   // Setup fMCHist
   fMCHist = (TH1D*)fDataHist->Clone();
   fMCHist->SetNameTitle((fName + "_MC").c_str(),
                         (fName + "_MC" + fPlotTitles).c_str());
 
   // Setup fMCFine
   Int_t nBins = fMCHist->GetNbinsX();
   fMCFine = new TH1D(
     (fName + "_MC_FINE").c_str(), (fName + "_MC_FINE" + fPlotTitles).c_str(),
     nBins * 6, fMCHist->GetBinLowEdge(1), fMCHist->GetBinLowEdge(nBins + 1));
 
   fMCStat = (TH1D*)fMCHist->Clone();
   fMCStat->Reset();
 
   fMCHist->Reset();
   fMCFine->Reset();
 
   // Setup the NEUT Mode Array
   PlotUtils::CreateNeutModeArray((TH1D*)fMCHist, (TH1**)fMCHist_PDG);
   PlotUtils::ResetNeutModeArray((TH1**)fMCHist_PDG);
 
   // Setup bin masks using sample name
   if (fIsMask) {
     std::string maskloc = FitPar::Config().GetParDIR(fName + ".mask");
     if (maskloc.empty()) {
       maskloc = FitPar::GetDataBase() + "/masks/" + fName + ".mask";
     }
 
     SetBinMask(maskloc);
   }
 
   fMCHist_Modes = new TrueModeStack( (fName + "_MODES").c_str(), ("True Channels"), fMCHist);
   SetAutoProcessTH1(fMCHist_Modes, kCMD_Reset, kCMD_Norm, kCMD_Write);
 
   return;
 }
 
 
 
 
 
 //********************************************************************
 void Measurement1D::SetDataValues(std::string dataFile) {
   //********************************************************************
 
   // Override this function if the input file isn't in a suitable format
   LOG(SAM) << "Reading data from: " << dataFile.c_str() << std::endl;
   fDataHist =
     PlotUtils::GetTH1DFromFile(dataFile, (fName + "_data"), fPlotTitles);
   fDataTrue = (TH1D*)fDataHist->Clone();
 
   // Number of data points is number of bins
   fNDataPointsX = fDataHist->GetXaxis()->GetNbins();
 
   return;
 };
 
 
 
 
 
 //********************************************************************
 void Measurement1D::SetDataFromDatabase(std::string inhistfile,
                                         std::string histname) {
   //********************************************************************
 
   LOG(SAM) << "Filling histogram from " << inhistfile << "->" << histname
            << std::endl;
   fDataHist = PlotUtils::GetTH1DFromRootFile(
                 (GeneralUtils::GetTopLevelDir() + "/data/" + inhistfile), histname);
   fDataHist->SetNameTitle((fName + "_data").c_str(), (fName + "_data").c_str());
 
   return;
 };
 
 //********************************************************************
 void Measurement1D::SetDataFromFile(std::string inhistfile,
                                     std::string histname) {
   //********************************************************************
 
   LOG(SAM) << "Filling histogram from " << inhistfile << "->" << histname
            << std::endl;
   fDataHist = PlotUtils::GetTH1DFromRootFile((inhistfile), histname);
   fDataHist->SetNameTitle((fName + "_data").c_str(), (fName + "_data").c_str());
 
   return;
 };
 
 //********************************************************************
 void Measurement1D::SetCovarMatrix(std::string covarFile) {
   //********************************************************************
 
   // Covariance function, only really used when reading in the MB Covariances.
 
   TFile* tempFile = new TFile(covarFile.c_str(), "READ");
 
   TH2D* covarPlot = new TH2D();
   //  TH2D* decmpPlot = new TH2D();
   TH2D* covarInvPlot = new TH2D();
   TH2D* fFullCovarPlot = new TH2D();
   std::string covName = "";
   std::string covOption = FitPar::Config().GetParS("thrown_covariance");
 
   if (fIsShape || fIsFree) covName = "shp_";
   if (fIsDiag)
     covName += "diag";
   else
     covName += "full";
 
   covarPlot = (TH2D*)tempFile->Get((covName + "cov").c_str());
   covarInvPlot = (TH2D*)tempFile->Get((covName + "covinv").c_str());
 
   if (!covOption.compare("SUB"))
     fFullCovarPlot = (TH2D*)tempFile->Get((covName + "cov").c_str());
   else if (!covOption.compare("FULL"))
     fFullCovarPlot = (TH2D*)tempFile->Get("fullcov");
   else
     ERR(WRN) << "Incorrect thrown_covariance option in parameters."
              << std::endl;
 
   int dim = int(fDataHist->GetNbinsX());  //-this->masked->Integral());
   int covdim = int(fDataHist->GetNbinsX());
 
   this->covar = new TMatrixDSym(dim);
   fFullCovar = new TMatrixDSym(dim);
   fDecomp = new TMatrixDSym(dim);
 
   int row, column = 0;
   row = 0;
   column = 0;
   for (Int_t i = 0; i < covdim; i++) {
     // if (this->masked->GetBinContent(i+1) > 0) continue;
 
     for (Int_t j = 0; j < covdim; j++) {
       //   if (this->masked->GetBinContent(j+1) > 0) continue;
 
       (*this->covar)(row, column) = covarPlot->GetBinContent(i + 1, j + 1);
       (*fFullCovar)(row, column) = fFullCovarPlot->GetBinContent(i + 1, j + 1);
 
       column++;
     }
     column = 0;
     row++;
   }
 
   // Set bin errors on data
   if (!fIsDiag) {
     StatUtils::SetDataErrorFromCov(fDataHist, fFullCovar);
   }
 
   // Get Deteriminant and inverse matrix
   // fCovDet = this->covar->Determinant();
 
   TDecompSVD LU = TDecompSVD(*this->covar);
   this->covar = new TMatrixDSym(dim, LU.Invert().GetMatrixArray(), "");
 
   return;
 };
 
 //********************************************************************
 // Sets the covariance matrix from a provided file in a text format
 // scale is a multiplicative pre-factor to apply in the case where the
 // covariance is given in some unit (e.g. 1E-38)
 void Measurement1D::SetCovarMatrixFromText(std::string covarFile, int dim,
     double scale) {
   //********************************************************************
 
   // Make a counter to track the line number
   int row = 0;
 
   std::string line;
   std::ifstream covarread(covarFile.c_str(), ifstream::in);
 
   this->covar = new TMatrixDSym(dim);
   fFullCovar = new TMatrixDSym(dim);
   if (covarread.is_open())
     LOG(SAM) << "Reading covariance matrix from file: " << covarFile
              << std::endl;
   else
     ERR(FTL) << "Covariance matrix provided is incorrect: " << covarFile
              << std::endl;
 
   // Loop over the lines in the file
   while (std::getline(covarread >> std::ws, line, '\n')) {
     int column = 0;
 
     // Loop over entries and insert them into matrix
     std::vector<double> entries = GeneralUtils::ParseToDbl(line, " ");
 
     if (entries.size() <= 1) {
       ERR(WRN) << "SetCovarMatrixFromText -> Covariance matrix only has <= 1 "
                "entries on this line: "
                << row << std::endl;
     }
 
     for (std::vector<double>::iterator iter = entries.begin();
          iter != entries.end(); iter++) {
       (*covar)(row, column) = *iter;
       (*fFullCovar)(row, column) = *iter;
 
       column++;
     }
 
     row++;
   }
   covarread.close();
 
   // Scale the actualy covariance matrix by some multiplicative factor
   (*fFullCovar) *= scale;
 
   // Robust matrix inversion method
   TDecompSVD LU = TDecompSVD(*this->covar);
   // THIS IS ACTUALLY THE INVERSE COVARIANCE MATRIXA AAAAARGH
   delete this->covar;
   this->covar = new TMatrixDSym(dim, LU.Invert().GetMatrixArray(), "");
 
   // Now need to multiply by the scaling factor
   // If the covariance
   (*this->covar) *= 1. / (scale);
 
   return;
 };
 
 //********************************************************************
 void Measurement1D::SetCovarMatrixFromCorrText(std::string corrFile, int dim) {
   //********************************************************************
 
   // Make a counter to track the line number
   int row = 0;
 
   std::string line;
   std::ifstream corr(corrFile.c_str(), ifstream::in);
 
   this->covar = new TMatrixDSym(dim);
   this->fFullCovar = new TMatrixDSym(dim);
   if (corr.is_open())
     LOG(SAM) << "Reading and converting correlation matrix from file: "
              << corrFile << std::endl;
   else {
     ERR(FTL) << "Correlation matrix provided is incorrect: " << corrFile
              << std::endl;
     exit(-1);
   }
 
   while (std::getline(corr >> std::ws, line, '\n')) {
     int column = 0;
 
     // Loop over entries and insert them into matrix
     // Multiply by the errors to get the covariance, rather than the correlation
     // matrix
     std::vector<double> entries = GeneralUtils::ParseToDbl(line, " ");
     for (std::vector<double>::iterator iter = entries.begin();
          iter != entries.end(); iter++) {
       double val = (*iter) * this->fDataHist->GetBinError(row + 1) * 1E38 *
                    this->fDataHist->GetBinError(column + 1) * 1E38;
       if (val == 0) {
         ERR(FTL) << "Found a zero value in the covariance matrix, assuming "
                  "this is an error!"
                  << std::endl;
         exit(-1);
       }
 
       (*this->covar)(row, column) = val;
       (*this->fFullCovar)(row, column) = val;
 
       column++;
     }
 
     row++;
   }
 
   // Robust matrix inversion method
   TDecompSVD LU = TDecompSVD(*this->covar);
   delete this->covar;
   this->covar = new TMatrixDSym(dim, LU.Invert().GetMatrixArray(), "");
 
   return;
 };
 
 
 
 
 
 
 //********************************************************************
 // FullUnits refers to if we have "real" unscaled units in the covariance matrix, e.g. 1E-76.
 // If this is the case we need to scale it so that the chi2 contribution is correct
 // NUISANCE internally assumes the covariance matrix has units of 1E76
 void Measurement1D::SetCovarFromDataFile(std::string covarFile,
     std::string covName, bool FullUnits) {
   //********************************************************************
 
   LOG(SAM) << "Getting covariance from " << covarFile << "->" << covName
            << std::endl;
 
   TFile* tempFile = new TFile(covarFile.c_str(), "READ");
   TH2D* covPlot = (TH2D*)tempFile->Get(covName.c_str());
   covPlot->SetDirectory(0);
   // Scale the covariance matrix if it comes in normal units
   if (FullUnits) {
     covPlot->Scale(1.E76);
   }
 
   int dim = covPlot->GetNbinsX();
   fFullCovar = new TMatrixDSym(dim);
 
   for (int i = 0; i < dim; i++) {
     for (int j = 0; j < dim; j++) {
       (*fFullCovar)(i, j) = covPlot->GetBinContent(i + 1, j + 1);
     }
   }
 
   this->covar = (TMatrixDSym*)fFullCovar->Clone();
   fDecomp = (TMatrixDSym*)fFullCovar->Clone();
 
   TDecompSVD LU = TDecompSVD(*this->covar);
   this->covar = new TMatrixDSym(dim, LU.Invert().GetMatrixArray(), "");
 
   TDecompChol LUChol = TDecompChol(*fDecomp);
   LUChol.Decompose();
   fDecomp = new TMatrixDSym(dim, LU.GetU().GetMatrixArray(), "");
 
   return;
 };
 
 // //********************************************************************
 // void Measurement1D::SetBinMask(std::string maskFile) {
 //   //********************************************************************
 
 //   // Create a mask histogram.
 //   int nbins = fDataHist->GetNbinsX();
 //   fMaskHist =
 //     new TH1I((fName + "_fMaskHist").c_str(),
 //              (fName + "_fMaskHist; Bin; Mask?").c_str(), nbins, 0, nbins);
 //   std::string line;
 //   std::ifstream mask(maskFile.c_str(), ifstream::in);
 
 //   if (mask.is_open())
 //     LOG(SAM) << "Reading bin mask from file: " << maskFile << std::endl;
 //   else
 //     LOG(FTL) << " Cannot find mask file." << std::endl;
 
 //   while (std::getline(mask >> std::ws, line, '\n')) {
 //     std::vector<int> entries = GeneralUtils::ParseToInt(line, " ");
 
 //     // Skip lines with poorly formatted lines
 //     if (entries.size() < 2) {
 //       LOG(WRN) << "Measurement1D::SetBinMask(), couldn't parse line: " << line
 //                << std::endl;
 //       continue;
 //     }
 
 //     // The first index should be the bin number, the second should be the mask
 //     // value.
 //     fMaskHist->SetBinContent(entries[0], entries[1]);
 //   }
 
 //   // Set masked data bins to zero
 //   PlotUtils::MaskBins(fDataHist, fMaskHist);
 
 //   return;
 // }
 
 // //********************************************************************
 // void Measurement1D::GetBinContents(std::vector<double>& cont,
 //                                    std::vector<double>& err) {
 //   //********************************************************************
 
 //   // Return a vector of the main bin contents
 //   for (int i = 0; i < fMCHist->GetNbinsX(); i++) {
 //     cont.push_back(fMCHist->GetBinContent(i + 1));
 //     err.push_back(fMCHist->GetBinError(i + 1));
 //   }
 
 //   return;
 // };
 
 
 /*
    XSec Functions
    */
 
 // //********************************************************************
 // void Measurement1D::SetFluxHistogram(std::string fluxFile, int minE, int
 // maxE,
 //     double fluxNorm) {
 //   //********************************************************************
 
 //   // Note this expects the flux bins to be given in terms of MeV
 //   LOG(SAM) << "Reading flux from file: " << fluxFile << std::endl;
 
 //   TGraph f(fluxFile.c_str(), "%lg %lg");
 
 //   fFluxHist =
 //     new TH1D((fName + "_flux").c_str(), (fName + "; E_{#nu} (GeV)").c_str(),
 //         f.GetN() - 1, minE, maxE);
 
 //   Double_t* yVal = f.GetY();
 
 //   for (int i = 0; i < fFluxHist->GetNbinsX(); ++i)
 //     fFluxHist->SetBinContent(i + 1, yVal[i] * fluxNorm);
 // };
 
 // //********************************************************************
 // double Measurement1D::TotalIntegratedFlux(std::string intOpt, double low,
 //     double high) {
 //   //********************************************************************
 
 //   if (fInput->GetType() == kGiBUU) {
 //     return 1.0;
 //   }
 
 //   // The default case of low = -9999.9 and high = -9999.9
 //   if (low == -9999.9) low = this->EnuMin;
 //   if (high == -9999.9) high = this->EnuMax;
 
 //   int minBin = fFluxHist->GetXaxis()->FindBin(low);
 //   int maxBin = fFluxHist->GetXaxis()->FindBin(high);
 
 //   // Get integral over custom range
 //   double integral = fFluxHist->Integral(minBin, maxBin + 1, intOpt.c_str());
 
 //   return integral;
 // };
 
diff --git a/src/FitBase/Measurement1D.h b/src/FitBase/Measurement1D.h
index 404ba50..dbd6471 100644
--- a/src/FitBase/Measurement1D.h
+++ b/src/FitBase/Measurement1D.h
@@ -1,655 +1,656 @@
 // Copyright 2016 L. Pickering, P towell, R. Terri, C. Wilkinson, C. Wret
 
 /*******************************************************************************
 *    This file is part of NUISANCE.
 *
 *    NUISANCE is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    NUISANCE is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with NUISANCE.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
 
 #ifndef MEASUREMENT_1D_H_SEEN
 #define MEASUREMENT_1D_H_SEEN
 
 /*!
  *  \addtogroup FitBase
  *  @{
  */
 
 #include <math.h>
 #include <stdlib.h>
 #include <deque>
 #include <iomanip>
 #include <iostream>
 #include <numeric>
 #include <sstream>
 #include <string>
 
 // ROOT includes
 #include <TArrayF.h>
 #include <TCanvas.h>
 #include <TCut.h>
 #include <TDecompChol.h>
 #include <TDecompSVD.h>
 #include <TGraph.h>
 #include <TGraphErrors.h>
 #include <TH1D.h>
 #include <TH2D.h>
 #include <TMatrixDSym.h>
 #include <TROOT.h>
 #include <TSystem.h>
 
 // External data fit includes
 #include "FitEvent.h"
-#include "FitParameters.h"
+
 #include "FitUtils.h"
 #include "MeasurementBase.h"
 #include "PlotUtils.h"
 #include "StatUtils.h"
 
 #include "SignalDef.h"
 #include "MeasurementVariableBox.h"
 #include "MeasurementVariableBox1D.h"
 
 namespace NUISANCE {
 namespace FitBase {
 
 }
 }
 
 //********************************************************************
 /// 1D Measurement base class. Histogram handling is done in this base layer.
 class Measurement1D : public MeasurementBase {
 //********************************************************************
 
 public:
   /*
     Constructor/Deconstuctor
   */
   Measurement1D(void);
   virtual ~Measurement1D(void);
 
   /*
     Setup Functions
   */
 
   /// \brief Setup all configs once initialised
   ///
   /// Should be called after all configs have been setup inside fSettings container.
   /// Handles the processing of inputs and setting up of types.
   /// Replaces the old 'SetupMeasurement' function.
   void FinaliseSampleSettings();
 
   /// \brief Creates the 1D data distribution given the binning provided.
   virtual void CreateDataHistogram(int dimx, double* binx);
 
   /// \brief Read 1D data inputs from a text file.
   ///
   /// Inputfile should have the format: \n
   /// low_binedge_1    bin_content_1  bin_error_1 \n
   /// low_binedge_2    bin_content_2  bin_error_2 \n
   /// ....             ....           ....        \n
   /// high_bin_edge_N  0.0            0.0
   virtual void SetDataFromTextFile(std::string datafile);
 
   /// \brief Read 1D data inputs from a root file.
   ///
   /// inhistfile specifies the path to the root file
   /// histname specifies the name of the histogram.
   ///
   /// If no histogram name is given the inhistfile value
   /// is automatically parsed with ';' so that: \n
   /// 'myhistfile.root;myhistname' \n
   /// will also work.
   virtual void SetDataFromRootFile(std::string inhistfile, std::string histname = "");
 
 
   /// \brief Setup a default empty data histogram
   ///
   /// Only used for flattree creators.
   virtual void SetEmptyData();
 
   /// \brief Set data bin errors to sqrt(entries)
   ///
   /// \warning REQUIRES DATA HISTOGRAM TO BE SET FIRST
   ///
   /// Sets the data errors as the sqrt of the bin contents
   /// Should be use for counting experiments
   virtual void SetPoissonErrors();
 
   /// \brief Make diagonal covariance from data
   ///
   /// \warning If no histogram passed, data must be setup first!
   /// Setup the covariance inputs by taking the data histogram
   /// errors and setting up a diagonal covariance matrix.
   ///
   /// If no data is supplied, fDataHist is used if already set.
   virtual void SetCovarFromDiagonal(TH1D* data = NULL);
 
   /// \brief Read the data covariance from a text file.
   ///
   /// Inputfile should have the format: \n
   /// covariance_11  covariance_12  covariance_13 ... \n
   /// covariance_21  covariance_22  covariance_23 ... \n
   /// ...            ...            ...           ... \n
   ///
   /// If no dimensions are given, it is assumed from the number
   /// entries in the first line of covfile.
   virtual void SetCovarFromTextFile(std::string covfile, int dim = -1);
 
   virtual void SetCovarFromMultipleTextFiles(std::string covfiles, int dim = -1);
 
   /// \brief Read the data covariance from a ROOT file.
   ///
   /// - covfile specifies the full path to the file
   /// - histname specifies the name of the covariance object. Both TMatrixDSym and TH2D are supported.
   ///
   /// If no histogram name is given the inhistfile value
   /// is automatically parsed with ; so that: \n
   /// mycovfile.root;myhistname \n
   /// will also work.
   virtual void SetCovarFromRootFile(std::string covfile, std::string histname="");
 
   /// \brief Read the inverted data covariance from a text file.
   ///
   /// Inputfile should have similar format to that shown
   /// in SetCovarFromTextFile.
   ///
   /// If no dimensions are given, it is assumed from the number
   /// entries in the first line of covfile.
   virtual void SetCovarInvertFromTextFile(std::string covfile, int dim = -1);
 
 
   /// \brief Read the inverted data covariance from a ROOT file.
   ///
   /// Inputfile should have similar format to that shown
   /// in SetCovarFromRootFile.
   ///
   /// If no histogram name is given the inhistfile value
   /// is automatically parsed with ; so that: \n
   /// mycovfile.root;myhistname \n
   /// will also work.
   virtual void SetCovarInvertFromRootFile(std::string covfile, std::string histname="");
 
   /// \brief Read the data correlations from a text file.
   ///
   /// \warning REQUIRES DATA HISTOGRAM TO BE SET FIRST
   ///
   /// Inputfile should have similar format to that shown
   /// in SetCovarFromTextFile.
   ///
   /// If no dimensions are given, it is assumed from the number
   /// entries in the first line of covfile.
   virtual void SetCorrelationFromTextFile(std::string covfile, int dim = -1);
 
   /// \brief Read the data correlations from multiple text files.
   ///
   /// \warning REQUIRES DATA HISTOGRAM TO BE SET FIRST
   ///
   /// Inputfile should have similar format to that shown
   /// in SetCovarFromTextFile.
   ///
   /// If no dimensions are given, it is assumed from the number
   /// entries in the first line of the first corrfile.
   virtual void SetCorrelationFromMultipleTextFiles(std::string corrfiles, int dim = -1);
 
   /// \brief Read the data correlations from a ROOT file.
   ///
   /// \warning REQUIRES DATA TO BE SET FIRST
   ///
   /// Inputfile should have similar format to that shown
   /// in SetCovarFromRootFile.
   ///
   /// If no histogram name is given the inhistfile value
   /// is automatically parsed with ; so that: \n
   /// mycovfile.root;myhistname \n
   /// will also work.
   virtual void SetCorrelationFromRootFile(std::string covfile, std::string histname="");
 
 
   /// \brief Read the cholesky decomposed covariance from a text file and turn it into a covariance
   ///
   /// Inputfile should have similar format to that shown
   /// in SetCovarFromTextFile.
   ///
   /// If no dimensions are given, it is assumed from the number
   /// entries in the first line of covfile.
   virtual void SetCholDecompFromTextFile(std::string covfile, int dim = -1);
 
 
   /// \brief Read the cholesky decomposed covariance from a ROOT file and turn it into a covariance
   ///
   /// Inputfile should have similar format to that shown
   /// in SetCovarFromRootFile.
   ///
   /// If no histogram name is given the inhistfile value
   /// is automatically parsed with ; so that: \n
   /// mycovfile.root;myhistname \n
   /// will also work.
   virtual void SetCholDecompFromRootFile(std::string covfile, std::string histname="");
 
   /// \brief Try to extract a shape-only matrix from the existing covariance
   virtual void SetShapeCovar();
 
   /// \brief Scale the data by some scale factor
   virtual void ScaleData(double scale);
 
 
   /// \brief Scale the data error bars by some scale factor
   virtual void ScaleDataErrors(double scale);
 
 
   /// \brief Scale the covariaince and its invert/decomp by some scale factor.
   virtual void ScaleCovar(double scale);
 
 
 
   /// \brief Setup a bin masking histogram and apply masking to data
   ///
   /// \warning REQUIRES DATA HISTOGRAM TO BE SET FIRST
   ///
   /// Reads in a list of bins in a text file to be masked. Format is: \n
   /// bin_index_1  1 \n
   /// bin_index_2  1 \n
   /// bin_index_3  1 \n
   ///
   /// If 0 is given then a bin entry will NOT be masked. So for example: \n\n
   /// 1  1 \n
   /// 2  1 \n
   /// 3  0 \n
   /// 4  1 \n\n
   /// Will mask only the 1st, 2nd, and 4th bins.
   ///
   /// Masking can be turned on by specifiying the MASK option when creating a sample.
   /// When this is passed NUISANCE will look in the following locations for the mask file:
   /// - FitPar::Config().GetParS(fName + ".mask")
   /// - "data/masks/" + fName + ".mask";
   virtual void SetBinMask(std::string maskfile);
 
 
   /// \brief Set the current fit options from a string.
   ///
   /// This is called twice for each sample, once to set the default
   /// and once to set the current setting (if anything other than default given)
   ///
   /// For this to work properly it requires the default and allowed types to be
   /// set correctly. These should be specified as a string listing options.
   ///
   /// To split up options so that NUISANCE can automatically detect ones that
   /// are conflicting. Any options seperated with the '/' symbol are non conflicting
   /// and can be given together, whereas any seperated with the ',' symbol cannot
   /// be specified by the end user at the same time.
   ///
   /// Default Type Examples:
   /// - DIAG/FIX = Default option will be a diagonal covariance, with FIXED norm.
   /// - MASK/SHAPE = Default option will be a masked hist, with SHAPE always on.
   ///
   /// Allowed Type examples:
   /// - 'FULL/DIAG/NORM/MASK' = Any of these options can be specified.
   /// - 'FULL,FREE,SHAPE/MASK/NORM' = User can give either FULL, FREE, or SHAPE as on option.
   /// MASK and NORM can also be included as options.
   virtual void SetFitOptions(std::string opt);
 
 
   /// \brief Final constructor setup
   /// \warning Should be called right at the end of the constructor.
   ///
   /// Contains a series of checks to ensure the data and inputs have been setup.
   /// Also creates the MC histograms needed for fitting.
   void FinaliseMeasurement();
 
 
 
 
   /*
     Smearing
   */
   /// \brief Read in smearing matrix from file
   ///
   /// Set the smearing matrix from a text file given the size of the matrix
   virtual void SetSmearingMatrix(std::string smearfile, int truedim,
                                  int recodim);
 
   /// \brief Apply smearing to MC true to get MC reco
   ///
   /// Apply smearing matrix to fMCHist using fSmearingMatrix
   virtual void ApplySmearingMatrix(void);
 
 
 
   /*
     Reconfigure Functions
   */
 
   /// \brief Create a Measurement1D box
   ///
   /// Creates a new 1D variable box containing just fXVar.
   ///
   /// This box is the bare minimum required by the JointFCN when
   /// running fast reconfigures during a routine.
   /// If for some reason a sample needs extra variables to be saved then
   /// it should override this function creating its own MeasurementVariableBox
   /// that contains the extra variables.
   virtual MeasurementVariableBox* CreateBox() {return new MeasurementVariableBox1D();};
 
   /// \brief Reset all MC histograms
   ///
   /// Resets all standard histograms and those registered to auto
   /// process to zero.
   ///
   /// If extra histograms are not included in auto processing, then they must be reset
   /// by overriding this function and doing it manually if required.
   virtual void ResetAll(void);
 
   /// \brief Fill MC Histograms from XVar
   ///
   /// Fill standard histograms using fXVar, Weight read from the variable box.
   ///
   /// WARNING : Any extra MC histograms need to be filled by overriding this function,
   /// even if they have been set to auto process.
   virtual void FillHistograms(void);
 
   // \brief Convert event rates to final histogram
   ///
   /// Apply standard scaling procedure to standard mc histograms to convert from
   /// raw events to xsec prediction.
   ///
   /// If any distributions have been set to auto process
   /// that is done during this function call, and a differential xsec is assumed.
   /// If that is not the case this function must be overriden.
   virtual void ScaleEvents(void);
 
   /// \brief Scale MC by a factor=1/norm
   ///
   /// Apply a simple normalisation scaling if the option FREE or a norm_parameter
   /// has been specified in the NUISANCE routine.
   virtual void ApplyNormScale(double norm);
 
 
   /*
     Statistical Functions
   */
 
   /// \brief Get Number of degrees of freedom
   ///
   /// Returns the number bins inside the data histogram accounting for
   /// any bin masking applied.
   virtual int GetNDOF(void);
 
   /// \brief Return Data/MC Likelihood at current state
   ///
   /// Returns the likelihood of the data given the current MC prediction.
   /// Diferent likelihoods definitions are used depending on the FitOptions.
   virtual double GetLikelihood(void);
 
 
   /*
     Fake Data
   */
 
   /// \brief Set the fake data values from either a file, or MC
   ///
   /// - Setting from a file "path": \n
   /// When reading from a file the full path must be given to a standard
   /// nuisance output. The standard MC histogram should have a name that matches
   /// this sample for it to be read in.
   /// \n\n
   /// - Setting from "MC": \n
   /// If the MC option is given the current MC prediction is used as fake data.
   virtual void SetFakeDataValues(std::string fakeOption);
 
   /// \brief Reset fake data back to starting fake data
   ///
   /// Reset the fake data back to original fake data (Reset back to before
   /// ThrowCovariance was first called)
   virtual void ResetFakeData(void);
 
   /// \brief Reset fake data back to original data
   ///
   /// Reset the data histogram back to the true original dataset for this sample
   /// before any fake data was defined.
   virtual void ResetData(void);
 
   /// \brief Generate fake data by throwing the covariance.
   ///
   /// Can be used on fake MC data or just the original dataset.
   /// Call ResetFakeData or ResetData to return to values before the throw.
   virtual void ThrowCovariance(void);
 
   /// \brief Throw the data by its assigned errors and assign this to MC
   ///
   /// Used when creating data toys by assign the MC to this thrown data
   /// so that the likelihood is calculated between data and thrown data
   virtual void ThrowDataToy(void);
 
 
   /*
     Access Functions
   */
 
   /// \brief Returns nicely formatted MC Histogram
   ///
   /// Format options can also be given in the samplesettings:
   /// - linecolor
   /// - linestyle
   /// - linewidth
   /// - fillcolor
   /// - fillstyle
   ///
   /// So to have a sample line colored differently in the xml cardfile put: \n
   /// <sample name="MiniBooNE_CCQE_XSec_1DQ2_nu" input="NEUT:input.root"
   /// linecolor="2" linestyle="7"  linewidth="2" />
   virtual TH1D* GetMCHistogram(void);
 
   /// \brief Returns nicely formatted data Histogram
   ///
   /// Format options can also be given in the samplesettings:
   /// - datacolor
   /// - datastyle
   /// - datawidth
   ///
   /// So to have a sample data colored differently in the xml cardfile put: \n
   /// <sample name="MiniBooNE_CCQE_XSec_1DQ2_nu" input="NEUT:input.root"
   /// datacolor="2" datastyle="7"  datawidth="2" />
   virtual TH1D* GetDataHistogram(void);
 
   /// \brief Returns a list of all MC histograms.
   ///
   /// Override this if you have extra histograms that need to be
   /// accessed outside of the Measurement1D class.
   inline virtual std::vector<TH1*> GetMCList(void) {
     return std::vector<TH1*>(1, GetMCHistogram());
   }
 
   /// \brief Returns a list of all Data histograms.
   ///
   /// Override this if you have extra histograms that need to be
   /// accessed outside of the Measurement1D class.
   inline virtual std::vector<TH1*> GetDataList(void) {
     return std::vector<TH1*>(1, GetDataHistogram());
   }
 
   /// \brief Returns a list of all Mask histograms.
   ///
   /// Override this if you have extra histograms that need to be
   /// accessed outside of the Measurement1D class.
   inline virtual std::vector<TH1*> GetMaskList(void) {
     return std::vector<TH1*>(1, fMaskHist);
   };
 
   /// \brief Returns a list of all Fine histograms.
   ///
   /// Override this if you have extra histograms that need to be
   /// accessed outside of the Measurement1D class.
   inline virtual std::vector<TH1*> GetFineList(void) {
     return std::vector<TH1*>(1, fMCFine);
   };
 
 
   /*
     Write Functions
   */
   /// \brief Save the current state to the current TFile directory \n
   ///
   /// Data/MC are both saved by default.
   /// A range of other histograms can be saved by setting the
   /// config option 'drawopts'.
   ///
   /// Possible options: \n
   /// - FINE    = Write Fine Histogram \n
   /// - WEIGHTS = Write Weighted MC Histogram (before scaling) \n
   /// - FLUX    = Write Flux Histogram from MC Input \n
   /// - EVT     = Write Event Histogram from MC Input \n
   /// - XSEC    = Write XSec Histogram from MC Input \n
   /// - MASK    = Write Mask Histogram \n
   /// - COV     = Write Covariance Histogram \n
   /// - INVCOV  = Write Inverted Covariance Histogram \n
   /// - DECMOP  = Write Decomp. Covariance Histogram \n
   /// - RESIDUAL= Write Resudial Histograms \n
   /// - RATIO   = Write Data/MC Ratio Histograms \n
   /// - SHAPE   = Write MC Shape Histograms norm. to Data \n
   /// - CANVMC  = Build MC Canvas Showing Data, MC, Shape \n
   /// - MODES   = Write PDG Stack \n
   /// - CANVPDG = Build MC Canvas Showing Data, PDGStack \n
   ///
   /// So to save a range of these in parameters/config.xml set: \n
   /// <config drawopts='FINE/COV/SHAPE/RATIO' />
   virtual void Write(std::string drawOpt);
 
 
 
   virtual void WriteRatioPlot();
 
 
 
 
   virtual void WriteShapePlot();
   virtual void WriteShapeRatioPlot();
 
 
 
 
   //*
   // OLD DEFUNCTIONS
   //
 
   /// OLD FUNCTION
   virtual void SetupMeasurement(std::string input, std::string type,
           FitWeight* rw, std::string fkdt);
 
   /// OLD FUNCTION
   virtual void SetupDefaultHist(void);
 
   /// OLD FUNCTION
   virtual void SetDataValues(std::string dataFile);
 
   /// OLD FUNCTION
   virtual void SetDataFromFile(std::string inhistfile, std::string histname);
   /// OLD FUNCTION
   virtual void SetDataFromDatabase(std::string inhistfile,
              std::string histname);
 
   /// OLD FUNCTION
   virtual void SetCovarMatrix(std::string covarFile);
   /// OLD FUNCTION
   virtual void SetCovarMatrixFromText(std::string covarFile, int dim,
                 double scale = 1.0);
   /// OLD FUNCTION
   virtual void SetCovarMatrixFromCorrText(std::string covarFile, int dim);
 
 
   /// OLD FUNCTION
   virtual void SetCovarFromDataFile(std::string covarFile, std::string covName,
 				    bool FullUnits = false);
 
 
   /// OLD FUNCTION
   // virtual THStack GetModeStack(void);
 
 protected:
 
   // Data
   TH1D* fDataHist;  ///< default data histogram
   TH1D* fDataOrig;  ///< histogram to store original data before throws.
   TH1D* fDataTrue;  ///< histogram to store true dataset
   std::string fPlotTitles;  ///< Plot title x and y for the histograms
 
 
   // MC
   TH1D* fMCHist;     ///< default MC Histogram used in the chi2 fits
   TH1D* fMCFine;     ///< finely binned MC histogram
   TH1D* fMCStat;     ///< histogram with unweighted events to properly calculate
   TH1D* fMCWeighted; ///< Weighted histogram before xsec scaling
 
   TH1I* fMaskHist;   ///< Mask histogram for neglecting specific bins
   TMatrixD* fSmearMatrix;   ///< Smearing matrix (note, this is not symmetric)
 
   TrueModeStack* fMCHist_Modes; ///< Optional True Mode Stack
 
 
   // Statistical
   TMatrixDSym* covar;       ///< Inverted Covariance
   TMatrixDSym* fFullCovar;  ///< Full Covariance
   TMatrixDSym* fDecomp;     ///< Decomposed Covariance
   TMatrixDSym* fCorrel;     ///< Correlation Matrix
 
   TMatrixDSym* fShapeCovar;  ///< Shape-only covariance
   TMatrixDSym* fShapeDecomp; ///< Decomposed shape-only covariance
+  TMatrixDSym* fShapeInvert; ///< Inverted shape-only covariance
 
   TMatrixDSym* fCovar;    ///< New FullCovar
   TMatrixDSym* fInvert;   ///< New covar
 
   double fNormError;        ///< Sample norm error
 
   double fLikelihood; ///< Likelihood value
 
   // Fake Data
   bool fIsFakeData;            ///< Flag: is the current data fake from MC
   std::string fFakeDataInput;  ///< Input fake data file path
   TFile* fFakeDataFile;        ///< Input fake data file
 
 
   // Fit specific flags
   std::string fFitType;       ///< Current fit type
   std::string fAllowedTypes;  ///< Fit Types Possible
   std::string fDefaultTypes;  ///< Starting Default Fit Types
 
   bool fIsShape;      ///< Flag : Perform Shape-only fit
   bool fIsFree;       ///< Flag : Perform normalisation free fit
   bool fIsDiag;       ///< Flag : only include uncorrelated diagonal errors
   bool fIsMask;       ///< Flag : Apply bin masking
   bool fIsRawEvents;  ///< Flag : Are bin contents just event rates
   bool fIsEnu1D;      ///< Flag : Perform Flux Unfolded Scaling
   bool fIsChi2SVD;    ///< Flag : Use alternative Chi2 SVD Method (Do not use)
   bool fAddNormPen;   ///< Flag : Add a normalisation penalty term to the chi2.
   bool fIsFix;        ///< Flag : keeping norm fixed
   bool fIsFull;       ///< Flag : using full covariaince
   bool fIsDifXSec;    ///< Flag : creating a dif xsec
   bool fIsChi2;       ///< Flag : using Chi2 over LL methods
   bool fIsSmeared;    ///< Flag : Apply smearing?
 
 
 
 
   /// OLD STUFF TO REMOVE
   TH1D* fMCHist_PDG[61]; ///< REMOVE OLD MC PDG Plot
 
   // Arrays for data entries
   Double_t* fXBins;       ///< REMOVE xBin edges
   Double_t* fDataValues;  ///< REMOVE data bin contents
   Double_t* fDataErrors;  ///< REMOVE data bin errors
   Int_t fNDataPointsX;    ///< REMOVE number of data points
 
 };
 
 /*! @} */
 #endif
diff --git a/src/FitBase/Measurement2D.cxx b/src/FitBase/Measurement2D.cxx
index 33fdd0f..87f361f 100644
--- a/src/FitBase/Measurement2D.cxx
+++ b/src/FitBase/Measurement2D.cxx
@@ -1,1961 +1,1961 @@
 // Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret
 
 /*******************************************************************************
 *    This file is part of NUISANCE.
 *
 *    NUISANCE is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    NUISANCE is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with NUISANCE.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
 
 #include "Measurement2D.h"
 #include "TDecompChol.h"
 
 
 //********************************************************************
 Measurement2D::Measurement2D(void) {
 //********************************************************************
 
   covar = NULL;
   fDecomp = NULL;
   fFullCovar = NULL;
 
   fMCHist = NULL;
   fMCFine = NULL;
   fDataHist = NULL;
 
   fMCHist_X = NULL;
   fMCHist_Y = NULL;
   fDataHist_X = NULL;
   fDataHist_Y = NULL;
 
   fMaskHist = NULL;
   fMapHist = NULL;
   fDataOrig = NULL;
   fDataTrue = NULL;
   fMCWeighted = NULL;
 
   fDefaultTypes = "FIX/FULL/CHI2";
   fAllowedTypes =
     "FIX,FREE,SHAPE/FULL,DIAG/CHI2/NORM/ENUCORR/Q2CORR/ENU1D/FITPROJX/"
     "FITPROJY";
 
   fIsFix = false;
   fIsShape = false;
   fIsFree = false;
 
   fIsDiag = false;
   fIsFull = false;
 
   fAddNormPen = false;
   fIsMask = false;
   fIsChi2SVD = false;
 
   fIsRawEvents = false;
   fIsDifXSec = false;
   fIsEnu = false;
 
 
   // XSec Scalings
   fScaleFactor = -1.0;
   fCurrentNorm = 1.0;
 
   // Histograms
   fDataHist = NULL;
   fDataTrue = NULL;
 
   fMCHist = NULL;
   fMCFine = NULL;
   fMCWeighted = NULL;
 
   fMaskHist = NULL;
 
   // Covar
   covar = NULL;
   fFullCovar = NULL;
 
   fCovar  = NULL;
   fInvert = NULL;
   fDecomp = NULL;
 
   // Fake Data
   fFakeDataInput = "";
   fFakeDataFile  = NULL;
 
   // Options
   fDefaultTypes = "FIX/FULL/CHI2";
   fAllowedTypes =
     "FIX,FREE,SHAPE/FULL,DIAG/CHI2/NORM/ENUCORR/Q2CORR/ENU1D/MASK";
 
   fIsFix = false;
   fIsShape = false;
   fIsFree = false;
   fIsDiag = false;
   fIsFull = false;
   fAddNormPen = false;
   fIsMask = false;
   fIsChi2SVD = false;
   fIsRawEvents = false;
   fIsDifXSec = false;
   fIsEnu1D = false;
 
   // Inputs
   fInput = NULL;
   fRW = NULL;
 
   // Extra Histograms
   fMCHist_Modes = NULL;
 
 }
 
 //********************************************************************
 Measurement2D::~Measurement2D(void) {
 //********************************************************************
 
   if (fDataHist)   delete fDataHist;
   if (fDataTrue)   delete fDataTrue;
   if (fMCHist)     delete fMCHist;
   if (fMCFine)     delete fMCFine;
   if (fMCWeighted) delete fMCWeighted;
   if (fMaskHist)   delete fMaskHist;
   if (covar)       delete covar;
   if (fFullCovar)  delete fFullCovar;
   if (fCovar)      delete fCovar;
   if (fInvert)     delete fInvert;
   if (fDecomp)     delete fDecomp;
 
 }
 
 //********************************************************************
 void Measurement2D::FinaliseSampleSettings() {
 //********************************************************************
 
   MeasurementBase::FinaliseSampleSettings();
 
   // Setup naming + renaming
   fName = fSettings.GetName();
   fSettings.SetS("originalname", fName);
   if (fSettings.Has("rename")) {
     fName = fSettings.GetS("rename");
     fSettings.SetS("name", fName);
   }
 
   // Setup all other options
   LOG(SAM) << "Finalising Sample Settings: " << fName << std::endl;
 
   if ((fSettings.GetS("originalname").find("Evt") != std::string::npos)) {
     fIsRawEvents = true;
     LOG(SAM) << "Found event rate measurement but using poisson likelihoods."
              << std::endl;
   }
 
   if (fSettings.GetS("originalname").find("XSec_1DEnu") != std::string::npos) {
     fIsEnu1D = true;
     LOG(SAM) << "::" << fName << "::" << std::endl;
     LOG(SAM) << "Found XSec Enu measurement, applying flux integrated scaling, "
              << "not flux averaged!" << std::endl;
   }
 
   if (fIsEnu1D && fIsRawEvents) {
     LOG(SAM) << "Found 1D Enu XSec distribution AND fIsRawEvents, is this "
              "really correct?!"
              << std::endl;
     LOG(SAM) << "Check experiment constructor for " << fName
              << " and correct this!" << std::endl;
     LOG(SAM) << "I live in " << __FILE__ << ":" << __LINE__ << std::endl;
     exit(-1);
   }
 
   if (!fRW) fRW = FitBase::GetRW();
   if (!fInput) SetupInputs(fSettings.GetS("input"));
 
   // Setup options
   SetFitOptions(fDefaultTypes); // defaults
   SetFitOptions(fSettings.GetS("type")); // user specified
 
   EnuMin = GeneralUtils::StrToDbl(fSettings.GetS("enu_min"));
   EnuMax = GeneralUtils::StrToDbl(fSettings.GetS("enu_max"));
 
   if (fAddNormPen) {
     fNormError = fSettings.GetNormError();
     if (fNormError <= 0.0) {
       ERR(WRN) << "Norm error for class " << fName << " is 0.0!" << std::endl;
       ERR(WRN) << "If you want to use it please add fNormError=VAL" << std::endl;
       throw;
     }
   }
 
 }
 
 void Measurement2D::CreateDataHistogram(int dimx, double* binx, int dimy, double* biny) {
   if (fDataHist) delete fDataHist;
 
   LOG(SAM) << "Creating Data Histogram dim : " << dimx << " " << dimy << std::endl;
 
   fDataHist = new TH2D( (fSettings.GetName() + "_data").c_str(), (fSettings.GetFullTitles()).c_str(),
                         dimx - 1, binx, dimy - 1, biny );
 
 }
 
 void Measurement2D::SetDataFromTextFile(std::string datfile) {
   // fDataHist = PlotUtils::GetTH2DFromTextFile(datfile,"");
 }
 
 void Measurement2D::SetDataFromRootFile(std::string datfile, std::string histname) {
   fDataHist = PlotUtils::GetTH2DFromRootFile(datfile, histname);
 }
 
 void Measurement2D::SetDataValuesFromTextFile(std::string datfile, TH2D* hist) {
 
   LOG(SAM) << "Setting data values from text file" << std::endl;
   if (!hist) hist = fDataHist;
 
   // Read TH2D From textfile
   TH2D* valhist = (TH2D*) hist->Clone();
   valhist->Reset();
   PlotUtils::Set2DHistFromText(datfile, valhist, 1.0, true);
 
   LOG(SAM) << " -> Filling values from read hist." << std::endl;
   for (int i = 0; i < valhist->GetNbinsX(); i++) {
     for (int j = 0; j < valhist->GetNbinsY(); j++) {
       hist->SetBinContent(i + 1, j + 1, valhist->GetBinContent(i + 1, j + 1));
     }
   }
   LOG(SAM) << " --> Done" << std::endl;
 }
 
 void Measurement2D::SetDataErrorsFromTextFile(std::string datfile, TH2D* hist) {
   LOG(SAM) << "Setting data errors from text file" << std::endl;
 
   if (!hist) hist = fDataHist;
 
   // Read TH2D From textfile
   TH2D* valhist = (TH2D*) hist->Clone();
   valhist->Reset();
   PlotUtils::Set2DHistFromText(datfile, valhist, 1.0);
 
   // Fill Errors
   LOG(SAM) << " -> Filling errors from read hist." << std::endl;
 
   for (int i = 0; i < valhist->GetNbinsX(); i++) {
     for (int j = 0; j < valhist->GetNbinsY(); j++) {
       hist->SetBinError(i + 1, j + 1, valhist->GetBinContent(i + 1, j + 1));
     }
   }
   LOG(SAM) << " --> Done" << std::endl;
 
 
 }
 
 void Measurement2D::SetMapValuesFromText(std::string dataFile) {
 
   TH2D* hist = fDataHist;
   std::vector<double> edgex;
   std::vector<double> edgey;
 
   for (int i = 0; i <= hist->GetNbinsX(); i++) edgex.push_back(hist->GetXaxis()->GetBinLowEdge(i + 1));
   for (int i = 0; i <= hist->GetNbinsY(); i++) edgey.push_back(hist->GetYaxis()->GetBinLowEdge(i + 1));
 
 
   fMapHist = new TH2I((fName + "_map").c_str(), (fName + fPlotTitles).c_str(),
                       edgex.size() - 1, &edgex[0], edgey.size() - 1, &edgey[0]);
 
   LOG(SAM) << "Reading map from: " << dataFile << std::endl;
   PlotUtils::Set2DHistFromText(dataFile, fMapHist, 1.0);
 
 }
 
 //********************************************************************
 void Measurement2D::SetPoissonErrors() {
 //********************************************************************
 
   if (!fDataHist) {
     ERR(FTL) << "Need a data hist to setup possion errors! " << std::endl;
     ERR(FTL) << "Setup Data First!" << std::endl;
     throw;
   }
 
   for (int i = 0; i < fDataHist->GetNbinsX() + 1; i++) {
     fDataHist->SetBinError(i + 1, sqrt(fDataHist->GetBinContent(i + 1)));
   }
 }
 
 //********************************************************************
 void Measurement2D::SetCovarFromDiagonal(TH2D* data) {
 //********************************************************************
 
   if (!data and fDataHist) {
     data = fDataHist;
   }
 
   if (data) {
     LOG(SAM) << "Setting diagonal covariance for: " << data->GetName() << std::endl;
     fFullCovar = StatUtils::MakeDiagonalCovarMatrix(data);
     covar      = StatUtils::GetInvert(fFullCovar);
     fDecomp    = StatUtils::GetDecomp(fFullCovar);
   } else {
     ERR(FTL) << "No data input provided to set diagonal covar from!" << std::endl;
 
   }
 
   // if (!fIsDiag) {
   //   ERR(FTL) << "SetCovarMatrixFromDiag called for measurement "
   //            << "that is not set as diagonal." << std::endl;
   //   throw;
   // }
 
 }
 
 //********************************************************************
 void Measurement2D::SetCovarFromTextFile(std::string covfile, int dim) {
 //********************************************************************
 
   if (dim == -1) {
     dim = this->GetNDOF();
   }
 
-  LOG(SAM) << "Reading covariance from text file: " << covfile << std::endl;
+  LOG(SAM) << "Reading covariance from text file: " << covfile << " " << dim << std::endl;
   fFullCovar = StatUtils::GetCovarFromTextFile(covfile, dim);
   covar      = StatUtils::GetInvert(fFullCovar);
   fDecomp    = StatUtils::GetDecomp(fFullCovar);
 
 }
 
 //********************************************************************
 void Measurement2D::SetCovarFromRootFile(std::string covfile, std::string histname) {
 //********************************************************************
 
   LOG(SAM) << "Reading covariance from text file: " << covfile << ";" << histname << std::endl;
   fFullCovar = StatUtils::GetCovarFromRootFile(covfile, histname);
   covar      = StatUtils::GetInvert(fFullCovar);
   fDecomp    = StatUtils::GetDecomp(fFullCovar);
 
 }
 
 //********************************************************************
 void Measurement2D::SetCovarInvertFromTextFile(std::string covfile, int dim) {
 //********************************************************************
 
   if (dim == -1) {
     dim = this->GetNDOF();
   }
 
   LOG(SAM) << "Reading inverted covariance from text file: " << covfile << std::endl;
   covar       = StatUtils::GetCovarFromTextFile(covfile, dim);
   fFullCovar  = StatUtils::GetInvert(covar);
   fDecomp     = StatUtils::GetDecomp(fFullCovar);
 
 }
 
 //********************************************************************
 void Measurement2D::SetCovarInvertFromRootFile(std::string covfile, std::string histname) {
 //********************************************************************
 
   LOG(SAM) << "Reading inverted covariance from text file: " << covfile << ";" << histname << std::endl;
   covar      = StatUtils::GetCovarFromRootFile(covfile, histname);
   fFullCovar = StatUtils::GetInvert(covar);
   fDecomp    = StatUtils::GetDecomp(fFullCovar);
 
 }
 
 //********************************************************************
 void Measurement2D::SetCorrelationFromTextFile(std::string covfile, int dim) {
 //********************************************************************
 
   if (dim == -1) dim = this->GetNDOF();
   LOG(SAM) << "Reading data correlations from text file: " << covfile << ";" << dim << std::endl;
   TMatrixDSym* correlation = StatUtils::GetCovarFromTextFile(covfile, dim);
 
   if (!fDataHist) {
     ERR(FTL) << "Trying to set correlations from text file but there is no data to build it from. \n"
              << "In constructor make sure data is set before SetCorrelationFromTextFile is called. \n" << std::endl;
     throw;
   }
 
   // Fill covar from data errors and correlations
   fFullCovar = new TMatrixDSym(dim);
   for (int i = 0; i < fDataHist->GetNbinsX(); i++) {
     for (int j = 0; j < fDataHist->GetNbinsX(); j++) {
       (*fFullCovar)(i, j) = (*correlation)(i, j) * fDataHist->GetBinError(i + 1) * fDataHist->GetBinError(j + 1) * 1.E76;
     }
   }
 
   // Fill other covars.
   covar   = StatUtils::GetInvert(fFullCovar);
   fDecomp = StatUtils::GetDecomp(fFullCovar);
 
   delete correlation;
 }
 
 //********************************************************************
 void Measurement2D::SetCorrelationFromRootFile(std::string covfile, std::string histname) {
 //********************************************************************
 
   LOG(SAM) << "Reading data correlations from text file: " << covfile << ";" << histname << std::endl;
   TMatrixDSym* correlation = StatUtils::GetCovarFromRootFile(covfile, histname);
 
   if (!fDataHist) {
     ERR(FTL) << "Trying to set correlations from text file but there is no data to build it from. \n"
              << "In constructor make sure data is set before SetCorrelationFromTextFile is called. \n" << std::endl;
     throw;
   }
 
   // Fill covar from data errors and correlations
   fFullCovar = new TMatrixDSym(fDataHist->GetNbinsX());
   for (int i = 0; i < fDataHist->GetNbinsX(); i++) {
     for (int j = 0; j < fDataHist->GetNbinsX(); j++) {
       (*fFullCovar)(i, j) = (*correlation)(i, j) * fDataHist->GetBinError(i + 1) * fDataHist->GetBinError(j + 1) * 1.E76;
     }
   }
 
   // Fill other covars.
   covar   = StatUtils::GetInvert(fFullCovar);
   fDecomp = StatUtils::GetDecomp(fFullCovar);
 
   delete correlation;
 }
 
 
 //********************************************************************
 void Measurement2D::SetCholDecompFromTextFile(std::string covfile, int dim) {
 //********************************************************************
 
   if (dim == -1) {
     dim = this->GetNDOF();
   }
 
   LOG(SAM) << "Reading cholesky from text file: " << covfile << " " << dim << std::endl;
   TMatrixD* temp = StatUtils::GetMatrixFromTextFile(covfile, dim, dim);
 
   TMatrixD* trans = (TMatrixD*)temp->Clone();
   trans->T();
   (*trans) *= (*temp);
 
   fFullCovar  = new TMatrixDSym(dim, trans->GetMatrixArray(), "");
   covar       = StatUtils::GetInvert(fFullCovar);
   fDecomp     = StatUtils::GetDecomp(fFullCovar);
 
   delete temp;
   delete trans;
 
 }
 
 //********************************************************************
 void Measurement2D::SetCholDecompFromRootFile(std::string covfile, std::string histname) {
 //********************************************************************
 
   LOG(SAM) << "Reading cholesky decomp from root file: " << covfile << ";" << histname << std::endl;
   TMatrixD* temp = StatUtils::GetMatrixFromRootFile(covfile, histname);
 
   TMatrixD* trans = (TMatrixD*)temp->Clone();
   trans->T();
   (*trans) *= (*temp);
 
   fFullCovar  = new TMatrixDSym(temp->GetNrows(), trans->GetMatrixArray(), "");
   covar       = StatUtils::GetInvert(fFullCovar);
   fDecomp     = StatUtils::GetDecomp(fFullCovar);
 
   delete temp;
   delete trans;
 }
 
 
 //********************************************************************
 void Measurement2D::ScaleData(double scale) {
 //********************************************************************
   fDataHist->Scale(scale);
 }
 
 
 //********************************************************************
 void Measurement2D::ScaleDataErrors(double scale) {
 //********************************************************************
   for (int i = 0; i < fDataHist->GetNbinsX(); i++) {
     for (int j = 0; j < fDataHist->GetNbinsY(); j++) {
       fDataHist->SetBinError(i + 1, j + 1, fDataHist->GetBinError(i + 1, j + 1) * scale);
     }
   }
 }
 
 
 
 //********************************************************************
 void Measurement2D::ScaleCovar(double scale) {
 //********************************************************************
   (*fFullCovar) *= scale;
   (*covar) *= 1.0 / scale;
   (*fDecomp) *= sqrt(scale);
 }
 
 
 //********************************************************************
 void Measurement2D::SetBinMask(std::string maskfile) {
 //********************************************************************
 
   if (!fIsMask) return;
   LOG(SAM) << "Reading bin mask from file: " << maskfile << std::endl;
 
   // Create a mask histogram with dim of data
   int nbinsx = fDataHist->GetNbinsX();
   int nbinxy = fDataHist->GetNbinsY();
   fMaskHist =
     new TH2I((fSettings.GetName() + "_BINMASK").c_str(),
              (fSettings.GetName() + "_BINMASK; Bin; Mask?").c_str(), nbinsx, 0, nbinsx, nbinxy, 0, nbinxy);
   std::string line;
   std::ifstream mask(maskfile.c_str(), ifstream::in);
 
   if (!mask.is_open()) {
     LOG(FTL) << " Cannot find mask file." << std::endl;
     throw;
   }
 
   while (std::getline(mask >> std::ws, line, '\n')) {
     std::vector<int> entries = GeneralUtils::ParseToInt(line, " ");
 
     // Skip lines with poorly formatted lines
     if (entries.size() < 2) {
       LOG(WRN) << "Measurement2D::SetBinMask(), couldn't parse line: " << line
                << std::endl;
       continue;
     }
 
     // The first index should be the bin number, the second should be the mask
     // value.
     int val = 0;
     if (entries[2] > 0) val = 1;
     fMaskHist->SetBinContent(entries[0], entries[1], val);
   }
 
   // Apply masking by setting masked data bins to zero
   PlotUtils::MaskBins(fDataHist, fMaskHist);
 
 
   return;
 }
 
 
 
 //********************************************************************
 void Measurement2D::FinaliseMeasurement() {
 //********************************************************************
 
   LOG(SAM) << "Finalising Measurement: " << fName << std::endl;
   if (fSettings.GetB("onlymc")) {
     if (fDataHist) delete fDataHist;
     fDataHist = new TH2D("empty_data", "empty_data", 1, 0.0, 1.0,1,0.0,1.0);
   }
   // Make sure data is setup
   if (!fDataHist) {
     ERR(FTL) << "No data has been setup inside " << fName << " constructor!" << std::endl;
     throw;
   }
 
   // Make sure covariances are setup
   if (!fFullCovar) {
     fIsDiag = true;
     SetCovarFromDiagonal(fDataHist);
   }
 
   if (!covar) {
     covar = StatUtils::GetInvert(fFullCovar);
   }
 
   if (!fDecomp) {
     fDecomp = StatUtils::GetDecomp(fFullCovar);
   }
 
   // Setup fMCHist from data
   fMCHist = (TH2D*)fDataHist->Clone();
   fMCHist->SetNameTitle((fSettings.GetName() + "_MC").c_str(),
                         (fSettings.GetFullTitles()).c_str());
   fMCHist->Reset();
 
   // Setup fMCFine
   fMCFine = new TH2D("mcfine", "mcfine", fDataHist->GetNbinsX() * 6,
                      fMCHist->GetXaxis()->GetBinLowEdge(1),
                      fMCHist->GetXaxis()->GetBinLowEdge(fDataHist->GetNbinsX() + 1),
                      fDataHist->GetNbinsY() * 6,
                      fMCHist->GetYaxis()->GetBinLowEdge(1),
                      fMCHist->GetYaxis()->GetBinLowEdge(fDataHist->GetNbinsY() + 1));
 
   fMCFine->SetNameTitle((fSettings.GetName() + "_MC_FINE").c_str(),
                         (fSettings.GetFullTitles()).c_str());
   fMCFine->Reset();
 
   // Setup MC Stat
   fMCStat = (TH2D*)fMCHist->Clone();
   fMCStat->Reset();
 
   // Search drawopts for possible types to include by default
   std::string drawopts = FitPar::Config().GetParS("drawopts");
   if (drawopts.find("MODES") != std::string::npos) {
     fMCHist_Modes = new TrueModeStack( (fSettings.GetName() + "_MODES").c_str(),
                                        ("True Channels"), fMCHist);
     SetAutoProcessTH1(fMCHist_Modes);
   }
 
   // Setup bin masks using sample name
   if (fIsMask) {
 
     std::string curname  = fName;
     std::string origname = fSettings.GetS("originalname");
 
     // Check rename.mask
     std::string maskloc = FitPar::Config().GetParDIR(curname + ".mask");
 
     // Check origname.mask
     if (maskloc.empty()) maskloc = FitPar::Config().GetParDIR(origname + ".mask");
 
     // Check database
     if (maskloc.empty()) {
       maskloc = FitPar::GetDataBase() + "/masks/" + origname + ".mask";
     }
 
     // Setup Bin Mask
     SetBinMask(maskloc);
   }
 
   if (fScaleFactor < 0) {
     ERR(FTL) << "I found a negative fScaleFactor in " << __FILE__ << ":" << __LINE__ << std::endl;
     ERR(FTL) << "fScaleFactor = " << fScaleFactor << std::endl;
     ERR(FTL) << "EXITING" << std::endl;
     throw;
   }
 
   // Create and fill Weighted Histogram
   if (!fMCWeighted) {
 
     fMCWeighted = (TH2D*)fMCHist->Clone();
     fMCWeighted->SetNameTitle((fName + "_MCWGHTS").c_str(),
                               (fName + "_MCWGHTS" + fPlotTitles).c_str());
     fMCWeighted->GetYaxis()->SetTitle("Weighted Events");
 
   }
 
 
 }
 
 //********************************************************************
 void Measurement2D::SetFitOptions(std::string opt) {
 //********************************************************************
 
   // Do nothing if default given
   if (opt == "DEFAULT") return;
 
   // CHECK Conflicting Fit Options
   std::vector<std::string> fit_option_allow =
     GeneralUtils::ParseToStr(fAllowedTypes, "/");
 
   for (UInt_t i = 0; i < fit_option_allow.size(); i++) {
     std::vector<std::string> fit_option_section =
       GeneralUtils::ParseToStr(fit_option_allow.at(i), ",");
 
     bool found_option = false;
 
     for (UInt_t j = 0; j < fit_option_section.size(); j++) {
       std::string av_opt = fit_option_section.at(j);
 
       if (!found_option and opt.find(av_opt) != std::string::npos) {
         found_option = true;
 
       } else if (found_option and opt.find(av_opt) != std::string::npos) {
         ERR(FTL) << "ERROR: Conflicting fit options provided: "
                  << opt << std::endl
                  << "Conflicting group = " << fit_option_section.at(i) << std::endl
                  << "You should only supply one of these options in card file." << std::endl;
         throw;
       }
     }
   }
 
   // Check all options are allowed
   std::vector<std::string> fit_options_input =
     GeneralUtils::ParseToStr(opt, "/");
   for (UInt_t i = 0; i < fit_options_input.size(); i++) {
     if (fAllowedTypes.find(fit_options_input.at(i)) == std::string::npos) {
       ERR(FTL) << "ERROR: Fit Option '" << fit_options_input.at(i)
                << "' Provided is not allowed for this measurement."
                << std::endl;
       ERR(FTL) << "Fit Options should be provided as a '/' seperated list "
                "(e.g. FREE/DIAG/NORM)"
                << std::endl;
       ERR(FTL) << "Available options for " << fName << " are '" << fAllowedTypes
                << "'" << std::endl;
 
       throw;
     }
   }
 
   // Set TYPE
   fFitType = opt;
 
   // FIX,SHAPE,FREE
   if (opt.find("FIX") != std::string::npos) {
     fIsFree = fIsShape = false;
     fIsFix = true;
   } else if (opt.find("SHAPE") != std::string::npos) {
     fIsFree = fIsFix = false;
     fIsShape = true;
   } else if (opt.find("FREE") != std::string::npos) {
     fIsFix = fIsShape = false;
     fIsFree = true;
   }
 
   // DIAG,FULL (or default to full)
   if (opt.find("DIAG") != std::string::npos) {
     fIsDiag = true;
     fIsFull = false;
   } else if (opt.find("FULL") != std::string::npos) {
     fIsDiag = false;
     fIsFull = true;
   }
 
   // CHI2/LL (OTHERS?)
   if (opt.find("LOG") != std::string::npos) {
     fIsChi2 = false;
 
     ERR(FTL) << "No other LIKELIHOODS properly supported!" << std::endl;
     ERR(FTL) << "Try to use a chi2!" << std::endl;
     throw;
 
   } else {
     fIsChi2 = true;
   }
 
   // EXTRAS
   if (opt.find("RAW") != std::string::npos) fIsRawEvents = true;
   if (opt.find("DIF") != std::string::npos) fIsDifXSec = true;
   if (opt.find("ENU1D") != std::string::npos) fIsEnu1D = true;
   if (opt.find("NORM") != std::string::npos) fAddNormPen = true;
   if (opt.find("MASK") != std::string::npos) fIsMask = true;
 
   // Set TYPE
   fFitType = opt;
 
   // FIX,SHAPE,FREE
   if (opt.find("FIX") != std::string::npos) {
     fIsFree = fIsShape = false;
     fIsFix = true;
   } else if (opt.find("SHAPE") != std::string::npos) {
     fIsFree = fIsFix = false;
     fIsShape = true;
   } else if (opt.find("FREE") != std::string::npos) {
     fIsFix = fIsShape = false;
     fIsFree = true;
   }
 
   // DIAG,FULL (or default to full)
   if (opt.find("DIAG") != std::string::npos) {
     fIsDiag = true;
     fIsFull = false;
   } else if (opt.find("FULL") != std::string::npos) {
     fIsDiag = false;
     fIsFull = true;
   }
 
   // CHI2/LL (OTHERS?)
   if (opt.find("LOG") != std::string::npos)
     fIsChi2 = false;
   else
     fIsChi2 = true;
 
   // EXTRAS
   if (opt.find("RAW") != std::string::npos) fIsRawEvents = true;
   if (opt.find("DIF") != std::string::npos) fIsDifXSec = true;
   if (opt.find("ENU1D") != std::string::npos) fIsEnu = true;
   if (opt.find("NORM") != std::string::npos) fAddNormPen = true;
   if (opt.find("MASK") != std::string::npos) fIsMask = true;
 
   fIsProjFitX = (opt.find("FITPROJX") != std::string::npos);
   fIsProjFitY = (opt.find("FITPROJY") != std::string::npos);
 
   return;
 };
 
 
 /*
    Reconfigure LOOP
 */
 //********************************************************************
 void Measurement2D::ResetAll() {
 //********************************************************************
 
   fMCHist->Reset();
   fMCFine->Reset();
   fMCStat->Reset();
 
   return;
 };
 
 //********************************************************************
 void Measurement2D::FillHistograms() {
   //********************************************************************
 
   if (Signal) {
     fMCHist->Fill(fXVar, fYVar, Weight);
     fMCFine->Fill(fXVar, fYVar, Weight);
     fMCStat->Fill(fXVar, fYVar, 1.0);
 
     if (fMCHist_Modes) fMCHist_Modes->Fill(Mode, fXVar, fYVar, Weight);
   }
 
   return;
 };
 
 //********************************************************************
 void Measurement2D::ScaleEvents() {
 //********************************************************************
 
   // Fill MCWeighted;
   // for (int i = 0; i < fMCHist->GetNbinsX(); i++) {
   // fMCWeighted->SetBinContent(i + 1, fMCHist->GetBinContent(i + 1));
   // fMCWeighted->SetBinError(i + 1,   fMCHist->GetBinError(i + 1));
   // }
 
 
   // Setup Stat ratios for MC and MC Fine
   double* statratio     = new double[fMCHist->GetNbinsX()];
   for (int i = 0; i < fMCHist->GetNbinsX(); i++) {
     if (fMCHist->GetBinContent(i + 1) != 0) {
       statratio[i] = fMCHist->GetBinError(i + 1) / fMCHist->GetBinContent(i + 1);
     } else {
       statratio[i] = 0.0;
     }
   }
 
   double* statratiofine = new double[fMCFine->GetNbinsX()];
   for (int i = 0; i < fMCFine->GetNbinsX(); i++) {
     if (fMCFine->GetBinContent(i + 1) != 0) {
       statratiofine[i] = fMCFine->GetBinError(i + 1) / fMCFine->GetBinContent(i + 1);
     } else {
       statratiofine[i] = 0.0;
     }
   }
 
 
   // Scaling for raw event rates
   if (fIsRawEvents) {
     double datamcratio = fDataHist->Integral() / fMCHist->Integral();
 
     fMCHist->Scale(datamcratio);
     fMCFine->Scale(datamcratio);
 
     if (fMCHist_Modes) fMCHist_Modes->Scale(datamcratio);
 
     // Scaling for XSec as function of Enu
   } else if (fIsEnu1D) {
 
     PlotUtils::FluxUnfoldedScaling(fMCHist, GetFluxHistogram(),
                                    GetEventHistogram(), fScaleFactor);
 
     PlotUtils::FluxUnfoldedScaling(fMCFine, GetFluxHistogram(),
                                    GetEventHistogram(), fScaleFactor);
 
 
     // if (fMCHist_Modes) {
     // PlotUtils::FluxUnfoldedScaling(fMCHist_Modes, GetFluxHistogram(),
     // GetEventHistogram(), fScaleFactor,
     // fNEvents);
     // }
 
     // Any other differential scaling
   } else {
     fMCHist->Scale(fScaleFactor, "width");
     fMCFine->Scale(fScaleFactor, "width");
 
     // if (fMCHist_Modes) fMCHist_Modes->Scale(fScaleFactor, "width");
   }
 
 
   // Proper error scaling - ROOT Freaks out with xsec weights sometimes
   for (int i = 0; i < fMCStat->GetNbinsX(); i++) {
     fMCHist->SetBinError(i + 1, fMCHist->GetBinContent(i + 1) * statratio[i]);
   }
 
   for (int i = 0; i < fMCFine->GetNbinsX(); i++) {
     fMCFine->SetBinError(i + 1, fMCFine->GetBinContent(i + 1) * statratiofine[i]);
   }
 
 
   // Clean up
   delete statratio;
   delete statratiofine;
 
   return;
 };
 
 //********************************************************************
 void Measurement2D::ApplyNormScale(double norm) {
 //********************************************************************
 
   fCurrentNorm = norm;
 
   fMCHist->Scale(1.0 / norm);
   fMCFine->Scale(1.0 / norm);
 
   return;
 };
 
 
 
 /*
    Statistic Functions - Outsources to StatUtils
 */
 
 //********************************************************************
 int Measurement2D::GetNDOF() {
 //********************************************************************
 
-  
+
   // Just incase it has gone...
   if (!fDataHist) return -1;
 
   int nDOF = 0;
 
   // If datahist has no errors make sure we don't include those bins as they are
   // not data points
   for (int xBin = 0; xBin < fDataHist->GetNbinsX() + 1; ++xBin) {
     for (int yBin = 0; yBin < fDataHist->GetNbinsY() + 1; ++yBin) {
       if (fDataHist->GetBinError(xBin, yBin) != 0)
         ++nDOF;
     }
   }
-  
+
   // Account for possible bin masking
   int nMasked = 0;
   if (fMaskHist and fIsMask)
     if (fMaskHist->Integral() > 0)
       for (int xBin = 0; xBin < fMaskHist->GetNbinsX() + 1; ++xBin)
         for (int yBin = 0; yBin < fMaskHist->GetNbinsY() + 1; ++yBin)
           if (fMaskHist->GetBinContent(xBin, yBin) > 0.5) ++nMasked;
 
   // Take away those masked DOF
   if (fIsMask) {
     nDOF -= nMasked;
   }
-  
+
   return nDOF;
 }
 
 //********************************************************************
 double Measurement2D::GetLikelihood() {
 //********************************************************************
 
   // If this is for a ratio, there is no data histogram to compare to!
   if (fNoData || !fDataHist) return 0.;
 
   // Fix weird masking bug
   if (!fIsMask) {
     if (fMaskHist) {
       fMaskHist = NULL;
     }
   } else {
     if (fMaskHist) {
       PlotUtils::MaskBins(fMCHist, fMaskHist);
     }
   }
 
   //  if (fIsProjFitX or fIsProjFitY) return GetProjectedChi2();
 
   // Scale up the results to match each other (Not using width might be
   // inconsistent with Meas1D)
   double scaleF = fDataHist->Integral() / fMCHist->Integral();
   if (fIsShape) {
     fMCHist->Scale(scaleF);
     fMCFine->Scale(scaleF);
     //PlotUtils::ScaleNeutModeArray((TH1**)fMCHist_PDG, scaleF);
   }
 
   if (!fMapHist) {
     fMapHist = StatUtils::GenerateMap(fDataHist);
   }
 
   // Get the chi2 from either covar or diagonals
   double chi2 = 0.0;
 
   if (fIsChi2) {
     if (fIsDiag) {
       chi2 =
         StatUtils::GetChi2FromDiag(fDataHist, fMCHist, fMapHist, fMaskHist);
     } else {
       chi2 = StatUtils::GetChi2FromCov(fDataHist, fMCHist, covar, fMapHist,
                                        fMaskHist);
     }
   }
 
   // Add a normal penalty term
   if (fAddNormPen) {
     chi2 +=
       (1 - (fCurrentNorm)) * (1 - (fCurrentNorm)) / (fNormError * fNormError);
     LOG(REC) << "Norm penalty = "
              << (1 - (fCurrentNorm)) * (1 - (fCurrentNorm)) /
              (fNormError * fNormError)
              << std::endl;
   }
 
   // Adjust the shape back to where it was.
   if (fIsShape and !FitPar::Config().GetParB("saveshapescaling")) {
     fMCHist->Scale(1. / scaleF);
     fMCFine->Scale(1. / scaleF);
   }
 
   fLikelihood = chi2;
 
   return chi2;
 }
 
 
 /*
   Fake Data Functions
 */
 //********************************************************************
 void Measurement2D::SetFakeDataValues(std::string fakeOption) {
 //********************************************************************
 
   // Setup original/datatrue
   TH2D* tempdata = (TH2D*) fDataHist->Clone();
 
   if (!fIsFakeData) {
     fIsFakeData = true;
 
     // Make a copy of the original data histogram.
     if (!fDataOrig) fDataOrig = (TH2D*)fDataHist->Clone((fName + "_data_original").c_str());
 
   } else {
     ResetFakeData();
 
   }
 
   // Setup Inputs
   fFakeDataInput = fakeOption;
   LOG(SAM) << "Setting fake data from : " << fFakeDataInput << std::endl;
 
   // From MC
   if (fFakeDataInput.compare("MC") == 0) {
     fDataHist = (TH2D*)fMCHist->Clone((fName + "_MC").c_str());
 
     // Fake File
   } else {
     if (!fFakeDataFile) fFakeDataFile = new TFile(fFakeDataInput.c_str(), "READ");
     fDataHist = (TH2D*)fFakeDataFile->Get((fName + "_MC").c_str());
 
   }
 
   // Setup Data Hist
   fDataHist->SetNameTitle((fName + "_FAKE").c_str(),
                           (fName + fPlotTitles).c_str());
 
   // Replace Data True
   if (fDataTrue) delete fDataTrue;
   fDataTrue = (TH2D*)fDataHist->Clone();
   fDataTrue->SetNameTitle((fName + "_FAKE_TRUE").c_str(),
                           (fName + fPlotTitles).c_str());
 
 
   // Make a new covariance for fake data hist.
   int nbins = fDataHist->GetNbinsX() * fDataHist->GetNbinsY();
   double alpha_i = 0.0;
   double alpha_j = 0.0;
 
   for (int i = 0; i < nbins; i++) {
     for (int j = 0; j < nbins; j++) {
       if (tempdata->GetBinContent(i + 1) && tempdata->GetBinContent(j + 1)) {
         alpha_i = fDataHist->GetBinContent(i + 1) / tempdata->GetBinContent(i + 1);
         alpha_j = fDataHist->GetBinContent(j + 1) / tempdata->GetBinContent(j + 1);
       } else {
         alpha_i = 0.0;
         alpha_j = 0.0;
       }
 
       (*fFullCovar)(i, j) = alpha_i * alpha_j * (*fFullCovar)(i, j);
     }
   }
 
   // Setup Covariances
   if (covar) delete covar;
   covar   = StatUtils::GetInvert(fFullCovar);
 
   if (fDecomp) delete fDecomp;
   fDecomp = StatUtils::GetInvert(fFullCovar);
 
   delete tempdata;
 
   return;
 };
 
 //********************************************************************
 void Measurement2D::ResetFakeData() {
 //********************************************************************
 
   if (fIsFakeData) {
     if (fDataHist) delete fDataHist;
     fDataHist = (TH2D*)fDataTrue->Clone((fSettings.GetName() + "_FKDAT").c_str());
   }
 
 }
 
 //********************************************************************
 void Measurement2D::ResetData() {
 //********************************************************************
 
   if (fIsFakeData) {
     if (fDataHist) delete fDataHist;
     fDataHist = (TH2D*)fDataOrig->Clone((fSettings.GetName() + "_data").c_str());
   }
 
   fIsFakeData = false;
 }
 
 //********************************************************************
 void Measurement2D::ThrowCovariance() {
 //********************************************************************
 
   // Take a fDecomposition and use it to throw the current dataset.
   // Requires fDataTrue also be set incase used repeatedly.
 
   if (fDataHist) delete fDataHist;
   fDataHist = StatUtils::ThrowHistogram(fDataTrue, fFullCovar);
 
   return;
 };
 
 //********************************************************************
 void Measurement2D::ThrowDataToy() {
   //********************************************************************
   if (!fDataTrue) fDataTrue = (TH2D*) fDataHist->Clone();
   if (fMCHist) delete fMCHist;
   fMCHist = StatUtils::ThrowHistogram(fDataTrue, fFullCovar);
 }
 
 
 /*
    Access Functions
 */
 
 //********************************************************************
 TH2D* Measurement2D::GetMCHistogram() {
 //********************************************************************
 
   if (!fMCHist) return fMCHist;
 
   std::ostringstream chi2;
   chi2 << std::setprecision(5) << this->GetLikelihood();
 
   int linecolor = kRed;
   int linestyle = 1;
   int linewidth = 1;
 
   int fillcolor = 0;
   int fillstyle = 1001;
 
   if (fSettings.Has("linecolor")) linecolor = fSettings.GetI("linecolor");
   if (fSettings.Has("linestyle")) linestyle = fSettings.GetI("linestyle");
   if (fSettings.Has("linewidth")) linewidth = fSettings.GetI("linewidth");
 
   if (fSettings.Has("fillcolor")) fillcolor = fSettings.GetI("fillcolor");
   if (fSettings.Has("fillstyle")) fillstyle = fSettings.GetI("fillstyle");
 
   fMCHist->SetTitle(chi2.str().c_str());
 
   fMCHist->SetLineColor(linecolor);
   fMCHist->SetLineStyle(linestyle);
   fMCHist->SetLineWidth(linewidth);
 
   fMCHist->SetFillColor(fillcolor);
   fMCHist->SetFillStyle(fillstyle);
 
   return fMCHist;
 };
 
 //********************************************************************
 TH2D* Measurement2D::GetDataHistogram() {
 //********************************************************************
 
   if (!fDataHist) return fDataHist;
 
   int datacolor = kBlack;
   int datastyle = 1;
   int datawidth = 1;
 
   if (fSettings.Has("datacolor")) datacolor = fSettings.GetI("datacolor");
   if (fSettings.Has("datastyle")) datastyle = fSettings.GetI("datastyle");
   if (fSettings.Has("datawidth")) datawidth = fSettings.GetI("datawidth");
 
   fDataHist->SetLineColor(datacolor);
   fDataHist->SetLineWidth(datawidth);
   fDataHist->SetMarkerStyle(datastyle);
 
   return fDataHist;
 };
 
 
 /*
    Write Functions
 */
 
 // Save all the histograms at once
 //********************************************************************
 void Measurement2D::Write(std::string drawOpt) {
 //********************************************************************
 
   // Get Draw Options
   drawOpt = FitPar::Config().GetParS("drawopts");
 
   // Write Settigns
   if (drawOpt.find("SETTINGS") != std::string::npos) {
     fSettings.Set("#chi^{2}", fLikelihood);
     fSettings.Set("NDOF", this->GetNDOF() );
     fSettings.Set("#chi^{2}/NDOF", fLikelihood / this->GetNDOF() );
     fSettings.Write();
   }
 
   // Write Data/MC
   GetDataList().at(0)->Write();
   GetMCList().at(0)->Write();
 
   // Write Fine Histogram
   if (drawOpt.find("FINE") != std::string::npos)
     GetFineList().at(0)->Write();
 
   // Write Weighted Histogram
   if (drawOpt.find("WEIGHTS") != std::string::npos && fMCWeighted)
     fMCWeighted->Write();
 
 
   // Save Flux/Evt if no event manager
   if (!FitPar::Config().GetParB("EventManager")) {
 
     if (drawOpt.find("FLUX") != std::string::npos && GetFluxHistogram())
       GetFluxHistogram()->Write();
 
     if (drawOpt.find("EVT") != std::string::npos && GetEventHistogram())
       GetEventHistogram()->Write();
 
     if (drawOpt.find("XSEC") != std::string::npos && GetEventHistogram())
       GetEventHistogram()->Write();
 
   }
 
   // Write Mask
   if (fIsMask && (drawOpt.find("MASK") != std::string::npos)) {
     fMaskHist->Write();
   }
 
 
   // Write Covariances
   if (drawOpt.find("COV") != std::string::npos && fFullCovar) {
     PlotUtils::GetFullCovarPlot(fFullCovar, fSettings.GetName());
   }
 
   if (drawOpt.find("INVCOV") != std::string::npos && covar) {
     PlotUtils::GetInvCovarPlot(covar, fSettings.GetName());
   }
 
   if (drawOpt.find("DECOMP") != std::string::npos && fDecomp) {
     PlotUtils::GetDecompCovarPlot(fDecomp, fSettings.GetName());
   }
 
   // // Likelihood residual plots
   // if (drawOpt.find("RESIDUAL") != std::string::npos) {
   //   WriteResidualPlots();
   // }
 
 
   // // RATIO
   // if (drawOpt.find("CANVMC") != std::string::npos) {
   //   TCanvas* c1 = WriteMCCanvas(fDataHist, fMCHist);
   //   c1->Write();
   //   delete c1;
   // }
 
   // // PDG
   // if (drawOpt.find("CANVPDG") != std::string::npos && fMCHist_Modes) {
   //   TCanvas* c2 = WritePDGCanvas(fDataHist, fMCHist, fMCHist_Modes);
   //   c2->Write();
   //   delete c2;
   // }
 
   // Write Extra Histograms
   AutoWriteExtraTH1();
   WriteExtraHistograms();
 
   /// 2D VERSION
   // If null pointer return
   if (!fMCHist and !fDataHist) {
     LOG(SAM) << fName << "Incomplete histogram set!" << std::endl;
     return;
   }
 
-  //  FitPar::Config().out->cd();
+  //  Config::Get().out->cd();
 
   // Get Draw Options
   drawOpt = FitPar::Config().GetParS("drawopts");
   bool drawData = (drawOpt.find("DATA") != std::string::npos);
   bool drawNormal = (drawOpt.find("MC") != std::string::npos);
   bool drawEvents = (drawOpt.find("EVT") != std::string::npos);
   bool drawXSec = (drawOpt.find("XSEC") != std::string::npos);
   bool drawFine = (drawOpt.find("FINE") != std::string::npos);
   bool drawRatio = (drawOpt.find("RATIO") != std::string::npos);
   // bool drawModes = (drawOpt.find("MODES") != std::string::npos);
   bool drawShape = (drawOpt.find("SHAPE") != std::string::npos);
   bool residual = (drawOpt.find("RESIDUAL") != std::string::npos);
   bool drawMatrix = (drawOpt.find("MATRIX") != std::string::npos);
   bool drawFlux = (drawOpt.find("FLUX") != std::string::npos);
   bool drawMask = (drawOpt.find("MASK") != std::string::npos);
   bool drawMap = (drawOpt.find("MAP") != std::string::npos);
   bool drawProj = (drawOpt.find("PROJ") != std::string::npos);
   // bool drawCanvPDG = (drawOpt.find("CANVPDG") != std::string::npos);
   bool drawCov = (drawOpt.find("COV") != std::string::npos);
   bool drawSliceCanvYMC = (drawOpt.find("CANVYMC") != std::string::npos);
   bool drawWeighted = (drawOpt.find("WGHT") != std::string::npos);
 
   if (FitPar::Config().GetParB("EventManager")) {
     drawFlux = false;
     drawXSec = false;
     drawEvents = false;
   }
 
   if (fMaskHist) fMaskHist->Write();
 
   // Save standard plots
   if (drawData) this->GetDataList().at(0)->Write();
   if (drawNormal) this->GetMCList().at(0)->Write();
 
   if (drawCov) {
     TH2D(*fFullCovar).Write((fName + "_COV").c_str());
   }
 
   if (drawOpt.find("INVCOV") != std::string::npos) {
     TH2D(*covar).Write((fName + "_INVCOV").c_str());
   }
 
   // Generate a simple map
   if (!fMapHist) fMapHist = StatUtils::GenerateMap(fDataHist);
 
   // Convert to 1D Lists
   TH1D* data_1D = StatUtils::MapToTH1D(fDataHist, fMapHist);
   TH1D* mc_1D = StatUtils::MapToTH1D(fMCHist, fMapHist);
   TH1I* mask_1D = StatUtils::MapToMask(fMaskHist, fMapHist);
 
   data_1D->Write();
   mc_1D->Write();
 
   if (mask_1D) {
     mask_1D->Write();
 
     TMatrixDSym* calc_cov =
       StatUtils::ApplyInvertedMatrixMasking(covar, mask_1D);
     TH1D* calc_data = StatUtils::ApplyHistogramMasking(data_1D, mask_1D);
     TH1D* calc_mc = StatUtils::ApplyHistogramMasking(mc_1D, mask_1D);
 
     TH2D* bin_cov = new TH2D(*calc_cov);
 
     bin_cov->Write();
     calc_data->Write();
     calc_mc->Write();
 
     delete mask_1D;
     delete calc_cov;
     delete calc_data;
     delete calc_mc;
     delete bin_cov;
   }
 
   delete data_1D;
   delete mc_1D;
 
   // Save only mc and data if splines
   if (fEventType == 4 or fEventType == 3) {
     return;
   }
 
   // Draw Extra plots
   if (drawFine) this->GetFineList().at(0)->Write();
   if (drawFlux and GetFluxHistogram()) {
     GetFluxHistogram()->Write();
   }
   if (drawEvents and GetEventHistogram()) {
     GetEventHistogram()->Write();
   }
   if (fIsMask and drawMask) {
     fMaskHist->Write((fName + "_MSK").c_str());  //< save mask
   }
   if (drawMap) fMapHist->Write((fName + "_MAP").c_str());  //< save map
 
   // // Save neut stack
   // if (drawModes) {
   //   THStack combo_fMCHist_PDG = PlotUtils::GetNeutModeStack(
   //                                 (fName + "_MC_PDG").c_str(), (TH1**)fMCHist_PDG, 0);
   //   combo_fMCHist_PDG.Write();
   // }
 
   // Save Matrix plots
   if (drawMatrix and fFullCovar and covar and fDecomp) {
     TH2D cov = TH2D((*fFullCovar));
     cov.SetNameTitle((fName + "_cov").c_str(),
                      (fName + "_cov;Bins; Bins;").c_str());
     cov.Write();
 
     TH2D covinv = TH2D((*this->covar));
     covinv.SetNameTitle((fName + "_covinv").c_str(),
                         (fName + "_cov;Bins; Bins;").c_str());
     covinv.Write();
 
     TH2D covdec = TH2D((*fDecomp));
     covdec.SetNameTitle((fName + "_covdec").c_str(),
                         (fName + "_cov;Bins; Bins;").c_str());
     covdec.Write();
   }
 
   // Save ratio plots if required
   if (drawRatio) {
     // Needed for error bars
     for (int i = 0; i < fMCHist->GetNbinsX() * fMCHist->GetNbinsY(); i++)
       fMCHist->SetBinError(i + 1, 0.0);
 
     fDataHist->GetSumw2();
     fMCHist->GetSumw2();
 
     // Create Ratio Histograms
     TH2D* dataRatio = (TH2D*)fDataHist->Clone((fName + "_data_RATIO").c_str());
     TH2D* mcRatio = (TH2D*)fMCHist->Clone((fName + "_MC_RATIO").c_str());
 
     mcRatio->Divide(fMCHist);
     dataRatio->Divide(fMCHist);
 
     // Cancel bin errors on MC
     for (int i = 0; i < mcRatio->GetNbinsX() * mcRatio->GetNbinsY(); i++) {
       mcRatio->SetBinError(
         i + 1, fMCHist->GetBinError(i + 1) / fMCHist->GetBinContent(i + 1));
     }
 
     mcRatio->SetMinimum(0);
     mcRatio->SetMaximum(2);
     dataRatio->SetMinimum(0);
     dataRatio->SetMaximum(2);
 
     mcRatio->Write();
     dataRatio->Write();
 
     delete mcRatio;
     delete dataRatio;
   }
 
   // Save Shape Plots if required
   if (drawShape) {
     // Create Shape Histogram
     TH2D* mcShape = (TH2D*)fMCHist->Clone((fName + "_MC_SHAPE").c_str());
 
     double shapeScale = 1.0;
     if (fIsRawEvents) {
       shapeScale = fDataHist->Integral() / fMCHist->Integral();
     } else {
       shapeScale = fDataHist->Integral("width") / fMCHist->Integral("width");
     }
 
     mcShape->Scale(shapeScale);
 
     mcShape->SetLineWidth(3);
     mcShape->SetLineStyle(7);  // dashes
 
     mcShape->Write();
 
     // Save shape ratios
     if (drawRatio) {
       // Needed for error bars
       mcShape->GetSumw2();
 
       // Create shape ratio histograms
       TH2D* mcShapeRatio =
         (TH2D*)mcShape->Clone((fName + "_MC_SHAPE_RATIO").c_str());
       TH2D* dataShapeRatio =
         (TH2D*)fDataHist->Clone((fName + "_data_SHAPE_RATIO").c_str());
 
       // Divide the histograms
       mcShapeRatio->Divide(mcShape);
       dataShapeRatio->Divide(mcShape);
 
       // Colour the shape ratio plots
       mcShapeRatio->SetLineWidth(3);
       mcShapeRatio->SetLineStyle(7);  // dashes
 
       mcShapeRatio->Write();
       dataShapeRatio->Write();
 
       delete mcShapeRatio;
       delete dataShapeRatio;
     }
 
     delete mcShape;
   }
 
   // Save residual calculations of what contributed to the chi2 values.
   if (residual) {
   }
 
   if (fIsProjFitX or fIsProjFitY or drawProj) {
     // If not already made, make the projections
     if (!fMCHist_X) {
       PlotUtils::MatchEmptyBins(fDataHist, fMCHist);
 
       fMCHist_X = PlotUtils::GetProjectionX(fMCHist, fMaskHist);
       fMCHist_Y = PlotUtils::GetProjectionY(fMCHist, fMaskHist);
 
       fDataHist_X = PlotUtils::GetProjectionX(fDataHist, fMaskHist);
       fDataHist_Y = PlotUtils::GetProjectionY(fDataHist, fMaskHist);
 
       double chi2X = StatUtils::GetChi2FromDiag(fDataHist_X, fMCHist_X);
       double chi2Y = StatUtils::GetChi2FromDiag(fDataHist_Y, fMCHist_Y);
 
       fMCHist_X->SetTitle(Form("%f", chi2X));
       fMCHist_Y->SetTitle(Form("%f", chi2Y));
     }
 
     // Save the histograms
     fDataHist_X->Write();
     fMCHist_X->Write();
 
     fDataHist_Y->Write();
     fMCHist_Y->Write();
   }
 
   if (drawSliceCanvYMC or true) {
     TCanvas* c1 = new TCanvas((fName + "_MC_CANV_Y").c_str(),
                               (fName + "_MC_CANV_Y").c_str(), 800, 600);
 
     c1->Divide(int(sqrt(fDataHist->GetNbinsY() + 1)),
                int(sqrt(fDataHist->GetNbinsY() + 1)));
     TH2D* mcShape = (TH2D*)fMCHist->Clone((fName + "_MC_SHAPE").c_str());
     double shapeScale =
       fDataHist->Integral("width") / fMCHist->Integral("width");
     mcShape->Scale(shapeScale);
     mcShape->SetLineStyle(7);
 
     c1->cd(1);
     TLegend* leg = new TLegend(0.6, 0.6, 0.9, 0.9);
     leg->AddEntry(fDataHist, (fName + " Data").c_str(), "ep");
     leg->AddEntry(fMCHist, (fName + " MC").c_str(), "l");
     leg->AddEntry(mcShape, (fName + " Shape").c_str(), "l");
     leg->Draw("SAME");
 
     /*
     // Make Y slices
     for (int i = 0; i < fDataHist->GetNbinY(); i++){
 
       c1->cd(i+2);
       TH1D* fDataHist_SliceY = PlotUtils::GetSliceY(fDataHist, i);
       fDataHist_SliceY->Draw("E1");
 
       TH1D* fMCHist_SliceY = PlotUtils::GetSliceY(fMCHist, i);
       fMCHist_SliceY->Draw("SAME HIST C");
 
       TH1D* mcShape_SliceY = PlotUtils::GetSliceY(mcShape, i);
       mcShape_SliceY->Draw("SAME HIST C");
     }
     */
     c1->Write();
   }
 
   if (drawWeighted) {
     fMCWeighted->Write();
   }
 
   // Returning
   LOG(SAM) << "Written Histograms: " << fName << std::endl;
   return;
 
   // Returning
   LOG(SAM) << "Written Histograms: " << fName << std::endl;
   return;
 }
 
 
 
 /*
   Setup Functions
 */
 //********************************************************************
 void Measurement2D::SetupMeasurement(std::string inputfile, std::string type,
                                      FitWeight* rw, std::string fkdt) {
 //********************************************************************
 
   // Check if name contains Evt, indicating that it is a raw number of events
   // measurements and should thus be treated as once
   fIsRawEvents = false;
   if ((fName.find("Evt") != std::string::npos) && fIsRawEvents == false) {
     fIsRawEvents = true;
     LOG(SAM) << "Found event rate measurement but fIsRawEvents == false!"
              << std::endl;
     LOG(SAM) << "Overriding this and setting fIsRawEvents == true!"
              << std::endl;
   }
 
   fIsEnu = false;
   if ((fName.find("XSec") != std::string::npos) &&
       (fName.find("Enu") != std::string::npos)) {
     fIsEnu = true;
     LOG(SAM) << "::" << fName << "::" << std::endl;
     LOG(SAM) << "Found XSec Enu measurement, applying flux integrated scaling, "
              "not flux averaged!"
              << std::endl;
     if (FitPar::Config().GetParB("EventManager")) {
       ERR(FTL) << "Enu Measurements do not yet work with the Event Manager!"
                << std::endl;
       ERR(FTL) << "If you want decent flux unfolded results please run in "
                "series mode (-q EventManager=0)"
                << std::endl;
       sleep(2);
     }
   }
 
   if (fIsEnu && fIsRawEvents) {
     LOG(SAM) << "Found 1D Enu XSec distribution AND fIsRawEvents, is this "
              "really correct?!"
              << std::endl;
     LOG(SAM) << "Check experiment constructor for " << fName
              << " and correct this!" << std::endl;
     LOG(SAM) << "I live in " << __FILE__ << ":" << __LINE__ << std::endl;
     exit(-1);
   }
 
   // Reset everything to NULL
   fRW = rw;
 
   // Setting up 2D Inputs
   this->SetupInputs(inputfile);
 
   // Set Default Options
   SetFitOptions(fDefaultTypes);
 
   // Set Passed Options
   SetFitOptions(type);
 }
 
 //********************************************************************
 void Measurement2D::SetupDefaultHist() {
   //********************************************************************
 
   // Setup fMCHist
   fMCHist = (TH2D*)fDataHist->Clone();
   fMCHist->SetNameTitle((fName + "_MC").c_str(),
                         (fName + "_MC" + fPlotTitles).c_str());
 
   // Setup fMCFine
   Int_t nBinsX = fMCHist->GetNbinsX();
   Int_t nBinsY = fMCHist->GetNbinsY();
   fMCFine = new TH2D((fName + "_MC_FINE").c_str(),
                      (fName + "_MC_FINE" + fPlotTitles).c_str(), nBinsX * 3,
                      fMCHist->GetXaxis()->GetBinLowEdge(1),
                      fMCHist->GetXaxis()->GetBinLowEdge(nBinsX + 1), nBinsY * 3,
                      fMCHist->GetYaxis()->GetBinLowEdge(1),
                      fMCHist->GetYaxis()->GetBinLowEdge(nBinsY + 1));
 
   // Setup MC Stat
   fMCStat = (TH2D*)fMCHist->Clone();
   fMCStat->Reset();
 
 
   // Setup the NEUT Mode Array
   //PlotUtils::CreateNeutModeArray(fMCHist, (TH1**)fMCHist_PDG);
 
   // Setup bin masks using sample name
   if (fIsMask) {
     std::string maskloc = FitPar::Config().GetParDIR(fName + ".mask");
     if (maskloc.empty()) {
       maskloc = FitPar::GetDataBase() + "/masks/" + fName + ".mask";
     }
 
     SetBinMask(maskloc);
   }
 
   return;
 }
 
 
 //********************************************************************
 void Measurement2D::SetDataValues(std::string dataFile, std::string TH2Dname) {
   //********************************************************************
 
   if (dataFile.find(".root") == std::string::npos) {
     ERR(FTL) << "Error! " << dataFile << " is not a .root file" << std::endl;
     ERR(FTL) << "Currently only .root file reading is supported (MiniBooNE "
              "CC1pi+ 2D), but implementing .txt should be dirt easy"
              << std::endl;
     ERR(FTL) << "See me at " << __FILE__ << ":" << __LINE__ << std::endl;
     exit(-1);
 
   } else {
     TFile* inFile = new TFile(dataFile.c_str(), "READ");
     fDataHist = (TH2D*)(inFile->Get(TH2Dname.c_str())->Clone());
     fDataHist->SetDirectory(0);
 
     fDataHist->SetNameTitle((fName + "_data").c_str(),
                             (fName + "_MC" + fPlotTitles).c_str());
 
     delete inFile;
   }
 
   return;
 }
 
 //********************************************************************
 void Measurement2D::SetDataValues(std::string dataFile, double dataNorm,
                                   std::string errorFile, double errorNorm) {
   //********************************************************************
 
   // Make a counter to track the line number
   int yBin = 0;
 
   std::string line;
   std::ifstream data(dataFile.c_str(), ifstream::in);
 
   fDataHist = new TH2D((fName + "_data").c_str(), (fName + fPlotTitles).c_str(),
                        fNDataPointsX - 1, fXBins, fNDataPointsY - 1, fYBins);
 
   if (data.is_open())
     LOG(SAM) << "Reading data from: " << dataFile.c_str() << std::endl;
 
   while (std::getline(data >> std::ws, line, '\n')) {
     int xBin = 0;
 
     // Loop over entries and insert them into the histogram
     std::vector<double> entries = GeneralUtils::ParseToDbl(line, " ");
     for (std::vector<double>::iterator iter = entries.begin();
          iter != entries.end(); iter++) {
       fDataHist->SetBinContent(xBin + 1, yBin + 1, (*iter) * dataNorm);
       xBin++;
     }
     yBin++;
   }
 
   yBin = 0;
   std::ifstream error(errorFile.c_str(), ifstream::in);
 
   if (error.is_open())
     LOG(SAM) << "Reading errors from: " << errorFile.c_str() << std::endl;
 
   while (std::getline(error >> std::ws, line, '\n')) {
     int xBin = 0;
 
     // Loop over entries and insert them into the histogram
     std::vector<double> entries = GeneralUtils::ParseToDbl(line, " ");
     for (std::vector<double>::iterator iter = entries.begin();
          iter != entries.end(); iter++) {
       fDataHist->SetBinError(xBin + 1, yBin + 1, (*iter) * errorNorm);
       xBin++;
     }
     yBin++;
   }
 
   return;
 };
 
 //********************************************************************
 void Measurement2D::SetDataValuesFromText(std::string dataFile,
     double dataNorm) {
   //********************************************************************
 
   fDataHist = new TH2D((fName + "_data").c_str(), (fName + fPlotTitles).c_str(),
                        fNDataPointsX - 1, fXBins, fNDataPointsY - 1, fYBins);
 
   LOG(SAM) << "Reading data from: " << dataFile << std::endl;
   PlotUtils::Set2DHistFromText(dataFile, fDataHist, dataNorm, true);
 
   return;
 };
 
 //********************************************************************
 void Measurement2D::SetCovarMatrix(std::string covarFile) {
   //********************************************************************
 
   // Used to read a covariance matrix from a root file
   TFile* tempFile = new TFile(covarFile.c_str(), "READ");
 
   // Make plots that we want
   TH2D* covarPlot = new TH2D();
   //  TH2D* decmpPlot = new TH2D();
   TH2D* covarInvPlot = new TH2D();
   TH2D* fFullCovarPlot = new TH2D();
 
   // Get covariance options for fake data studies
   std::string covName = "";
   std::string covOption = FitPar::Config().GetParS("throw_covariance");
 
   // Which matrix to get?
   if (fIsShape || fIsFree) covName = "shp_";
   if (fIsDiag)
     covName += "diag";
   else
     covName += "full";
 
   covarPlot = (TH2D*)tempFile->Get((covName + "cov").c_str());
   covarInvPlot = (TH2D*)tempFile->Get((covName + "covinv").c_str());
 
   // Throw either the sub matrix or the full matrix
   if (!covOption.compare("SUB"))
     fFullCovarPlot = (TH2D*)tempFile->Get((covName + "cov").c_str());
   else if (!covOption.compare("FULL"))
     fFullCovarPlot = (TH2D*)tempFile->Get("fullcov");
   else
     ERR(WRN) << " Incorrect thrown_covariance option in parameters."
              << std::endl;
 
   // Bin masking?
   int dim = int(fDataHist->GetNbinsX());  //-this->masked->Integral());
   int covdim = int(fDataHist->GetNbinsX());
 
   // Make new covars
   this->covar = new TMatrixDSym(dim);
   fFullCovar = new TMatrixDSym(dim);
   fDecomp = new TMatrixDSym(dim);
 
   // Full covariance values
   int row, column = 0;
   row = 0;
   column = 0;
   for (Int_t i = 0; i < covdim; i++) {
     // masking can be dodgy
     // if (this->masked->GetBinContent(i+1) > 0) continue;
     for (Int_t j = 0; j < covdim; j++) {
       //   if (this->masked->GetBinContent(j+1) > 0) continue;
       (*this->covar)(row, column) = covarPlot->GetBinContent(i + 1, j + 1);
       (*fFullCovar)(row, column) = fFullCovarPlot->GetBinContent(i + 1, j + 1);
 
       column++;
     }
     column = 0;
     row++;
   }
 
   // Set bin errors on data
   if (!fIsDiag) {
     for (Int_t i = 0; i < fDataHist->GetNbinsX(); i++) {
       fDataHist->SetBinError(
         i + 1, sqrt((covarPlot->GetBinContent(i + 1, i + 1))) * 1E-38);
     }
   }
 
   TDecompSVD LU = TDecompSVD(*this->covar);
   this->covar = new TMatrixDSym(dim, LU.Invert().GetMatrixArray(), "");
 
   tempFile->Close();
   delete tempFile;
 
   return;
 };
 
 //********************************************************************
 void Measurement2D::SetCovarMatrixFromText(std::string covarFile, int dim) {
   //********************************************************************
 
   // Make a counter to track the line number
   int row = 0;
 
   std::string line;
   std::ifstream covar(covarFile.c_str(), ifstream::in);
 
   this->covar = new TMatrixDSym(dim);
   fFullCovar = new TMatrixDSym(dim);
   if (covar.is_open())
     LOG(SAM) << "Reading covariance matrix from file: " << covarFile
              << std::endl;
 
   while (std::getline(covar >> std::ws, line, '\n')) {
     int column = 0;
 
     // Loop over entries and insert them into matrix
     // Multiply by the errors to get the covariance, rather than the correlation
     // matrix
     std::vector<double> entries = GeneralUtils::ParseToDbl(line, " ");
     for (std::vector<double>::iterator iter = entries.begin();
          iter != entries.end(); iter++) {
       double val = (*iter) * fDataHist->GetBinError(row + 1) * 1E38 *
                    fDataHist->GetBinError(column + 1) * 1E38;
       (*this->covar)(row, column) = val;
       (*fFullCovar)(row, column) = val;
 
       column++;
     }
 
     row++;
   }
 
   // Robust matrix inversion method
   TDecompSVD LU = TDecompSVD(*this->covar);
   this->covar = new TMatrixDSym(dim, LU.Invert().GetMatrixArray(), "");
 
   return;
 };
 
 //********************************************************************
 void Measurement2D::SetCovarMatrixFromChol(std::string covarFile, int dim) {
   //********************************************************************
 
   // Make a counter to track the line number
   int row = 0;
 
   std::string line;
   std::ifstream covarread(covarFile.c_str(), ifstream::in);
 
   TMatrixD* newcov = new TMatrixD(dim, dim);
 
   if (covarread.is_open())
     LOG(SAM) << "Reading covariance matrix from file: " << covarFile
              << std::endl;
   while (std::getline(covarread >> std::ws, line, '\n')) {
     int column = 0;
 
     // Loop over entries and insert them into matrix
     // Multiply by the errors to get the covariance, rather than the correlation
     // matrix
     std::vector<double> entries = GeneralUtils::ParseToDbl(line, " ");
     for (std::vector<double>::iterator iter = entries.begin();
          iter != entries.end(); iter++) {
       (*newcov)(row, column) = *iter;
       column++;
     }
 
     row++;
   }
   covarread.close();
 
   // Form full covariance
   TMatrixD* trans = (TMatrixD*)(newcov)->Clone();
   trans->T();
   (*trans) *= (*newcov);
 
   fFullCovar = new TMatrixDSym(dim, trans->GetMatrixArray(), "");
 
   delete newcov;
   delete trans;
 
   // Robust matrix inversion method
   TDecompChol LU = TDecompChol(*this->fFullCovar);
   this->covar = new TMatrixDSym(dim, LU.Invert().GetMatrixArray(), "");
 
   return;
 };
 
 // //********************************************************************
 // void Measurement2D::SetMapValuesFromText(std::string dataFile) {
 // //********************************************************************
 
 //   fMapHist = new TH2I((fName + "_map").c_str(), (fName + fPlotTitles).c_str(),
 //                       fNDataPointsX - 1, fXBins, fNDataPointsY - 1, fYBins);
 
 //   LOG(SAM) << "Reading map from: " << dataFile << std::endl;
 //   PlotUtils::Set2DHistFromText(dataFile, fMapHist, 1.0);
 
 //   return;
 // };
 
 
diff --git a/src/FitBase/Measurement2D.h b/src/FitBase/Measurement2D.h
index a5a44dc..44b2e66 100644
--- a/src/FitBase/Measurement2D.h
+++ b/src/FitBase/Measurement2D.h
@@ -1,641 +1,641 @@
 // Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret
 
 /*******************************************************************************
 *    This file is part of NUISANCE.
 *
 *    NUISANCE is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    NUISANCE is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with NUISANCE.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
 
 #ifndef MEASUREMENT_2D_HXX_SEEN
 #define MEASUREMENT_2D_HXX_SEEN
 
 /*!
  *  \addtogroup FitBase
  *  @{
  */
 
 #include <math.h>
 #include <stdlib.h>
 #include <deque>
 #include <fstream>
 #include <iomanip>
 #include <iostream>
 #include <numeric>
 #include <sstream>
 #include <string>
 
 // ROOT includes
 #include <TArrayF.h>
 #include <TDecompSVD.h>
 #include <TGraph.h>
 #include <TGraphErrors.h>
 #include <TH1D.h>
 #include <TH2D.h>
 #include <TMatrixDSym.h>
 #include <TROOT.h>
 #include <TSystem.h>
 
 // External data fit includes
 #include "FitEvent.h"
-#include "FitParameters.h"
+
 #include "FitUtils.h"
 #include "MeasurementBase.h"
 #include "PlotUtils.h"
 #include "SignalDef.h"
 #include "StatUtils.h"
 #include "MeasurementVariableBox2D.h"
 
 //********************************************************************
 //! 2D Measurement base class. Histogram handling is done in this base layer.
 class Measurement2D : public MeasurementBase {
   //********************************************************************
 
 public:
   /*
     Constructor/Deconstuctor
   */
 
   //! Default Constructor
   Measurement2D();
 
   //! Default Destructor
   virtual ~Measurement2D();
 
   /*
     Setup Functions
   */
 
   /// \brief Setup all configs once initialised
   ///
   /// Should be called after all configs have been setup inside fSettings container.
   /// Handles the processing of inputs and setting up of types.
   /// Replaces the old 'SetupMeasurement' function.
   void FinaliseSampleSettings();
 
   /// \brief Creates the 2D data distribution given the binning provided.
   virtual void CreateDataHistogram(int dimx, double* binx, int dimy, double* biny);
 
 
   /// \brief Set Data Histogram from a list of contents in a text file
   ///
   /// Assumes the format: \n
   /// x_low_1  y_low_1  cont_11  err_11 \n
   /// x_low_1  y_low_2  cont_12  err_12 \n
   /// x_low_2  y_low_1  cont_21  err_21 \n
   /// x_low_2  y_low_2  cont_22  err_22 \n
   /// x_low_2  y_low_3  cont_23  err_23 \n
   /// x_low_3  y_low_2  cont_32  err_32 \n
   virtual void SetDataFromTextFile(std::string datfile);
 
 
   /// \brief Set Data Histogram from a TH2D in a file
   ///
   /// - datfile = Full path to data file
   /// - histname = Name of histogram
   ///
   /// If histname not given it assumes that datfile
   /// is in the format: \n
   /// 'file.root;histname'
   virtual void SetDataFromRootFile(std::string datfile, std::string histname="");
 
 
   /// \brief Set data values from a 2D array in text file
   ///
   /// \warning requires DATA HISTOGRAM TO BE SET FIRST
   ///
   /// Assumes form: \n
   /// cont_11 cont_12 ... cont_1N \n
   /// cont_21 cont_22 ... cont_2N \n
   /// ...     ...     ... ...     \n
   /// cont_N1 cont_N2 ... cont_NN \n
   virtual void SetDataValuesFromTextFile(std::string datfile, TH2D* hist = NULL);
 
 
   /// \brief Set data errors from a 2D array in text file
   ///
   /// \warning requires DATA HISTOGRAM TO BE SET FIRST
   ///
   /// Assumes form: \n
   /// errs_11 errs_12 ... errs_1N \n
   /// errs_21 errs_22 ... errs_2N \n
   /// ...     ...     ... ...     \n
   /// errs_N1 errs_N2 ... errs_NN \n
   virtual void SetDataErrorsFromTextFile(std::string datfile, TH2D* hist = NULL);
 
 
   /// \brief Set data bin errors to sqrt(entries)
   ///
   /// \warning REQUIRES DATA HISTOGRAM TO BE SET FIRST
   ///
   /// Sets the data errors as the sqrt of the bin contents
   /// Should be use for counting experiments
   virtual void SetPoissonErrors();
 
   /// \brief Make diagonal covariance from data
   ///
   /// \warning If no histogram passed, data must be setup first!
   /// Setup the covariance inputs by taking the data histogram
   /// errors and setting up a diagonal covariance matrix.
   ///
   /// If no data is supplied, fDataHist is used if already set.
   virtual void SetCovarFromDiagonal(TH2D* data = NULL);
 
   /// \brief Read the data covariance from a text file.
   ///
   /// Inputfile should have the format: \n
   /// covariance_11  covariance_12  covariance_13 ... \n
   /// covariance_21  covariance_22  covariance_23 ... \n
   /// ...            ...            ...           ... \n
   ///
   /// If no dimensions are given, it is assumed from the number
   /// entries in the first line of covfile.
   virtual void SetCovarFromTextFile(std::string covfile, int dim = -1);
 
   /// \brief Read the data covariance from a ROOT file.
   ///
   /// - covfile specifies the full path to the file
   /// - histname specifies the name of the covariance object. Both TMatrixDSym and TH2D are supported.
   ///
   /// If no histogram name is given the inhistfile value
   /// is automatically parsed with ; so that: \n
   /// mycovfile.root;myhistname \n
   /// will also work.
   virtual void SetCovarFromRootFile(std::string covfile, std::string histname="");
 
   /// \brief Read the inverted data covariance from a text file.
   ///
   /// Inputfile should have similar format to that shown
   /// in SetCovarFromTextFile.
   ///
   /// If no dimensions are given, it is assumed from the number
   /// entries in the first line of covfile.
   virtual void SetCovarInvertFromTextFile(std::string covfile, int dim = -1);
 
 
   /// \brief Read the inverted data covariance from a ROOT file.
   ///
   /// Inputfile should have similar format to that shown
   /// in SetCovarFromRootFile.
   ///
   /// If no histogram name is given the inhistfile value
   /// is automatically parsed with ; so that: \n
   /// mycovfile.root;myhistname \n
   /// will also work.
   virtual void SetCovarInvertFromRootFile(std::string covfile, std::string histname="");
 
   /// \brief Read the data correlations from a text file.
   ///
   /// \warning REQUIRES DATA HISTOGRAM TO BE SET FIRST
   ///
   /// Inputfile should have similar format to that shown
   /// in SetCovarFromTextFile.
   ///
   /// If no dimensions are given, it is assumed from the number
   /// entries in the first line of covfile.
   virtual void SetCorrelationFromTextFile(std::string covfile, int dim = -1);
 
   /// \brief Read the data correlations from a ROOT file.
   ///
   /// \warning REQUIRES DATA TO BE SET FIRST
   ///
   /// Inputfile should have similar format to that shown
   /// in SetCovarFromRootFile.
   ///
   /// If no histogram name is given the inhistfile value
   /// is automatically parsed with ; so that: \n
   /// mycovfile.root;myhistname \n
   /// will also work.
   virtual void SetCorrelationFromRootFile(std::string covfile, std::string histname="");
 
 
   /// \brief Read the cholesky decomposed covariance from a text file and turn it into a covariance
   ///
   /// Inputfile should have similar format to that shown
   /// in SetCovarFromTextFile.
   ///
   /// If no dimensions are given, it is assumed from the number
   /// entries in the first line of covfile.
   virtual void SetCholDecompFromTextFile(std::string covfile, int dim = -1);
 
 
   /// \brief Read the cholesky decomposed covariance from a ROOT file and turn it into a covariance
   ///
   /// Inputfile should have similar format to that shown
   /// in SetCovarFromRootFile.
   ///
   /// If no histogram name is given the inhistfile value
   /// is automatically parsed with ; so that: \n
   /// mycovfile.root;myhistname \n
   /// will also work.
   virtual void SetCholDecompFromRootFile(std::string covfile, std::string histname="");
 
 
   /// \brief Read the map values from a text file
   ///
   /// \warning Requires DATA hist to be set beforehand.
   /// Format should be a 2D array of mappings. 
   /// -1 indicates empty bins. \n
   /// e.g.: \n
   ///  1  2  3  4  5 \n
   /// -1  6  7  8  9 \n
   /// -1 -1 10 11 -1 \n
   virtual void SetMapValuesFromText(std::string dataFile);
 
 
   /// \brief Scale the data by some scale factor
   virtual void ScaleData(double scale);
 
 
   /// \brief Scale the data error bars by some scale factor
   virtual void ScaleDataErrors(double scale);
 
 
   /// \brief Scale the covariaince and its invert/decomp by some scale factor.
   virtual void ScaleCovar(double scale);
 
 
   /// \brief Setup a bin masking histogram and apply masking to data
   ///
   /// \warning REQUIRES DATA HISTOGRAM TO BE SET FIRST
   ///
   /// Reads in a list of bins in a text file to be masked. Format is: \n
   /// bin_index_x_1 bin_index_y_1 1 \n
   /// bin_index_x_2 bin_index_y_2 1 \n
   /// bin_index_x_3 bin_index_y_3 1 \n
   ///
   /// If 0 is given then a bin entry will NOT be masked. So for example: \n\n
   /// 1 1  1 \n
   /// 2 0 1 \n
   /// 3 4 0 \n
   /// 4 0 1 \n\n
   /// Will mask only the (1,1), (2,0), and (4,0) bins.
   ///
   /// Masking can be turned on by specifiying the MASK option when creating a sample.
   /// When this is passed NUISANCE will look in the following locations for the mask file:
   /// - FitPar::Config().GetParS(fName + ".mask")
   /// - "data/masks/" + fName + ".mask";
   virtual void SetBinMask(std::string maskfile);
 
   /// \brief Set the current fit options from a string.
   ///
   /// This is called twice for each sample, once to set the default
   /// and once to set the current setting (if anything other than default given)
   ///
   /// For this to work properly it requires the default and allowed types to be
   /// set correctly. These should be specified as a string listing options.
   ///
   /// To split up options so that NUISANCE can automatically detect ones that
   /// are conflicting. Any options seperated with the '/' symbol are non conflicting
   /// and can be given together, whereas any seperated with the ',' symbol cannot
   /// be specified by the end user at the same time.
   ///
   /// Default Type Examples:
   /// - DIAG/FIX = Default option will be a diagonal covariance, with FIXED norm.
   /// - MASK/SHAPE = Default option will be a masked hist, with SHAPE always on.
   ///
   /// Allowed Type examples:
   /// - 'FULL/DIAG/NORM/MASK' = Any of these options can be specified.
   /// - 'FULL,FREE,SHAPE/MASK/NORM' = User can give either FULL, FREE, or SHAPE as on option.
   /// MASK and NORM can also be included as options.
   virtual void SetFitOptions(std::string opt);
 
   /// \brief Final constructor setup
   /// \warning Should be called right at the end of the constructor.
   ///
   /// Contains a series of checks to ensure the data and inputs have been setup.
   /// Also creates the MC histograms needed for fitting.
   void FinaliseMeasurement();
 
 
 
   /*
     Reconfigure
   */
 
   /// \brief Create a Measurement1D box
   ///
   /// Creates a new 1D variable box containing just fXVar.
   ///
   /// This box is the bare minimum required by the JointFCN when
   /// running fast reconfigures during a routine.
   /// If for some reason a sample needs extra variables to be saved then
   /// it should override this function creating its own MeasurementVariableBox
   /// that contains the extra variables.
   virtual MeasurementVariableBox* CreateBox() {return new MeasurementVariableBox2D();};
 
   /// \brief Reset all MC histograms
   ///
   /// Resets all standard histograms and those registered to auto
   /// process to zero.
   ///
   /// If extra histograms are not included in auto processing, then they must be reset
   /// by overriding this function and doing it manually if required.
   virtual void ResetAll(void);
 
   /// \brief Fill MC Histograms from XVar, YVar
   ///
   /// Fill standard histograms using fXVar, fYVar, Weight read from the variable box.
   ///
   /// WARNING : Any extra MC histograms need to be filled by overriding this function,
   /// even if they have been set to auto process.
   virtual void FillHistograms(void);
 
   // \brief Convert event rates to final histogram
   ///
   /// Apply standard scaling procedure to standard mc histograms to convert from
   /// raw events to xsec prediction.
   ///
   /// If any distributions have been set to auto process
   /// that is done during this function call, and a differential xsec is assumed.
   /// If that is not the case this function must be overriden.
   virtual void ScaleEvents(void);
 
   /// \brief Scale MC by a factor=1/norm
   ///
   /// Apply a simple normalisation scaling if the option FREE or a norm_parameter
   /// has been specified in the NUISANCE routine.
   virtual void ApplyNormScale(double norm);
 
 
 
   /*
     Statistical Functions
   */
 
   /// \brief Get Number of degrees of freedom
   ///
   /// Returns the number bins inside the data histogram accounting for
   /// any bin masking applied.
   virtual int GetNDOF();
 
   /// \brief Return Data/MC Likelihood at current state
   ///
   /// Returns the likelihood of the data given the current MC prediction.
   /// Diferent likelihoods definitions are used depending on the FitOptions.
   virtual double GetLikelihood(void);
 
 
 
 
 
   /*
     Fake Data
   */
 
   /// \brief Set the fake data values from either a file, or MC
   ///
   /// - Setting from a file "path": \n
   /// When reading from a file the full path must be given to a standard
   /// nuisance output. The standard MC histogram should have a name that matches
   /// this sample for it to be read in.
   /// \n\n
   /// - Setting from "MC": \n
   /// If the MC option is given the current MC prediction is used as fake data.
   virtual void SetFakeDataValues(std::string fakeOption);
 
   /// \brief Reset fake data back to starting fake data
   ///
   /// Reset the fake data back to original fake data (Reset back to before
   /// ThrowCovariance was first called)
   virtual void ResetFakeData(void);
 
   /// \brief Reset fake data back to original data
   ///
   /// Reset the data histogram back to the true original dataset for this sample
   /// before any fake data was defined.
   virtual void ResetData(void);
 
   /// \brief Generate fake data by throwing the covariance.
   ///
   /// Can be used on fake MC data or just the original dataset.
   /// Call ResetFakeData or ResetData to return to values before the throw.
   virtual void ThrowCovariance(void);
 
   /// \brief Throw the data by its assigned errors and assign this to MC    
   ///           
   /// Used when creating data toys by assign the MC to this thrown data     
   /// so that the likelihood is calculated between data and thrown data     
   virtual void ThrowDataToy(void);
 
 
 
 
 
   /*
     Access Functions
   */
 
   /// \brief Returns nicely formatted MC Histogram
   ///
   /// Format options can also be given in the samplesettings:
   /// - linecolor
   /// - linestyle
   /// - linewidth
   /// - fillcolor
   /// - fillstyle
   ///
   /// So to have a sample line colored differently in the xml cardfile put: \n
   /// <sample name="MiniBooNE_CCQE_XSec_1DQ2_nu" input="NEUT:input.root"
   /// linecolor="2" linestyle="7"  linewidth="2" />
   virtual TH2D* GetMCHistogram(void);
 
   /// \brief Returns nicely formatted data Histogram
   ///
   /// Format options can also be given in the samplesettings:
   /// - datacolor
   /// - datastyle
   /// - datawidth
   ///
   /// So to have a sample data colored differently in the xml cardfile put: \n
   /// <sample name="MiniBooNE_CCQE_XSec_1DQ2_nu" input="NEUT:input.root"
   /// datacolor="2" datastyle="7"  datawidth="2" />
   virtual TH2D* GetDataHistogram(void);
 
   /// \brief Returns a list of all MC histograms.
   ///
   /// Override this if you have extra histograms that need to be
   /// accessed outside of the Measurement1D class.
   inline virtual std::vector<TH1*> GetMCList(void) {
     return std::vector<TH1*>(1, GetMCHistogram());
   }
 
   /// \brief Returns a list of all Data histograms.
   ///
   /// Override this if you have extra histograms that need to be
   /// accessed outside of the Measurement1D class.
   inline virtual std::vector<TH1*> GetDataList(void) {
     return std::vector<TH1*>(1, GetDataHistogram());
   }
 
   /// \brief Returns a list of all Mask histograms.
   ///
   /// Override this if you have extra histograms that need to be
   /// accessed outside of the Measurement1D class.
   inline virtual std::vector<TH1*> GetMaskList(void) {
     return std::vector<TH1*>(1, fMaskHist);
   };
 
   /// \brief Returns a list of all Fine histograms.
   ///
   /// Override this if you have extra histograms that need to be
   /// accessed outside of the Measurement1D class.
   inline virtual std::vector<TH1*> GetFineList(void) {
     return std::vector<TH1*>(1, fMCFine);
   };
 
 
   /*
     Write Functions
   */
   /// \brief Save the current state to the current TFile directory \n
   ///
   /// Data/MC are both saved by default.
   /// A range of other histograms can be saved by setting the
   /// config option 'drawopts'.
   ///
   /// Possible options: \n
   /// - FINE    = Write Fine Histogram \n
   /// - WEIGHTS = Write Weighted MC Histogram (before scaling) \n
   /// - FLUX    = Write Flux Histogram from MC Input \n
   /// - EVT     = Write Event Histogram from MC Input \n
   /// - XSEC    = Write XSec Histogram from MC Input \n
   /// - MASK    = Write Mask Histogram \n
   /// - COV     = Write Covariance Histogram \n
   /// - INVCOV  = Write Inverted Covariance Histogram \n
   /// - DECMOP  = Write Decomp. Covariance Histogram \n
   /// - RESIDUAL= Write Resudial Histograms \n
   /// - RATIO   = Write Data/MC Ratio Histograms \n
   /// - SHAPE   = Write MC Shape Histograms norm. to Data \n
   /// - CANVMC  = Build MC Canvas Showing Data, MC, Shape \n
   /// - MODES   = Write PDG Stack \n
   /// - CANVPDG = Build MC Canvas Showing Data, PDGStack \n
   ///
   /// So to save a range of these in parameters/config.xml set: \n
   /// <config drawopts='FINE/COV/SHAPE/RATIO' />
   virtual void Write(std::string drawOpt);
 
 
 
 
 
 
   //////// OLD FUNCTIONS ////////////
 
 
   //! Intial setup of common measurement variables. Parse input files, types,
   //! etc.
   virtual void SetupMeasurement(std::string input, std::string type,
             FitWeight* rw, std::string fkdt);
 
   //! Setup the default mc Hist given a data histogram
   virtual void SetupDefaultHist();
 
   //! Set the data values and errors from two files
   virtual void SetDataValues(std::string dataFile, double dataNorm,
 			     std::string errorFile, double errorNorm);
   virtual void SetDataValues(std::string dataFile, std::string TH2Dname);
 
   //! Set the data values only from a text file
   virtual void SetDataValuesFromText(std::string dataFile, double norm);
 
   //! Read a covariance matrix from a file (Default name "covar" in file)
   virtual void SetCovarMatrix(std::string covarFile);
 
   //! Set the covariance matrix from a text file
   virtual void SetCovarMatrixFromText(std::string covarFile, int dim);
 
   //! Set the covariance matrix from a text file containing the cholesky
   //! fDecomposition
   virtual void SetCovarMatrixFromChol(std::string covarFile, int dim);
 
 protected:
   // The data histograms
   TH2D* fDataHist;    //!< default data histogram (use in chi2 calculations)
   TH2D* fDataOrig;    //!< histogram to store original data before throws.
   TH2D* fDataTrue;    //!< histogram to store true dataset
   TH1D* fDataHist_X;  //!< Projections onto X of the fDataHist
   TH1D* fDataHist_Y;  //!< Projections onto Y of the fDataHist
 
   // The MC histograms
   TH2D* fMCHist;          //!< MC Histogram (used in chi2 calculations)
   TH2D* fMCFine;          //!< Finely binned MC Histogram
   TH2D* fMCHist_PDG[61];  //!< MC Histograms for each interaction mode
   TH1D* fMCHist_X;        //!< Projections onto X of the fMCHist
   TH1D* fMCHist_Y;        //!< Projections onto Y of the fMCHist
   TH2D* fMCWeighted;      //!< Raw Event Weights
   TH2D* fMCStat;
 
   TH2I* fMaskHist;  //!< mask histogram for the data
   TH2I* fMapHist;   //!< map histogram used to convert 2D to 1D distributions
 
   bool fIsFakeData;          //!< is current data actually fake
   std::string fakeDataFile;  //!< MC fake data input file
 
   std::string fPlotTitles;  //!< X and Y plot titles.
   std::string fFitType;
   std::string fDefaultTypes;  //!< Default Fit Options
   std::string fAllowedTypes;  //!< Any allowed Fit Options
 
   TMatrixDSym* covar;       //!< inverted covariance matrix
   TMatrixDSym* fFullCovar;  //!< covariance matrix
   TMatrixDSym* fDecomp;     //!< fDecomposed covariance matrix
   TMatrixDSym* fCorrel;     //!< correlation matrix
   double fCovDet;           //!< covariance deteriminant
   double fNormError;        //!< Normalisation on the error on the data
 
   double fLikelihood; //!< Likelihood value
 
   Double_t* fXBins;     //!< X Bin Edges
   Double_t* fYBins;     //!< Y Bin Edges
   Int_t fNDataPointsX;  //!< Number of X data points
   Int_t fNDataPointsY;  //!< NUmber of Y data points
 
   // Fit specific flags
   bool fIsShape;      //!< Flag: Perform shape-only fit
   bool fIsFree;       //!< Flag: Perform normalisation free fit
   bool fIsDiag;       //!< Flag: Only use diagonal bin errors in stats
   bool fIsMask;       //!< Flag: Apply bin masking
   bool fIsRawEvents;  //!< Flag: Only event rates in histograms
   bool fIsEnu;        //!< Needs Enu Unfolding
   bool fIsChi2SVD;    //!< Flag: Chi2 SVD Method (DO NOT USE)
   bool fAddNormPen;   //!< Flag: Add normalisation penalty to fi
   bool fIsProjFitX;  //!< Flag: Use 1D projections onto X and Y to calculate the
   //!Chi2 Method. If flagged X will be used to set the rate.
   bool fIsProjFitY;  //!< Flag: Use 1D projections onto X and Y to calculate the
   //!Chi2 Method. If flagged Y will be used to set the rate.
   bool fIsFix;       //!< Flag: Fixed Histogram Norm
   bool fIsFull;      //!< Flag; Use Full Covar
   bool fIsDifXSec;   //!< Flag: Differential XSec
   bool fIsEnu1D;     //!< Flag: Flux Unfolded XSec
   bool fIsChi2;      //!< Flag; Use Chi2 over LL
 
 
   TrueModeStack* fMCHist_Modes; ///< Optional True Mode Stack
 
   TMatrixDSym* fCovar;    ///< New FullCovar
   TMatrixDSym* fInvert;   ///< New covar
 
 
   // Fake Data
   std::string fFakeDataInput;  ///< Input fake data file path
   TFile* fFakeDataFile;        ///< Input fake data file
 
   // Arrays for data entries
   Double_t* fDataValues;  ///< REMOVE data bin contents
   Double_t* fDataErrors;  ///< REMOVE data bin errors
 
 };
 
 /*! @} */
 #endif
diff --git a/src/FitBase/MeasurementBase.h b/src/FitBase/MeasurementBase.h
index 33a0ef6..00dddc7 100644
--- a/src/FitBase/MeasurementBase.h
+++ b/src/FitBase/MeasurementBase.h
@@ -1,362 +1,362 @@
 // Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret
 
 /*******************************************************************************
 *    This file is part of NUISANCE.
 *
 *    NUISANCE is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    NUISANCE is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with NUISANCE.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
 
 #ifndef INPUTHANDLER_H_SEEN
 #define INPUTHANDLER_H_SEEN
 
 /*!
  *  \addtogroup FitBase
  *  @{
  */
 
 // C Includes
 #include <math.h>
 #include <stdlib.h>
 #include <time.h>
 #include <deque>
 #include <iomanip>
 #include <iostream>
 #include <list>
 #include <numeric>
 #include <sstream>
 #include <string>
 
 // ROOT includes
 #include <TArrayF.h>
 #include <TDecompChol.h>
 #include <TDecompSVD.h>
 #include <TGraph.h>
 #include <TGraphErrors.h>
 #include <TH1D.h>
 #include <TH2D.h>
 #include <TMatrixDSym.h>
 #include <TROOT.h>
 #include <TSystem.h>
 
 // External data fit includes
 #include "FitEvent.h"
-#include "FitParameters.h"
+
 #include "FitUtils.h"
 #include "GeneralUtils.h"
 #include "PlotUtils.h"
 #include "StatUtils.h"
 #include "InputFactory.h"
 #include "FitWeight.h"
 
 #include "TMultiDimFit.h"
 
 #ifdef __GENIE_ENABLED__
 #include "Conventions/Units.h"
 #endif
 
 #include "EventManager.h"
 #include "TObject.h"
 #include "InputHandler.h"
 #include "NuisConfig.h"
 #include "NuisKey.h"
 #include "SampleSettings.h"
 #include "StackBase.h"
 #include "StandardStacks.h"
 
 /// Enumerations to help with extra plot functions
 enum extraplotflags {
   kCMD_Reset = 0,
   kCMD_Fill,
   kCMD_Scale,
   kCMD_Norm,
   kCMD_Write,
   kCMD_Error,
   kCMD_extraplotflags
 };
 
 enum MeasurementSpeciesClass {
   kSingleSpeciesMeasurement = 0,
   kNumuWithWrongSignMeasurement,
   kNueWithWrongSignMeasurement,
   kFourSpeciesMeasurement,
 };
 
 /// InputHandler Class
 ///
 /// Inherits from Measurement base to handle whatever input is throwna t the
 /// fitter automatically.
 /// All functions here handle how files are read in, converted to custom formats
 /// and reconfigures are called.
 /// Used generally for the MC inputs.
 
 //! 2nd level experiment class that handles converting MC into a common format
 //! and calling reconfigure
 
 
 class MeasurementBase {
 public:
   /*
     Constructor/Destructors
   */
   //! Default Constructor. Set everything to NULL
   MeasurementBase();
 
   //! Default virtual destructor
   virtual ~MeasurementBase(void);
   virtual void InitialSetup(void) {};
 
   /*
     Reconfigure Functions
   */
   //! Function called if MC tuning dials haven't been changed and all we want to
   //! do is update the normalisation.
   virtual void Renormalise(void);
 
   //! Call reconfigure only looping over signal events to save time.
   virtual void ReconfigureFast(void);
 
   virtual void FillHistograms(double weight);
 
 
   //! Call reconfigure looping over all MC events including background
   virtual void Reconfigure(void);
 
   // virtual TH2D GetCovarMatrix(void) = 0;
   virtual double GetLikelihood(void) { return 0.0; };
   virtual int GetNDOF(void) { return 0; };
   virtual void ThrowCovariance(void) = 0;
   virtual void ThrowDataToy(void) = 0;
   virtual void SetFakeDataValues(std::string fkdt) = 0;
 
   //! Get the total integrated flux between this samples energy range
   virtual double TotalIntegratedFlux(std::string intOpt = "width",
                                      double low = -9999.9,
                                      double high = -9999.9);
 
   //! Get the predicted event rate for this sample
   virtual double PredictedEventRate(std::string intOpt = "width",
                                     double low = -9999.9,
                                     double high = -9999.9);
 
   virtual SampleSettings LoadSampleSettings(nuiskey samplekey);
   virtual SampleSettings LoadSampleSettings(std::string name, std::string input, std::string type);
 
   virtual void FinaliseSampleSettings();
   virtual void FinaliseMeasurement();
   virtual void ProcessExtraHistograms(int cmd, MeasurementVariableBox* vars,
                                       double weight = 1.0);
 
   virtual void FillExtraHistograms(MeasurementVariableBox* vars, double weight = 1.0);
   virtual void ScaleExtraHistograms(MeasurementVariableBox* vars);
   virtual void ResetExtraHistograms();
   virtual void NormExtraHistograms(MeasurementVariableBox* vars, double norm = 1.0);
   virtual void WriteExtraHistograms();
   virtual MeasurementVariableBox* CreateBox() {return new MeasurementVariableBox();};
 
   int GetPassed() {
     int signalSize = 0;
     return signalSize;
   }
 
   int GetTotal() { return fNEvents; }
 
   /*
     Reconfigure LOOP
   */
   // All these should be virtual
   ///! Reset Histograms (Handled at Measurement Stage)
   virtual void ResetAll(void) = 0;
 
   ///! Fill the event variables for this sample (Handled in each inherited
   /// sample)
   virtual void FillEventVariables(FitEvent* event) { (void)event; };
 
   ///! Check whether this event is signle (Handled in each inherited sample)
   virtual bool isSignal(FitEvent* event) {
     (void)event;
     return false;
   };
 
   ///! Fill the histogram for this event using fXVar and fYVar (Handled in each
   /// inherited sample)
   virtual void FillHistograms(void) {};
 
   ///! Convert event rates to whatever distributions you need.
   virtual void ConvertEventRates(void);
 
   ///! Call scale events after the plots have been filled at the end of
   /// reconfigure.
   virtual void ScaleEvents(void) {};
 
   ///! Apply the scale factor at the end of reconfigure.
   virtual void ApplyNormScale(double norm) { (void)norm; };
 
   ///! Save Histograms
   virtual void Write(std::string drawOpt = "") = 0;
 
   virtual MeasurementVariableBox* FillVariableBox(FitEvent* event);
 
   virtual MeasurementVariableBox* GetBox();
 
   void FillHistogramsFromBox(MeasurementVariableBox* var, double weight);
   /*
     Histogram Access Functions
   */
 
   ///! Virtual function to get data histogram
   virtual std::vector<TH1*> GetDataList(void) = 0;
 
   ///! Virtual function to get MC histogram
   virtual std::vector<TH1*> GetMCList(void) = 0;
   virtual std::vector<TH1*> GetFineList(void) = 0;
   virtual std::vector<TH1*> GetMaskList(void) = 0;
 
   ///! Return flux histograms in a vector
   virtual std::vector<TH1*> GetFluxList(void);
   virtual std::vector<TH1*> GetEventRateList(void);
   virtual std::vector<TH1*> GetXSecList(void);
 
   virtual TH1D* GetEventHistogram() { return fInput->GetEventHistogram(); };
   virtual TH1D* GetXSecHistogram() { return fInput->GetXSecHistogram(); };
   virtual TH1D* GetFluxHistogram() { return fInput->GetFluxHistogram(); };
 
   ///! Return input for this sample
   InputHandlerBase* GetInput(void);
 
   std::string GetName(void) { return fName; };
   double GetScaleFactor(void) { return fScaleFactor; };
 
   double GetXVar(void) { return fXVar; };
   double GetYVar(void) { return fYVar; };
   double GetZVar(void) { return fZVar; };
   double GetMode(void) { return this->Mode; };
   double GetEnu(void) { return this->Enu; };
 
   void SetupInputs(std::string inputfile);
   int GetInputID(void);
   std::string GetInputFileName() { return fInputFileName; };
   void SetSignal(bool sig);
   void SetSignal(FitEvent* evt);
   void SetWeight(double wght);
   void SetMode(int md);
   void SetNoData(bool isTrue = true) { fNoData = isTrue; };
 
   inline void SetXVar(double xvar) { fXVar = xvar; };
   inline void SetYVar(double yvar) { fYVar = yvar; };
   inline void SetZVar(double zvar) { fZVar = zvar; };
 
   virtual std::vector<MeasurementBase*> GetSubSamples() {
     return std::vector<MeasurementBase*>(1, this);
   }
 
 
   void SetAutoProcessTH1(TH1* hist,  int c1 = -1,
                          int c2 = -1, int c3 = -1,
                          int c4 = -1, int c5 = -1);
   void SetAutoProcess(TH1* hist,  int c1 = -1,
 		      int c2 = -1, int c3 = -1,
 		      int c4 = -1, int c5 = -1);
   void SetAutoProcess(TGraph* g,  int c1 = -1,
                       int c2 = -1, int c3 = -1,
                       int c4 = -1, int c5 = -1);
   void SetAutoProcess(TF1* f,  int c1 = -1,
                       int c2 = -1, int c3 = -1,
                       int c4 = -1, int c5 = -1);
   void SetAutoProcess(StackBase* hist, int c1 = -1,
 		      int c2 = -1, int c3 = -1,
 		      int c4 = -1, int c5 = -1);
   void SetAutoProcessTH1(StackBase* hist, int c1 = -1,
                          int c2 = -1, int c3 = -1,
                          int c4 = -1, int c5 = -1);
   void AutoFillExtraTH1();
   void AutoResetExtraTH1();
   void AutoScaleExtraTH1();
   void AutoNormExtraTH1(double norm);
   void AutoWriteExtraTH1();
 
 
   // functions that need to be added.
   // - Initial Check
   // - Check Target/Beam loop.
   // - Check flux shape if suggested one given.
   // - Return MeasurementList (returns )
 
 
 protected:
   // Minimum and maximum energies
   double Enu;     //!< Neutrino Energy
   double EnuMin;  //!< Minimum incoming particle energy of events to include
   double EnuMax;  //!< Maximum incoming particle energy of events to include
 
   BaseFitEvt* signal_event;
   FitEvent* cust_event;
 
   FitWeight* fRW;        //!< Pointer to the rw engine
   InputHandlerBase* fInput;  //!< Instance of the input handler
 
   std::string fName; //!< Name of the sample
   int fEventType;
 
   double fBeamDistance;  //!< Incoming Particle flight distance (for oscillation
   //! analysis)
   double fScaleFactor;   //!< fScaleFactor applied to events to convert from
   //! eventrate to final distribution
   double
   fCurrentNorm;  //!< current normalisation factor applied if fit is "FREE"
   bool fMCFilled;    //!< flag whether MC plots have been filled (For
   //! ApplyNormalisation)
   bool fNoData;      //!< flag whether data plots do not exist (for ratios)
   bool fIsNoWidth;    ///< Flag : Don't scale by bin width
 
   // TEMP OBJECTS TO HANDLE MERGE
   double fXVar, fYVar, fZVar, Mode, Weight;
   bool Signal;
   int ievt;
   int fNEvents;
   double Enu_rec, ThetaMu, CosThetaMu;
 
   InputUtils::InputType fInputType;
   std::string fInputFileName;
   TH1D* fFluxHist;
   TH1D* fEventHist;
 
   MeasurementSpeciesClass fMeasurementSpeciesType;
   SampleSettings fSettings;
 
   MeasurementVariableBox* fEventVariables;
 
   std::map<StackBase*, std::vector<int> > fExtraTH1s;
   int NSignal;
   // std::map<TH1*, bool[6] > fExtaStacks;
 
   bool fIsJoint;
 
 
 
   double fNPOT, fFluxIntegralOverride, fTargetVolume, fTargetMaterialDensity;
   double fEvtRateScaleFactor;
 
 };
 
 
 
 
 // Class TypeDefs
 typedef std::list<MeasurementBase*>::const_iterator MeasListConstIter;
 typedef std::list<MeasurementBase*>::iterator MeasListIter;
 typedef std::vector<MeasurementBase*>::const_iterator MeasVectConstIter;
 typedef std::vector<MeasurementBase*>::iterator MeasVectIter;
 
 /*! @} */
 #endif
diff --git a/src/FitBase/SampleSettings.cxx b/src/FitBase/SampleSettings.cxx
index f574209..b94bb56 100644
--- a/src/FitBase/SampleSettings.cxx
+++ b/src/FitBase/SampleSettings.cxx
@@ -1,231 +1,231 @@
 #include "SampleSettings.h"
 
 SampleSettings::SampleSettings() {
 };
 
 SampleSettings::SampleSettings(nuiskey key) {
 	fKeyValues = key;
-	if (!key.Has("type")) key.AddS("type", "DEFAULT");
+	if (!key.Has("type")) key.Set("type", "DEFAULT");
 }
 
 std::string SampleSettings::GetName() {
 	return GetS("name");
 }
 
 void SampleSettings::SetS(std::string name, std::string val) {
 	fKeyValues.SetS(name, val);
 };
 
 bool SampleSettings::Found(std::string name, std::string substr) {
 	std::string compstring = fKeyValues.GetS(name);
 	return compstring.find(substr) != std::string::npos;
 }
 
 
 void SampleSettings::SetXTitle(std::string name) {
 	SetDefault("xtitle", name);
 };
 
 void SampleSettings::SetYTitle(std::string name) {
 	SetDefault("ytitle", name);
 };
 
 
 void SampleSettings::SetZTitle(std::string name) {
 	SetDefault("ztitle", name);
 };
 
 void SampleSettings::SetNormError(double norm) {
 	SetDefault("norm_error", GeneralUtils::DblToStr(norm));
 };
 
 double SampleSettings::GetNormError() {
   return GetD("norm_error");
 };
 
 std::string SampleSettings::GetCovarInput() {
 	return GetS("covar");
 }
 
 void SampleSettings::SetAllowedTypes(std::string allowed, std::string defaulttype) {
 	SetDefault("default_types", allowed);
 	SetDefault("allowed_types", defaulttype);
 };
 
 void SampleSettings::SetEnuRangeFromFlux(TH1D* fluxhist) {
 	double enu_min = fluxhist->GetXaxis()->GetXmin();
 	double enu_max = fluxhist->GetXaxis()->GetXmax();
 	SetEnuRange(enu_min, enu_max);
 };
 
 void SampleSettings::SetEnuRange(double min, double max) {
 	SetDefault("enu_min", min);
 	SetDefault("enu_max", max);
 };
 
 void SampleSettings::Set(std::string name, double d) {
 	SetDefault(name, d);
 }
 
 void SampleSettings::Set(std::string name, int i) {
 	SetDefault(name, i);
 }
 
 void SampleSettings::Set(std::string name, std::string s) {
 	SetDefault(name, s);
 }
 
 
 
 void SampleSettings::DefineAllowedTargets(std::string targ) {
 	// fAllowedTargets = TargetUtils::ParseTargetsToIntVect(targ);
 };
 
 
 void SampleSettings::FoundFill(std::string name, std::string substr, bool& cont, bool def) {
 	std::string compstring = fKeyValues.GetS(name);
 	if (compstring.find(substr) != std::string::npos) {
 		cont = def;
 	} else {
 		cont = !def;
 	}
 };
 
 
 void SampleSettings::SetTitle(std::string val) {
 	SetDefault("title", val);
 };
 
 void SampleSettings::SetDataInput(std::string val) {
 	SetDefault("data", val);
 };
 
 std::string SampleSettings::GetMapInput() {
 	return GetS("map");
 }
 void SampleSettings::SetMapInput(std::string val) {
 	SetDefault("map", val);
 }
 
 void SampleSettings::SetErrorInput(std::string val) {
 	SetDefault("error", val);
 };
 
 
 
 void SampleSettings::SetCovarInput(std::string val) {
 	SetDefault("covar", val);
 };
 
 void SampleSettings::SetShapeCovarInput(std::string val) {
   SetDefault("shapecovar", val);
 };
 
 
 void SampleSettings::SetDefault(std::string name, std::string val) {
-	if (!fKeyValues.Has(name)) fKeyValues.AddS(name, val);
+	if (!fKeyValues.Has(name)) fKeyValues.Set(name, val);
 };
 
 void SampleSettings::SetDefault(std::string name, double val ) {
-	if (!fKeyValues.Has(name)) fKeyValues.AddD(name, val);
+	if (!fKeyValues.Has(name)) fKeyValues.Set(name, val);
 };
 
 void SampleSettings::SetHasExtraHistograms(bool opt) {
 	fHasExtraHistograms = opt;
 };
 
 void SampleSettings::DefineAllowedSpecies(std::string species) {
 	fAllowedTargets = BeamUtils::ParseSpeciesToIntVect(species);
 };
 
 std::string SampleSettings::Title() {
 	return GetS("title");
 }
 
 std::string SampleSettings::GetDataInput() {
 	return GetS("data");
 };
 
 
 std::string SampleSettings::GetErrorInput() {
 	return GetS("error");
 };
 
 std::string SampleSettings::PlotTitles() {
 	return ";" + GetS("xtitle") + ";" + GetS("ytitle");
 };
 
 std::string SampleSettings::GetFullTitles() {
 	return Title() + PlotTitles();
 }
 
 int SampleSettings::GetI(std::string name) {
 	return fKeyValues.GetI(name);
 }
 
 bool SampleSettings::GetB(std::string name){
 	return fKeyValues.GetB(name);
 }
 
 
 double SampleSettings::GetD(std::string name) {
 	return fKeyValues.GetD(name);
 }
 
 std::string SampleSettings::GetS(std::string name) {
 	return fKeyValues.GetS(name);
 }
 
 void SampleSettings::SetSuggestedFlux(std::string str) {
 	SetS("suggested_flux", str);
 }
 
 void SampleSettings::SetDescription(std::string str) {
 	SetS("description", str);
 }
 
 void SampleSettings::Write(std::string name) {
 
 	if (name.empty()) name = this->GetS("name") + "_settings";
 
 	// Make a new canvas
 	TCanvas* c1 = new TCanvas( name.c_str(), name.c_str(), 800, 600 );
 	c1->cd();
 
 	// Make new TPaveText
 	TPaveText pttitle = TPaveText(0.05, 0.85, 0.95, 0.95);
 	pttitle.AddText( name.c_str() );
 	pttitle.SetTextAlign(11);
 	pttitle.SetTextSize(15);
 	pttitle.Draw();
 
 
 	TPaveText pt = TPaveText(0.05, 0.05, 0.95, 0.80);
 	std::vector<std::string> keys = fKeyValues.GetAllKeys();
 	for (int i = 0; i < keys.size(); i++) {
 
 		std::string keyval = fKeyValues.GetS(keys[i]);
 		std::vector<std::string> lines = GeneralUtils::ParseToStr(keyval, "\n");
 
 		if (lines.size() == 1) {
 			pt.AddText( ("#bullet #bf{" + keys[i] + "} : " + fKeyValues.GetS(keys[i])).c_str() );
 		} else {
 			pt.AddText( ("#bullet #bf{" + keys[i] + "} : ").c_str() );
 			for (int j = 0; j < lines.size(); j++) {
 				pt.AddText(("   |-->  " + lines[j]).c_str() );
 			}
 		}
 	}
 
 	pt.SetTextAlign(11);
 	pt.SetTextSize(14);
 	pt.Draw("SAME");
 
 
 	c1->Write();
 	delete c1;
 }
 
 void SampleSettings::SetOnlyMC(bool state) {
 	SetDefault("onlymc", state);
 }
diff --git a/src/Utils/StackBase.cxx b/src/FitBase/StackBase.cxx
similarity index 100%
rename from src/Utils/StackBase.cxx
rename to src/FitBase/StackBase.cxx
diff --git a/src/Utils/StackBase.h b/src/FitBase/StackBase.h
similarity index 99%
rename from src/Utils/StackBase.h
rename to src/FitBase/StackBase.h
index 826edb1..398afa6 100644
--- a/src/Utils/StackBase.h
+++ b/src/FitBase/StackBase.h
@@ -1,126 +1,126 @@
 #ifndef STACK_BASE_H
 #define STACK_BASE_H
 
 #include "MeasurementVariableBox.h"
 #include "FitLogger.h"
 #include "GeneralUtils.h"
 #include "TH1.h"
 #include "TH1D.h"
 #include "TH2D.h"
 #include "THStack.h"
 #include "TH2.h"
 #include "TH3.h"
-#include "FitParameters.h"
+
 #include "PlotUtils.h"
 
 class StackBase {
 public:
 	StackBase() {};
 	~StackBase() {};
 
 	virtual void AddMode(std::string name, std::string title,
 	                     int linecolor = 1, int linewidth = 1, int fillstyle = 1001);
 	virtual void AddMode(int index, std::string name, std::string title,
 	                     int linecolor = 1, int linewidth = 1, int fillstyle = 1001);
 	
 	virtual bool IncludeInStack(TH1* hist);
 	virtual bool IncludeInStack(int index);
 	
 	virtual void SetupStack(TH1* hist);
 	virtual void Scale(double sf, std::string opt = "");
 	virtual void FluxUnfold(TH1D* flux, TH1D* events, double scalefactor);
 	virtual void Reset();
 	virtual void FillStack(int index, double x, double y = 1.0, double z = 1.0, double weight = 1.0);
 	virtual void Write();
 
 	virtual void Add(StackBase* hist, double scale);
 	virtual void Add(TH1* hist, double scale);
 	
 	virtual void AddNewHist(std::string name, TH1* hist);
 	virtual void AddToCategory(std::string name, TH1* hist);
 	virtual void AddToCategory(int index, TH1* hist);
 
 	virtual void Divide(TH1* hist);
 	virtual void Multiply(TH1* hist);
 	virtual TH1* GetHist(int entry);
 	virtual TH1* GetHist(std::string label);
 	virtual THStack GetStack();
 
 	std::string GetType(){return fType;};
 
 	std::string fName;
 	std::string fTitle;
 	std::string fXTitle;
 	std::string fYTitle;
 	std::string fZTitle;
 	std::string fType;
 
 	TH1* fTemplate;
 	int fNDim;
 
 	// Maps incase we want to be selective
 	std::vector< std::vector<int> >  fAllStyles;
 	std::vector<std::string> fAllTitles;
 	std::vector<std::string> fAllLabels;
 	std::vector<TH1*> fAllHists;
 };
 
 
 /*
 class NuSpeciesStack : public StackBase {
 public:
 	SetupStack(TH1* hist) {
 		AddMode("numu", "numu", kBlue, 2, 3004);
 		AddMode("numubar", "numubar", kRed, 2, 3004 );
 		AddMode("nue", "nue",   kGreen, 2, 3004 );
 		StackBase::SetupStack(hist);
 	};
 
 	void NuSpeciesStack::FillStack(int species, double x, double y = 1.0, double z = 1.0, double weight = 1.0) {
 		Stackbase::FillStack(ConvertSpeciesToIndex(species), x, y, z, weight);
 	}
 
 	int ConvertSpeciesToIndex(int species) {
 		switch (species) {
 		case 14: return 0;
 		case -14: return 1;
 		case 11: return 2;
 		default: return -1;
 		}
 	};
 };
 
 class TargetStack : public StackBase {
 public:
 	SetupStack(TH1* hist) {
 		AddMode("C", "C", kBlue, 2, 3004);
 		AddMode("H", "H", kRed, 2, 3004 );
 		AddMode("O", "O",   kGreen, 2, 3004 );
 		StackBase::SetupStack(hist);
 	};
 
 	void NuSpeciesStack::FillStack(int species, double x,
 	                               double y = 1.0, double z = 1.0,
 	                               double weight = 1.0) {
 		Stackbase::FillStack(ConvertTargetToIndex(species), x, y, z, weight);
 	}
 
 	int ConvertTargetToIndex(int target) {
 		switch (species) {
 		case 1000010010: return 0;
 		case 1000: return 1;
 		case 1000: return 2;
 		default: return -1;
 		}
 	};
 }
 
 */
 
 
 #endif
 
 
 
 
 
diff --git a/src/Utils/StandardStacks.cxx b/src/FitBase/StandardStacks.cxx
similarity index 100%
rename from src/Utils/StandardStacks.cxx
rename to src/FitBase/StandardStacks.cxx
diff --git a/src/Utils/StandardStacks.h b/src/FitBase/StandardStacks.h
similarity index 100%
rename from src/Utils/StandardStacks.h
rename to src/FitBase/StandardStacks.h
diff --git a/src/InputHandler/FitEvent.h b/src/InputHandler/FitEvent.h
index dc20304..07653b3 100644
--- a/src/InputHandler/FitEvent.h
+++ b/src/InputHandler/FitEvent.h
@@ -1,640 +1,640 @@
 // Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret
 
 /*******************************************************************************
 *    This file is part of NUISANCE.
 *
 *    NUISANCE is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    NUISANCE is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with NUISANCE.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
 #ifndef FITEVENT2_H_SEEN
 #define FITEVENT2_H_SEEN
 /*!
  *  \addtogroup InputHandler
  *  @{
  */
 
 #include <algorithm>
 #include <iterator>
 #include <vector>
 #include "FitParticle.h"
 #include "TLorentzVector.h"
 #include "TSpline.h"
-#include "FitParameters.h"
+
 #include "BaseFitEvt.h"
 #include "FitLogger.h"
 #include "TArrayD.h"
 #include "TTree.h"
 #include "TChain.h"
 
 #include "PhysConst.h"
 
 /// Common container for event particles
 class FitEvent : public BaseFitEvt {
 public:
 
   FitEvent();
   ~FitEvent() {};
 
   void FreeFitParticles();
   void ClearFitParticles();
   void ResetEvent(void);
   void ResetParticleList(void);
   void HardReset();
   void OrderStack();
   void SetBranchAddress(TChain* tn);
   void AddBranchesToTree(TTree* tn);
   void Print();
   void PrintChris();
   void DeallocateParticleStack();
   void AllocateParticleStack(int stacksize);
   void ExpandParticleStack(int stacksize);
   void AddGeneratorInfo(GeneratorInfoBase* gen);
 
 
   // ---- HELPER/ACCESS FUNCTIONS ---- //
   /// Return True Interaction ID
   inline int GetMode    (void) const { return fMode;    };
   /// Return Target Atomic Number
   inline int GetTargetA (void) const { return fTargetA; };
   /// Return Target Nuclear Charge
   inline int GetTargetZ (void) const { return fTargetZ; };
   /// Get Event Total Cross-section
   inline int GetTotCrs  (void) const { return fTotCrs;  };
 
   /// Is Event Charged Current?
   inline bool IsCC() const { return (abs(fMode) <= 30); };
   /// Is Event Neutral Current?
   inline bool IsNC() const { return (abs(fMode) > 30);  };
 
   /// Return Particle 4-momentum for given index in particle stack
   TLorentzVector GetParticleP4    (int index) const;
   /// Return Particle 3-momentum for given index in particle stack
   TVector3       GetParticleP3    (int index) const;
   /// Return Particle absolute momentum for given index in particle stack
   double         GetParticleMom   (int index) const;
   /// Return Particle absolute momentum-squared for given index in particle stack
   double         GetParticleMom2  (int index) const;
   /// Return Particle energy for given index in particle stack
   double         GetParticleE     (int index) const;
   /// Return Particle State for given index in particle stack
   int            GetParticleState (int index) const;
   /// Return Particle PDG for given index in particle stack
   int            GetParticlePDG   (int index) const;
 
 
   /// Allows the removal of KE up to total KE.
   inline void RemoveKE(int index, double KE){
 
     FitParticle *fp = GetParticle(index);
 
     double mass = fp->M();
     double oKE = fp->KE();
     double nE = mass + (oKE - KE);
     if(nE < mass){ // Can't take more KE than it has
       nE = mass;
     }
     double n3Mom = sqrt(nE*nE - mass*mass);
     TVector3 np3 = fp->P3().Unit()*n3Mom;
 
     fParticleMom[index][0] = np3[0];
     fParticleMom[index][1] = np3[1];
     fParticleMom[index][2] = np3[2];
     fParticleMom[index][3] = nE;
 
   }
 
   /// Allows the removal of KE up to total KE.
   inline void GiveKE(int index, double KE){
     RemoveKE(index,-KE);
   }
   /// Return Particle for given index in particle stack
   FitParticle* GetParticle(int const index);
   /// Get Total Number of Particles in stack
   inline uint  NParticles (void) const { return fNParticles; };
 
   /// Check if event contains a particle given a pdg and state.
   /// If no state is passed all states are considered.
   bool HasParticle (int const pdg = 0, int const state = -1) const ;
 
   template <size_t N>
   inline bool HasParticle(int const (&pdgs)[N], int const state = -1) const {
     for (size_t i = 0; i < N; i++) {
       if (HasParticle( pdgs[i], state )) {
         return false;
       }
     }
     return false;
   }
 
   /// Get total number of particles given a pdg and state.
   /// If no state is passed all states are considered.
   int  NumParticle (int const pdg = 0, int const state = -1) const;
 
   template <size_t N>
   inline int NumParticle(int const (&pdgs)[N], int const state = -1) const {
     int ncount = 0;
     for (size_t i = 0; i < N; i++) {
       ncount += NumParticle( pdgs[i], state );
     }
     return ncount;
   }
 
   /// Return a vector of particle indices that can be used with 'GetParticle'
   /// functions given a particle pdg and state.
   /// If no state is passed all states are considered.
   std::vector<int> GetAllParticleIndices (int const pdg = -1, int const state = -1) const;
 
   template <size_t N>
   inline std::vector<int> GetAllParticleIndices(int const (&pdgs)[N], const int state = -1) const {
     std::vector<int> plist;
     for (size_t i = 0; i < N; i++) {
       std::vector<int> plisttemp = GetAllParticleIndices(pdgs[i], state);
       plist.insert( plist.end(), plisttemp.begin(), plisttemp.end() );
     }
     return plist;
   }
 
   /// Return a vector of FitParticles given a particle pdg and state.
   /// This is memory intensive and slow than GetAllParticleIndices,
   /// but is slightly easier to use.
   std::vector<FitParticle*> GetAllParticle (int const pdg = -1, int const state = -1);
 
   template <size_t N>
   inline std::vector<FitParticle*> GetAllParticle(int const (&pdgs)[N], int const state = -1) {
     std::vector<FitParticle*> plist;
     for (size_t i = 0; i < N; i++) {
       std::vector<FitParticle*> plisttemp = GetAllParticle(pdgs[i], state);
       plist.insert( plist.end(), plisttemp.begin(), plisttemp.end() );
     }
     return plist;
   }
 
   inline std::vector<int> GetAllNuElectronIndices (void) { return GetAllParticleIndices(12);   };
   inline std::vector<int> GetAllNuMuonIndices     (void) { return GetAllParticleIndices(14);   };
   inline std::vector<int> GetAllNuTauIndices      (void) { return GetAllParticleIndices(16);   };
   inline std::vector<int> GetAllElectronIndices   (void) { return GetAllParticleIndices(11);   };
   inline std::vector<int> GetAllMuonIndices       (void) { return GetAllParticleIndices(13);   };
   inline std::vector<int> GetAllTauIndices        (void) { return GetAllParticleIndices(15);   };
   inline std::vector<int> GetAllProtonIndices     (void) { return GetAllParticleIndices(2212); };
   inline std::vector<int> GetAllNeutronIndices    (void) { return GetAllParticleIndices(2112); };
   inline std::vector<int> GetAllPiZeroIndices     (void) { return GetAllParticleIndices(111);  };
   inline std::vector<int> GetAllPiPlusIndices     (void) { return GetAllParticleIndices(211);  };
   inline std::vector<int> GetAllPiMinusIndices    (void) { return GetAllParticleIndices(-211); };
   inline std::vector<int> GetAllPhotonIndices     (void) { return GetAllParticleIndices(22);   };
 
   inline std::vector<FitParticle*> GetAllNuElectron (void) { return GetAllParticle(12);   };
   inline std::vector<FitParticle*> GetAllNuMuon     (void) { return GetAllParticle(14);   };
   inline std::vector<FitParticle*> GetAllNuTau      (void) { return GetAllParticle(16);   };
   inline std::vector<FitParticle*> GetAllElectron   (void) { return GetAllParticle(11);   };
   inline std::vector<FitParticle*> GetAllMuon       (void) { return GetAllParticle(13);   };
   inline std::vector<FitParticle*> GetAllTau        (void) { return GetAllParticle(15);   };
   inline std::vector<FitParticle*> GetAllProton     (void) { return GetAllParticle(2212); };
   inline std::vector<FitParticle*> GetAllNeutron    (void) { return GetAllParticle(2112); };
   inline std::vector<FitParticle*> GetAllPiZero     (void) { return GetAllParticle(111);  };
   inline std::vector<FitParticle*> GetAllPiPlus     (void) { return GetAllParticle(211);  };
   inline std::vector<FitParticle*> GetAllPiMinus    (void) { return GetAllParticle(-211); };
   inline std::vector<FitParticle*> GetAllPhoton     (void) { return GetAllParticle(22);   };
 
   // --- Highest Momentum Search Functions --- //
   /// Returns the Index of the highest momentum particle given a pdg and state.
   /// If no state is given all states are considered, but that will just return the
   /// momentum of the beam in most cases so is not advised.
   int  GetHMParticleIndex (int const pdg = 0, int const state = -1) const;
 
   template <size_t N>
   inline int GetHMParticleIndex (int const (&pdgs)[N], int const state = -1) const {
 
     double mom = -999.9;
     int rtnindex = -1;
 
     for (size_t i = 0; i < N; ++i) {
       // Use ParticleMom as doesn't require Particle Mem alloc
       int pindex = GetHMParticleIndex(pdgs[i], state);
       if (pindex != -1){
 	double momnew = GetParticleMom2(pindex);
 	if (momnew > mom) {
 	  rtnindex = pindex;
 	  mom = momnew;
 	}
       }
     }
     return rtnindex;
   };
 
   /// Returns the highest momentum particle given a pdg and state.
   /// If no state is given all states are considered, but that will just return the
   /// momentum of the beam in most cases so is not advised.
   inline FitParticle* GetHMParticle(int const pdg = 0, int const state = -1) {
     return GetParticle( GetHMParticleIndex(pdg, state) );
   }
 
   template <size_t N>
   inline FitParticle* GetHMParticle(int const (&pdgs)[N], int const state) {
     return GetParticle(GetHMParticleIndex(pdgs, state));
   };
 
 
   // ---- Initial State Helpers --- //
   /// Checks the event has a particle of a given pdg in the initial state.
   inline bool HasISParticle(int const pdg) const {
     return HasParticle(pdg, kInitialState);
   };
   template <size_t N>
   inline bool HasISParticle(int const (&pdgs)[N]) const {
     return HasParticle(pdgs, kInitialState);
   };
 
   /// Returns the number of particles with a given pdg in the initial state.
   inline int NumISParticle(int const pdg = 0) const {
     return NumParticle(pdg, kInitialState);
   };
   template <size_t N>
   inline int NumISParticle(int const (&pdgs)[N]) const {
     return NumParticle(pdgs, kInitialState);
   };
 
   /// Returns a list of indices for all particles with a given pdg
   /// in the initial state. These can be used with the 'GetParticle' functions.
   inline std::vector<int> GetAllISParticleIndices(int const pdg = -1) const {
     return GetAllParticleIndices(pdg, kInitialState);
   };
   template <size_t N>
   inline std::vector<int> GetAllISParticleIndices(int const (&pdgs)[N]) const {
     return GetAllParticleIndices(pdgs, kInitialState);
   };
 
   /// Returns a list of particles with a given pdg in the initial state.
   /// This function is more memory intensive and slower than the Indices function.
   inline std::vector<FitParticle*> GetAllISParticle(int const pdg = -1) {
     return GetAllParticle(pdg, kInitialState);
   };
   template <size_t N>
   inline std::vector<FitParticle*> GetAllISParticle(int const (&pdgs)[N]) {
     return GetAllParticle(pdgs, kInitialState);
   };
 
   /// Returns the highest momentum particle with a given pdg in the initial state.
   inline FitParticle* GetHMISParticle(int const pdg) {
     return GetHMParticle(pdg, kInitialState);
   };
   template <size_t N>
   inline FitParticle* GetHMISParticle(int const (&pdgs)[N]) {
     return GetHMParticle(pdgs, kInitialState);
   };
 
   /// Returns the highest momentum particle index with a given pdg in the initial state.
   inline int GetHMISParticleIndex(int const pdg) const {
     return GetHMParticleIndex(pdg, kInitialState);
   };
   template <size_t N>
   inline int GetHMISParticleIndex(int const (&pdgs)[N]) const {
     return GetHMParticleIndex(pdgs, kInitialState);
   };
 
   inline bool HasISNuElectron   (void) const { return HasISParticle(12);   };
   inline bool HasISNuMuon       (void) const { return HasISParticle(14);   };
   inline bool HasISNuTau        (void) const { return HasISParticle(16);   };
   inline bool HasISElectron     (void) const { return HasISParticle(11);   };
   inline bool HasISMuon         (void) const { return HasISParticle(13);   };
   inline bool HasISTau          (void) const { return HasISParticle(15);   };
   inline bool HasISProton       (void) const { return HasISParticle(2212); };
   inline bool HasISNeutron      (void) const { return HasISParticle(2112); };
   inline bool HasISPiZero       (void) const { return HasISParticle(111);  };
   inline bool HasISPiPlus       (void) const { return HasISParticle(211);  };
   inline bool HasISPiMinus      (void) const { return HasISParticle(-211); };
   inline bool HasISPhoton       (void) const { return HasISParticle(22);   };
   inline bool HasISLeptons      (void) const { return HasISParticle(PhysConst::pdg_leptons);       };
   inline bool HasISPions        (void) const { return HasISParticle(PhysConst::pdg_pions);         };
   inline bool HasISChargePions  (void) const { return HasISParticle(PhysConst::pdg_charged_pions); };
 
   inline int NumISNuElectron   (void) const { return NumISParticle(12);   };
   inline int NumISNuMuon       (void) const { return NumISParticle(14);   };
   inline int NumISNuTau        (void) const { return NumISParticle(16);   };
   inline int NumISElectron     (void) const { return NumISParticle(11);   };
   inline int NumISMuon         (void) const { return NumISParticle(13);   };
   inline int NumISTau          (void) const { return NumISParticle(15);   };
   inline int NumISProton       (void) const { return NumISParticle(2212); };
   inline int NumISNeutron      (void) const { return NumISParticle(2112); };
   inline int NumISPiZero       (void) const { return NumISParticle(111);  };
   inline int NumISPiPlus       (void) const { return NumISParticle(211);  };
   inline int NumISPiMinus      (void) const { return NumISParticle(-211); };
   inline int NumISPhoton       (void) const { return NumISParticle(22);   };
   inline int NumISLeptons      (void) const { return NumISParticle(PhysConst::pdg_leptons);       };
   inline int NumISPions        (void) const { return NumISParticle(PhysConst::pdg_pions);         };
   inline int NumISChargePions  (void) const { return NumISParticle(PhysConst::pdg_charged_pions); };
 
   inline std::vector<int> GetAllISNuElectronIndices (void) const { return GetAllISParticleIndices(12);   };
   inline std::vector<int> GetAllISNuMuonIndices     (void) const { return GetAllISParticleIndices(14);   };
   inline std::vector<int> GetAllISNuTauIndices      (void) const { return GetAllISParticleIndices(16);   };
   inline std::vector<int> GetAllISElectronIndices   (void) const { return GetAllISParticleIndices(11);   };
   inline std::vector<int> GetAllISMuonIndices       (void) const { return GetAllISParticleIndices(13);   };
   inline std::vector<int> GetAllISTauIndices        (void) const { return GetAllISParticleIndices(15);   };
   inline std::vector<int> GetAllISProtonIndices     (void) const { return GetAllISParticleIndices(2212); };
   inline std::vector<int> GetAllISNeutronIndices    (void) const { return GetAllISParticleIndices(2112); };
   inline std::vector<int> GetAllISPiZeroIndices     (void) const { return GetAllISParticleIndices(111);  };
   inline std::vector<int> GetAllISPiPlusIndices     (void) const { return GetAllISParticleIndices(211);  };
   inline std::vector<int> GetAllISPiMinusIndices    (void) const { return GetAllISParticleIndices(-211); };
   inline std::vector<int> GetAllISPhotonIndices     (void) const { return GetAllISParticleIndices(22);   };
   inline std::vector<int> GetAllISLeptonsIndices    (void) const { return GetAllISParticleIndices(PhysConst::pdg_leptons);       };
   inline std::vector<int> GetAllISPionsIndices      (void) const { return GetAllISParticleIndices(PhysConst::pdg_pions);         };
   inline std::vector<int> GetAllISChargePionsIndices(void) const { return GetAllISParticleIndices(PhysConst::pdg_charged_pions); };
 
   inline std::vector<FitParticle*> GetAllISNuElectron (void) { return GetAllISParticle(12);   };
   inline std::vector<FitParticle*> GetAllISNuMuon     (void) { return GetAllISParticle(14);   };
   inline std::vector<FitParticle*> GetAllISNuTau      (void) { return GetAllISParticle(16);   };
   inline std::vector<FitParticle*> GetAllISElectron   (void) { return GetAllISParticle(11);   };
   inline std::vector<FitParticle*> GetAllISMuon       (void) { return GetAllISParticle(13);   };
   inline std::vector<FitParticle*> GetAllISTau        (void) { return GetAllISParticle(15);   };
   inline std::vector<FitParticle*> GetAllISProton     (void) { return GetAllISParticle(2212); };
   inline std::vector<FitParticle*> GetAllISNeutron    (void) { return GetAllISParticle(2112); };
   inline std::vector<FitParticle*> GetAllISPiZero     (void) { return GetAllISParticle(111);  };
   inline std::vector<FitParticle*> GetAllISPiPlus     (void) { return GetAllISParticle(211);  };
   inline std::vector<FitParticle*> GetAllISPiMinus    (void) { return GetAllISParticle(-211); };
   inline std::vector<FitParticle*> GetAllISPhoton     (void) { return GetAllISParticle(22);   };
   inline std::vector<FitParticle*> GetAllISLeptons    (void) { return GetAllISParticle(PhysConst::pdg_leptons);       };
   inline std::vector<FitParticle*> GetAllISPions      (void) { return GetAllISParticle(PhysConst::pdg_pions);         };
   inline std::vector<FitParticle*> GetAllISChargePions(void) { return GetAllISParticle(PhysConst::pdg_charged_pions); };
 
   inline FitParticle* GetHMISNuElectron (void) { return GetHMISParticle(12);   };
   inline FitParticle* GetHMISNuMuon     (void) { return GetHMISParticle(14);   };
   inline FitParticle* GetHMISNuTau      (void) { return GetHMISParticle(16);   };
   inline FitParticle* GetHMISElectron   (void) { return GetHMISParticle(11);   };
   inline FitParticle* GetHMISMuon       (void) { return GetHMISParticle(13);   };
   inline FitParticle* GetHMISTau        (void) { return GetHMISParticle(15);   };
   inline FitParticle* GetHMISAnyLeptons (void) { return GetHMISParticle(PhysConst::pdg_all_leptons);   };
   inline FitParticle* GetHMISProton     (void) { return GetHMISParticle(2212); };
   inline FitParticle* GetHMISNeutron    (void) { return GetHMISParticle(2112); };
   inline FitParticle* GetHMISPiZero     (void) { return GetHMISParticle(111);  };
   inline FitParticle* GetHMISPiPlus     (void) { return GetHMISParticle(211);  };
   inline FitParticle* GetHMISPiMinus    (void) { return GetHMISParticle(-211); };
   inline FitParticle* GetHMISPhoton     (void) { return GetHMISParticle(22);   };
   inline FitParticle* GetHMISLepton    (void) { return GetHMISParticle(PhysConst::pdg_leptons);       };
   inline FitParticle* GetHMISPions      (void) { return GetHMISParticle(PhysConst::pdg_pions);         };
   inline FitParticle* GetHMISChargePions(void) { return GetHMISParticle(PhysConst::pdg_charged_pions); };
 
   inline int GetHMISNuElectronIndex (void) { return GetHMISParticleIndex(12);   };
   inline int GetHMISNuMuonIndex     (void) { return GetHMISParticleIndex(14);   };
   inline int GetHMISNuTauIndex      (void) { return GetHMISParticleIndex(16);   };
   inline int GetHMISElectronIndex   (void) { return GetHMISParticleIndex(11);   };
   inline int GetHMISMuonIndex       (void) { return GetHMISParticleIndex(13);   };
   inline int GetHMISTauIndex        (void) { return GetHMISParticleIndex(15);   };
   inline int GetHMISProtonIndex     (void) { return GetHMISParticleIndex(2212); };
   inline int GetHMISNeutronIndex    (void) { return GetHMISParticleIndex(2112); };
   inline int GetHMISPiZeroIndex     (void) { return GetHMISParticleIndex(111);  };
   inline int GetHMISPiPlusIndex     (void) { return GetHMISParticleIndex(211);  };
   inline int GetHMISPiMinusIndex    (void) { return GetHMISParticleIndex(-211); };
   inline int GetHMISPhotonIndex     (void) { return GetHMISParticleIndex(22);   };
   inline int GetHMISLeptonsIndex    (void) { return GetHMISParticleIndex(PhysConst::pdg_leptons);       };
   inline int GetHMISPionsIndex      (void) { return GetHMISParticleIndex(PhysConst::pdg_pions);         };
   inline int GetHMISChargePionsIndex(void) { return GetHMISParticleIndex(PhysConst::pdg_charged_pions); };
 
   // ---- Final State Helpers --- //
   inline bool HasFSParticle(int const pdg) const {
     return HasParticle(pdg, kFinalState);
   };
   template <size_t N>
   inline bool HasFSParticle(int const (&pdgs)[N]) const {
     return HasParticle(pdgs, kFinalState);
   };
 
   inline int NumFSParticle(int const pdg = 0) const {
     return NumParticle(pdg, kFinalState);
   };
   template <size_t N>
   inline int NumFSParticle(int const (&pdgs)[N]) const {
     return NumParticle(pdgs, kFinalState);
   };
 
   inline std::vector<int> GetAllFSParticleIndices(int const pdg = -1) const {
     return GetAllParticleIndices(pdg, kFinalState);
   };
   template <size_t N>
   inline std::vector<int> GetAllFSParticleIndices(int const (&pdgs)[N]) const {
     return GetAllParticleIndices(pdgs, kFinalState);
   };
 
   inline std::vector<FitParticle*> GetAllFSParticle(int const pdg = -1) {
     return GetAllParticle(pdg, kFinalState);
   };
   template <size_t N>
   inline std::vector<FitParticle*> GetAllFSParticle(int const (&pdgs)[N]) {
     return GetAllParticle(pdgs, kFinalState);
   };
 
   inline FitParticle* GetHMFSParticle(int const pdg) {
     return GetHMParticle(pdg, kFinalState);
   };
   template <size_t N>
   inline FitParticle* GetHMFSParticle(int const (&pdgs)[N]) {
     return GetHMParticle(pdgs, kFinalState);
   };
 
   inline int GetHMFSParticleIndex(int const pdg) const {
     return GetHMParticleIndex(pdg, kFinalState);
   };
   template <size_t N>
   inline int GetHMFSParticleIndex(int const (&pdgs)[N]) const {
     return GetHMParticleIndex(pdgs, kFinalState);
   };
 
   inline bool HasFSNuElectron   (void) const { return HasFSParticle(12);   };
   inline bool HasFSNuMuon       (void) const { return HasFSParticle(14);   };
   inline bool HasFSNuTau        (void) const { return HasFSParticle(16);   };
   inline bool HasFSElectron     (void) const { return HasFSParticle(11);   };
   inline bool HasFSMuon         (void) const { return HasFSParticle(13);   };
   inline bool HasFSTau          (void) const { return HasFSParticle(15);   };
   inline bool HasFSProton       (void) const { return HasFSParticle(2212); };
   inline bool HasFSNeutron      (void) const { return HasFSParticle(2112); };
   inline bool HasFSPiZero       (void) const { return HasFSParticle(111);  };
   inline bool HasFSPiPlus       (void) const { return HasFSParticle(211);  };
   inline bool HasFSPiMinus      (void) const { return HasFSParticle(-211); };
   inline bool HasFSPhoton       (void) const { return HasFSParticle(22);   };
   inline bool HasFSLeptons      (void) const { return HasFSParticle(PhysConst::pdg_leptons);       };
   inline bool HasFSPions        (void) const { return HasFSParticle(PhysConst::pdg_pions);         };
   inline bool HasFSChargePions  (void) const { return HasFSParticle(PhysConst::pdg_charged_pions); };
 
   inline int NumFSNuElectron   (void) const { return NumFSParticle(12);   };
   inline int NumFSNuMuon       (void) const { return NumFSParticle(14);   };
   inline int NumFSNuTau        (void) const { return NumFSParticle(16);   };
   inline int NumFSElectron     (void) const { return NumFSParticle(11);   };
   inline int NumFSMuon         (void) const { return NumFSParticle(13);   };
   inline int NumFSTau          (void) const { return NumFSParticle(15);   };
   inline int NumFSProton       (void) const { return NumFSParticle(2212); };
   inline int NumFSNeutron      (void) const { return NumFSParticle(2112); };
   inline int NumFSPiZero       (void) const { return NumFSParticle(111);  };
   inline int NumFSPiPlus       (void) const { return NumFSParticle(211);  };
   inline int NumFSPiMinus      (void) const { return NumFSParticle(-211); };
   inline int NumFSPhoton       (void) const { return NumFSParticle(22);   };
   int NumFSLeptons      (void) const; // { return NumFSParticle(PhysConst::pdg_leptons);       };
   inline int NumFSPions        (void) const { return NumFSParticle(PhysConst::pdg_pions);         };
   inline int NumFSChargePions  (void) const { return NumFSParticle(PhysConst::pdg_charged_pions); };
 
   inline std::vector<int> GetAllFSNuElectronIndices (void) const { return GetAllFSParticleIndices(12);   };
   inline std::vector<int> GetAllFSNuMuonIndices     (void) const { return GetAllFSParticleIndices(14);   };
   inline std::vector<int> GetAllFSNuTauIndices      (void) const { return GetAllFSParticleIndices(16);   };
   inline std::vector<int> GetAllFSElectronIndices   (void) const { return GetAllFSParticleIndices(11);   };
   inline std::vector<int> GetAllFSMuonIndices       (void) const { return GetAllFSParticleIndices(13);   };
   inline std::vector<int> GetAllFSTauIndices        (void) const { return GetAllFSParticleIndices(15);   };
   inline std::vector<int> GetAllFSProtonIndices     (void) const { return GetAllFSParticleIndices(2212); };
   inline std::vector<int> GetAllFSNeutronIndices    (void) const { return GetAllFSParticleIndices(2112); };
   inline std::vector<int> GetAllFSPiZeroIndices     (void) const { return GetAllFSParticleIndices(111);  };
   inline std::vector<int> GetAllFSPiPlusIndices     (void) const { return GetAllFSParticleIndices(211);  };
   inline std::vector<int> GetAllFSPiMinusIndices    (void) const { return GetAllFSParticleIndices(-211); };
   inline std::vector<int> GetAllFSPhotonIndices     (void) const { return GetAllFSParticleIndices(22);   };
   inline std::vector<int> GetAllFSLeptonsIndices    (void) const { return GetAllFSParticleIndices(PhysConst::pdg_leptons);       };
   inline std::vector<int> GetAllFSPionsIndices      (void) const { return GetAllFSParticleIndices(PhysConst::pdg_pions);         };
   inline std::vector<int> GetAllFSChargePionsIndices(void) const { return GetAllFSParticleIndices(PhysConst::pdg_charged_pions); };
 
   inline std::vector<FitParticle*> GetAllFSNuElectron (void) { return GetAllFSParticle(12);   };
   inline std::vector<FitParticle*> GetAllFSNuMuon     (void) { return GetAllFSParticle(14);   };
   inline std::vector<FitParticle*> GetAllFSNuTau      (void) { return GetAllFSParticle(16);   };
   inline std::vector<FitParticle*> GetAllFSElectron   (void) { return GetAllFSParticle(11);   };
   inline std::vector<FitParticle*> GetAllFSMuon       (void) { return GetAllFSParticle(13);   };
   inline std::vector<FitParticle*> GetAllFSTau        (void) { return GetAllFSParticle(15);   };
   inline std::vector<FitParticle*> GetAllFSProton     (void) { return GetAllFSParticle(2212); };
   inline std::vector<FitParticle*> GetAllFSNeutron    (void) { return GetAllFSParticle(2112); };
   inline std::vector<FitParticle*> GetAllFSPiZero     (void) { return GetAllFSParticle(111);  };
   inline std::vector<FitParticle*> GetAllFSPiPlus     (void) { return GetAllFSParticle(211);  };
   inline std::vector<FitParticle*> GetAllFSPiMinus    (void) { return GetAllFSParticle(-211); };
   inline std::vector<FitParticle*> GetAllFSPhoton     (void) { return GetAllFSParticle(22);   };
   inline std::vector<FitParticle*> GetAllFSLeptons     (void) { return GetAllFSParticle(PhysConst::pdg_leptons);       };
   inline std::vector<FitParticle*> GetAllFSPions       (void) { return GetAllFSParticle(PhysConst::pdg_pions);         };
   inline std::vector<FitParticle*> GetAllFSChargePions (void) { return GetAllFSParticle(PhysConst::pdg_charged_pions); };
 
   inline FitParticle* GetHMFSNuElectron (void) { return GetHMFSParticle(12);   };
   inline FitParticle* GetHMFSNuMuon     (void) { return GetHMFSParticle(14);   };
   inline FitParticle* GetHMFSNuTau      (void) { return GetHMFSParticle(16);   };
   inline FitParticle* GetHMFSElectron   (void) { return GetHMFSParticle(11);   };
   inline FitParticle* GetHMFSMuon       (void) { return GetHMFSParticle(13);   };
   inline FitParticle* GetHMFSTau        (void) { return GetHMFSParticle(15);   };
   inline FitParticle* GetHMFSAnyLeptons (void) { return GetHMFSParticle(PhysConst::pdg_all_leptons);   };
   inline FitParticle* GetHMFSProton     (void) { return GetHMFSParticle(2212); };
   inline FitParticle* GetHMFSNeutron    (void) { return GetHMFSParticle(2112); };
   inline FitParticle* GetHMFSPiZero     (void) { return GetHMFSParticle(111);  };
   inline FitParticle* GetHMFSPiPlus     (void) { return GetHMFSParticle(211);  };
   inline FitParticle* GetHMFSPiMinus    (void) { return GetHMFSParticle(-211); };
   inline FitParticle* GetHMFSPhoton     (void) { return GetHMFSParticle(22);   };
 
   inline FitParticle* GetHMFSLeptons    (void) { return GetHMFSParticle(PhysConst::pdg_leptons);       };
   inline FitParticle* GetHMFSAnyLepton  (void) { return GetHMFSParticle(PhysConst::pdg_all_leptons);   };
 
   inline FitParticle* GetHMFSPions      (void) { return GetHMFSParticle(PhysConst::pdg_pions);         };
   inline FitParticle* GetHMFSChargePions(void) { return GetHMFSParticle(PhysConst::pdg_charged_pions); };
 
   inline int GetHMFSNuElectronIndex (void) const { return GetHMFSParticleIndex(12);   };
   inline int GetHMFSNuMuonIndex     (void) const { return GetHMFSParticleIndex(14);   };
   inline int GetHMFSNuTauIndex      (void) const { return GetHMFSParticleIndex(16);   };
   inline int GetHMFSElectronIndex   (void) const { return GetHMFSParticleIndex(11);   };
   inline int GetHMFSMuonIndex       (void) const { return GetHMFSParticleIndex(13);   };
   inline int GetHMFSTauIndex        (void) const { return GetHMFSParticleIndex(15);   };
   inline int GetHMFSProtonIndex     (void) const { return GetHMFSParticleIndex(2212); };
   inline int GetHMFSNeutronIndex    (void) const { return GetHMFSParticleIndex(2112); };
   inline int GetHMFSPiZeroIndex     (void) const { return GetHMFSParticleIndex(111);  };
   inline int GetHMFSPiPlusIndex     (void) const { return GetHMFSParticleIndex(211);  };
   inline int GetHMFSPiMinusIndex    (void) const { return GetHMFSParticleIndex(-211); };
   inline int GetHMFSPhotonIndex     (void) const { return GetHMFSParticleIndex(22);   };
 
   inline int GetHMFSLeptonsIndex    (void) const { return GetHMFSParticleIndex(PhysConst::pdg_leptons);       };
   inline int GetHMFSAnyLeptonIndex  (void) const { return GetHMFSParticleIndex(PhysConst::pdg_all_leptons);       };
 
   inline int GetHMFSPionsIndex      (void) const { return GetHMFSParticleIndex(PhysConst::pdg_pions);         };
   inline int GetHMFSChargePionsIndex(void) const { return GetHMFSParticleIndex(PhysConst::pdg_charged_pions); };
 
   // ---- NEUTRINO INCOMING Related Functions
   int                   GetBeamNeutrinoIndex   (void) const;
   inline TLorentzVector GetBeamNeutrinoP4      (void) const { return GetParticleP4(GetBeamNeutrinoIndex()); };
   inline TVector3       GetBeamNeutrinoP3      (void) const { return GetParticleP3(GetBeamNeutrinoIndex()); };
   inline double         GetBeamNeutrinoMom     (void) const { return GetParticleMom(GetBeamNeutrinoIndex()); };
   inline double         GetBeamNeutrinoMom2    (void) const { return GetParticleMom2(GetBeamNeutrinoIndex()); };
   inline double         GetBeamNeutrinoE       (void) const { return GetParticleE(GetBeamNeutrinoIndex()); };
   inline double         Enu                    (void) const { return GetBeamNeutrinoE(); };
   inline int            GetBeamNeutrinoPDG     (void) const { return GetParticlePDG(GetBeamNeutrinoIndex()); };
   inline int            PDGnu                  (void) const { return GetBeamNeutrinoPDG(); };
   inline int            GetNeutrinoInPos       (void) const { return GetBeamNeutrinoIndex(); };
   inline FitParticle*   GetBeamNeutrino        (void) { return GetParticle(GetBeamNeutrinoIndex()); };
   inline FitParticle*   GetNeutrinoIn          (void) { return GetParticle(GetBeamNeutrinoIndex()); };
 
 
   // ---- Electron INCOMING Related Functions
   int                   GetBeamElectronIndex   (void) const;
   inline TLorentzVector GetBeamElectronP4      (void) const { return GetParticleP4(GetBeamElectronIndex()); };
   inline TVector3       GetBeamElectronP3      (void) const { return GetParticleP3(GetBeamElectronIndex()); };
   inline double         GetBeamElectronMom     (void) const { return GetParticleMom(GetBeamElectronIndex()); };
   inline double         GetBeamElectronMom2    (void) const { return GetParticleMom2(GetBeamElectronIndex()); };
   inline double         GetBeamElectronE       (void) const { return GetParticleE(GetBeamElectronIndex()); };
   inline FitParticle*   GetBeamElectron        (void) { return GetParticle(GetBeamElectronIndex()); };
 
   // ---- Pion INCOMING Functions
   int                   GetBeamPionIndex   (void) const;
   inline TLorentzVector GetBeamPionP4      (void) const { return GetParticleP4(GetBeamPionIndex()); };
   inline TVector3       GetBeamPionP3      (void) const { return GetParticleP3(GetBeamPionIndex()); };
   inline double         GetBeamPionMom     (void) const { return GetParticleMom(GetBeamPionIndex()); };
   inline double         GetBeamPionMom2    (void) const { return GetParticleMom2(GetBeamPionIndex()); };
   inline double         GetBeamPionE       (void) const { return GetParticleE(GetBeamPionIndex()); };
   inline FitParticle*   GetBeamPion        (void) { return GetParticle(GetBeamPionIndex()); };
 
   /// Legacy Functions
   inline FitParticle* PartInfo(uint i) { return GetParticle(i); };
   inline UInt_t Npart (void) const { return NPart(); };
   inline UInt_t NPart (void) const { return fNParticles; };
 
 
 
   // Other Functions
   int NumFSMesons();
   inline int GetBeamPartPos(void) const { return 0; };
   FitParticle* GetBeamPart(void);
 
   int GetLeptonOutPos(void) const;
   FitParticle* GetLeptonOut(void);
 
 
   // Event Information
   double weight;  // need for silly reason
   int Mode;  // Public access needed
 
   int fMode;
   UInt_t fEventNo;
   double fTotCrs;
   int fTargetA;
   int fTargetZ;
   int fTargetH;
   bool fBound;
   int fDistance;
   int fTargetPDG;
 
   // Reduced Particle Stack
   UInt_t kMaxParticles;
   int fNParticles;
   double** fParticleMom;
   UInt_t* fParticleState;
   int* fParticlePDG;
   FitParticle** fParticleList;
 
   double** fOrigParticleMom;
   UInt_t* fOrigParticleState;
   int* fOrigParticlePDG;
 
   double* fNEUT_ParticleStatusCode;
   double* fNEUT_ParticleAliveCode;
   GeneratorInfoBase* fGenInfo;
 
   // Config Options for this class
   bool kRemoveFSIParticles;
   bool kRemoveUndefParticles;
 
 
 
 };
 /*! @} */
 #endif
diff --git a/src/InputHandler/InputUtils.cxx b/src/InputHandler/InputUtils.cxx
index 8f7acdf..cb6047d 100644
--- a/src/InputHandler/InputUtils.cxx
+++ b/src/InputHandler/InputUtils.cxx
@@ -1,173 +1,173 @@
 // Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret
 
 /*******************************************************************************
 *    This file is part of NUISANCE.
 *
 *    NUISANCE is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    NUISANCE is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with NUISANCE.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
 
-#include "FitParameters.h"
+
 #include "GeneralUtils.h"
 
 #include "InputHandler.h"
 #include "InputUtils.h"
 
 namespace InputUtils {
 
 std::vector<std::string> ParseInputFileList(std::string const &inpFile) {
   std::vector<std::string> inputs = GeneralUtils::ParseToStr(inpFile, ",");
   if (inputs.front()[0] == '(') {
     inputs.front() = inputs.front().substr(1);
   }
   if (inputs.back()[inputs.back().size() - 1] == ')') {
     inputs.back() = inputs.back().substr(0, inputs.back().size() - 1);
   }
   return inputs;
 }
 
 InputType ParseInputType(std::string const &inp) {
   // The hard-coded list of supported input generators
   const static std::string filetypes[] = {
       "NEUT",   "NUWRO", "GENIE",  "GiBUU", "NUANCE",
       "EVSPLN", "EMPTY", "FEVENT", "JOINT", "SIGMAQ0HIST", "HISTO"};
 
   size_t nInputTypes = GeneralUtils::GetArraySize(filetypes);
 
   for (size_t i = 0; i < nInputTypes; i++) {
     if (inp == filetypes[i]) {
       return InputType(i);
     }
   }
 
   return kInvalid_Input;
 }
 
 bool IsJointInput(std::string const &inputs) {
   bool isJoint = (inputs[0] == '(');
   if (isJoint && (inputs[inputs.length() - 1] != ')')) {
     ERR(FTL) << "Inputs specifier: \"" << inputs
              << "\" looks like a composite input specifier -- "
                 "(filea.root,fileb.root), however, it did not end in a \')\', "
                 "it ended in a \'"
              << inputs[inputs.length() - 1] << "\'" << std::endl;
     throw;
   }
   return isJoint;
 }
 
 std::string ExpandInputDirectories(std::string const &inputs) {
   // Parse the "environement" flags in the fitter config
   // Can specify NEUT_DIR = "" and others in parameters/fitter.config.dat
   const static std::string filedir[] = {"NEUT_DIR",   "NUWRO_DIR",
                                         "GENIE_DIR",  "NUANCE_DIR",
                                         "EVSPLN_DIR", "GIBUU_DIR"};
   size_t nfiledir = GeneralUtils::GetArraySize(filedir);
   std::string expandedInputs = inputs;
 
   for (size_t i = 0; i < nfiledir; i++) {
     std::string tempdir = "@" + filedir[i];
     bool didRpl;
     do {
       size_t torpl = expandedInputs.find(tempdir);
       if (torpl != std::string::npos) {
         std::string event_folder = FitPar::Config().GetParS(filedir[i]);
         expandedInputs.replace(torpl, tempdir.size(), event_folder);
         didRpl = true;
       } else {
         didRpl = false;
       }
     } while (didRpl);
   }
 
   bool didRpl;
   do {
     size_t torpl = expandedInputs.find("//");
     if (torpl != std::string::npos) {
       expandedInputs.replace(torpl, 2, "/");
       didRpl = true;
     } else {
       didRpl = false;
     }
   } while (didRpl);
 
   return expandedInputs;
 }
 
 InputType GuessInputTypeFromFile(TFile *inpF) {
   const std::string NEUT_TreeName = "neuttree";
   const std::string NuWro_TreeName = "treeout";
   const std::string GENIE_TreeName = "gtree";
   const std::string GiBUU_TreeName = "giRooTracker";
   if (!inpF) {
     return kInvalid_Input;
   }
   TTree *NEUT_Input = dynamic_cast<TTree *>(inpF->Get(NEUT_TreeName.c_str()));
   if (NEUT_Input) {
     return kNEUT_Input;
   }
   TTree *NUWRO_Input = dynamic_cast<TTree *>(inpF->Get(NuWro_TreeName.c_str()));
   if (NUWRO_Input) {
     return kNUWRO_Input;
   }
   TTree *GENIE_Input = dynamic_cast<TTree *>(inpF->Get(GENIE_TreeName.c_str()));
   if (GENIE_Input) {
     return kGENIE_Input;
   }
   TTree *GiBUU_Input = dynamic_cast<TTree *>(inpF->Get(GiBUU_TreeName.c_str()));
   if (GiBUU_Input) {
     return kGiBUU_Input;
   }
 
   return kInvalid_Input;
 }
 
 std::string PrependGuessedInputTypeToName(std::string const &inpFName) {
 
   //If it already has a name.
   if(inpFName.find(":") != std::string::npos){
     return inpFName;
   }
 
   TFile *inpF = TFile::Open(inpFName.c_str(), "READ");
   if (!inpF || !inpF->IsOpen()) {
     THROW("Couldn't open \"" << inpFName << "\" for reading.");
   }
   InputType iType = GuessInputTypeFromFile(inpF);
   if (iType == kInvalid_Input) {
     THROW("Couldn't determine input type from file: " << inpFName << ".");
   }
   inpF->Close();
   delete inpF;
 
   switch (iType) {
     case kNEUT_Input: {
       return "NEUT:" + inpFName;
     }
     case kNUWRO_Input: {
       return "NUWRO:" + inpFName;
     }
     case kGENIE_Input: {
       return "GENIE:" + inpFName;
     }
     case kGiBUU_Input: {
       return "GiBUU:" + inpFName;
     }
     default: {
       ERR(FTL) << "Input type from file: " << inpFName << " was invalid."
                << std::endl;
       throw;
     }
   }
 }
 }
diff --git a/src/Routines/CMakeLists.txt b/src/Logger/CMakeLists.txt
similarity index 79%
copy from src/Routines/CMakeLists.txt
copy to src/Logger/CMakeLists.txt
index 2c5cf1c..dee1fc1 100644
--- a/src/Routines/CMakeLists.txt
+++ b/src/Logger/CMakeLists.txt
@@ -1,66 +1,54 @@
 # Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret
 
 ################################################################################
 #    This file is part of NUISANCE.
 #
 #    NUISANCE is free software: you can redistribute it and/or modify
 #    it under the terms of the GNU General Public License as published by
 #    the Free Software Foundation, either version 3 of the License, or
 #    (at your option) any later version.
 #
 #    NUISANCE is distributed in the hope that it will be useful,
 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 #    GNU General Public License for more details.
 #
 #    You should have received a copy of the GNU General Public License
 #    along with NUISANCE.  If not, see <http://www.gnu.org/licenses/>.
 ################################################################################
-set(IMPLFILES
-ComparisonRoutines.cxx
-SystematicRoutines.cxx
-SplineRoutines.cxx
-)
-
-if(USE_MINIMIZER)
-  set(IMPLFILES ${IMPLFILES};MinimizerRoutines.cxx)
-endif()
-
 set(HEADERFILES
-ComparisonRoutines.h
-SystematicRoutines.h
-SplineRoutines.h
+FitLogger.h
+Initialiser.h
 )
 
-if(USE_MINIMIZER)
-  set(HEADERFILES ${HEADERFILES};MinimizerRoutines.h)
-endif()
+set(IMPLFILES
+PythiaQuiet.f
+FitLogger.cxx
+Initialiser.cxx
+)
 
-set(LIBNAME Routines)
+set(LIBNAME Logger)
 
 if(CMAKE_BUILD_TYPE MATCHES DEBUG)
   add_library(${LIBNAME} STATIC ${IMPLFILES})
 else(CMAKE_BUILD_TYPE MATCHES RELEASE)
   add_library(${LIBNAME} SHARED ${IMPLFILES})
 endif()
 
-include_directories(${EXP_INCLUDE_DIRECTORIES})
-
 include_directories(${MINIMUM_INCLUDE_DIRECTORIES})
 
-include_directories(${CMAKE_SOURCE_DIR}/src/FCN)
-include_directories(${CMAKE_SOURCE_DIR}/src/MCStudies)
-
 set_target_properties(${LIBNAME} PROPERTIES VERSION
   "${NUISANCE_VERSION_MAJOR}.${NUISANCE_VERSION_MINOR}.${NUISANCE_VERSION_REVISION}")
+
 #set_target_properties(${LIBNAME} PROPERTIES LINK_FLAGS ${ROOT_LD_FLAGS})
 
 if(DEFINED PROJECTWIDE_EXTRA_DEPENDENCIES)
   add_dependencies(${LIBNAME} ${PROJECTWIDE_EXTRA_DEPENDENCIES})
 endif()
 
 install(TARGETS ${LIBNAME} DESTINATION lib)
 #Can uncomment this to install the headers... but is it really neccessary?
 #install(FILES ${HEADERFILES} DESTINATION include)
 
 set(MODULETargets ${MODULETargets} ${LIBNAME} PARENT_SCOPE)
+
diff --git a/src/Utils/FitLogger.cxx b/src/Logger/FitLogger.cxx
similarity index 99%
rename from src/Utils/FitLogger.cxx
rename to src/Logger/FitLogger.cxx
index a5d364f..f675869 100644
--- a/src/Utils/FitLogger.cxx
+++ b/src/Logger/FitLogger.cxx
@@ -1,350 +1,352 @@
 // Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret
 
 /*******************************************************************************
 *    This file is part of NUISANCE.
 *
 *    NUISANCE is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    NUISANCE is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with NUISANCE.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
 
 #include "FitLogger.h"
 #include <fcntl.h>
 #include <unistd.h>
 
 namespace Logger {
 
 // Logger Variables
 int log_verb = 4;
 bool use_colors = true;
-bool showtrace = false;
+
+bool showtrace  = true;
+
 std::ostream* __LOG_outstream(&std::cout);
 std::ofstream __LOG_nullstream;
 
 // Error Variables
 int err_verb = 0;
 std::ostream* __ERR_outstream(&std::cerr);
 
 // Extra Variables
 bool external_verb = false;
 
 bool super_rainbow_mode = true;  //!< For when fitting gets boring.
 unsigned int super_rainbow_mode_colour = 0;
 
 std::streambuf* default_cout = std::cout.rdbuf();
 std::streambuf* default_cerr = std::cerr.rdbuf();
 std::ofstream redirect_stream("/dev/null");
 int silentfd = open("/dev/null", O_WRONLY);
 int savedstdoutfd = dup(fileno(stdout));
 int savedstderrfd = dup(fileno(stderr));
 
 int nloggercalls = 0;
 int timelastlog = 0;
 }
 
 // -------- Logging Functions --------- //
 
 bool LOGGING(int level) {
   // std::cout << "LOGGING : " << __FILENAME__ << " " << __FUNCTION__ <<
   // std::endl;
   return (Logger::log_verb >=
           (uint)__GETLOG_LEVEL(level, __FILENAME__, __FUNCTION__));
 };
 
 int __GETLOG_LEVEL(int level, const char* filename, const char* funct) {
 #ifdef __DEBUG__
   int logfile = FitPar::Config().GetParI("logging." + std::string(filename));
   if (logfile >= DEB and logfile <= EVT) {
     level = logfile;
   }
 
   int logfunc = FitPar::Config().GetParI("logging." + std::string(funct));
   if (logfunc >= DEB and logfunc <= EVT) {
     level = logfunc;
   }
 #endif
 
   return level;
 };
 
 std::ostream& __OUTLOG(int level, const char* filename, const char* funct,
                        int line) {
   if (Logger::log_verb < (unsigned int)level &&
       Logger::log_verb != (unsigned int)DEB) {
     return (Logger::__LOG_nullstream);
 
   } else {
     if (Logger::use_colors) {
       switch (level) {
         case FIT:
           std::cout << BOLDGREEN;
           break;
         case MIN:
           std::cout << BOLDBLUE;
           break;
         case SAM:
           std::cout << MAGENTA;
           break;
         case REC:
           std::cout << BLUE;
           break;
         case SIG:
           std::cout << GREEN;
           break;
         case DEB:
           std::cout << CYAN;
           break;
         default:
           break;
       }
     }
 
     switch (level) {
       case FIT:
         std::cout << "[LOG Fitter]";
         break;
       case MIN:
         std::cout << "[LOG Minmzr]";
         break;
       case SAM:
         std::cout << "[LOG Sample]";
         break;
       case REC:
         std::cout << "[LOG Reconf]";
         break;
       case SIG:
         std::cout << "[LOG Signal]";
         break;
       case EVT:
         std::cout << "[LOG Event ]";
         break;
       case DEB:
         std::cout << "[LOG DEBUG ]";
         break;
       default:
         std::cout << "[LOG INFO  ]";
         break;
     }
 
     // Apply indent
     if (true) {
       switch (level) {
         case FIT:
           std::cout << ": ";
           break;
         case MIN:
           std::cout << ":- ";
           break;
         case SAM:
           std::cout << ":-- ";
           break;
         case REC:
           std::cout << ":--- ";
           break;
         case SIG:
           std::cout << ":---- ";
           break;
         case EVT:
           std::cout << ":----- ";
           break;
         case DEB:
           std::cout << ":------ ";
           break;
         default:
           std::cout << " ";
           break;
       }
     }
 
     if (Logger::use_colors) std::cout << RESET;
 
     if (Logger::showtrace) {
       std::cout << " : " << filename << "::" << funct << "[l. " << line
                 << "] : ";
     }
 
     return *(Logger::__LOG_outstream);
   }
 }
 
 void SETVERBOSITY(int level) { Logger::log_verb = level; }
 
 void SETVERBOSITY(std::string verb) {
   if (!verb.compare("DEB"))
     Logger::log_verb = -1;
   else if (!verb.compare("QUIET"))
     Logger::log_verb = 0;
   else if (!verb.compare("FIT"))
     Logger::log_verb = 1;
   else if (!verb.compare("MIN"))
     Logger::log_verb = 2;
   else if (!verb.compare("SAM"))
     Logger::log_verb = 3;
   else if (!verb.compare("REC"))
     Logger::log_verb = 4;
   else if (!verb.compare("SIG"))
     Logger::log_verb = 5;
   else if (!verb.compare("EVT"))
     Logger::log_verb = 6;
   else
     Logger::log_verb = std::atoi(verb.c_str());
 }
 
 /// Set Trace Option
 void SETTRACE(bool val) { Logger::showtrace = val; }
 
 // ------ ERROR FUNCTIONS ---------- //
 std::ostream& __OUTERR(int level, const char* filename, const char* funct,
                        int line) {
   if (Logger::use_colors) std::cerr << RED;
 
   switch (level) {
     case FTL:
       std::cerr << "[ERR FATAL ]: ";
       break;
     case WRN:
       std::cerr << "[ERR WARN  ]: ";
       break;
   }
 
   if (Logger::use_colors) std::cerr << RESET;
 
   // Allows enable error debugging trace
   if (true or Logger::showtrace) {
     std::cout << filename << "::" << funct << "[l. " << line << "] : ";
   }
 
   return *(Logger::__ERR_outstream);
 }
 
 // ----------- External Logging ----------- //
 void SETEXTERNALVERBOSITY(int level) { Logger::external_verb = (level > 0); }
 
 void StopTalking() {
   // Check verbosity set correctly
   if (!Logger::external_verb) return;
 
   // Only redirect if we're not debugging
   if (Logger::log_verb == (unsigned int)DEB) return;
 
   std::cout.rdbuf(Logger::redirect_stream.rdbuf());
   std::cerr.rdbuf(Logger::redirect_stream.rdbuf());
   shhnuisancepythiaitokay_();
   fflush(stdout);
   fflush(stderr);
   dup2(Logger::silentfd, fileno(stdout));
   dup2(Logger::silentfd, fileno(stderr));
 }
 
 void StartTalking() {
   // Check verbosity set correctly
   if (!Logger::external_verb) return;
 
   std::cout.rdbuf(Logger::default_cout);
   std::cerr.rdbuf(Logger::default_cerr);
   canihaznuisancepythia_();
   fflush(stdout);
   fflush(stderr);
   dup2(Logger::savedstdoutfd, fileno(stdout));
   dup2(Logger::savedstderrfd, fileno(stderr));
 }
 
 //******************************************
 void LOG_VERB(std::string verb) {
   //******************************************
 
   if (!verb.compare("DEB"))
     Logger::log_verb = -1;
   else if (!verb.compare("QUIET"))
     Logger::log_verb = 0;
   else if (!verb.compare("FIT"))
     Logger::log_verb = 1;
   else if (!verb.compare("MIN"))
     Logger::log_verb = 2;
   else if (!verb.compare("SAM"))
     Logger::log_verb = 3;
   else if (!verb.compare("REC"))
     Logger::log_verb = 4;
   else if (!verb.compare("SIG"))
     Logger::log_verb = 5;
   else if (!verb.compare("EVT"))
     Logger::log_verb = 6;
   // else Logger::log_verb = GeneralUtils::StrToInt(verb);
 
   std::cout << "Set logging verbosity to : " << Logger::log_verb << std::endl;
   return;
 }
 
 //******************************************
 void ERR_VERB(std::string verb) {
   //******************************************
   std::cout << "Setting ERROR VERB" << std::endl;
 
   if (!verb.compare("ERRQUIET"))
     Logger::err_verb = 0;
   else if (!verb.compare("FTL"))
     Logger::err_verb = 1;
   else if (!verb.compare("WRN"))
     Logger::err_verb = 2;
   // else Logger::err_verb = GeneralUtils::StrToInt(verb);
 
   std::cout << "Set error verbosity to : " << Logger::err_verb << std::endl;
   return;
 }
 
 //******************************************
 bool LOG_LEVEL(int level) {
   //******************************************
 
   if (Logger::log_verb == (unsigned int)DEB) {
     return true;
   }
 
   if (Logger::log_verb < (unsigned int)level) {
     return false;
   }
 
   return true;
 }
 
 void SET_TRACE(bool val) { Logger::showtrace = val; }
 
 //******************************************
 std::ostream& _LOG(int level, const char* filename, const char* func, int line)
 //******************************************
 {
   return __OUTLOG(level, filename, func, line);
 }
 
 //******************************************
 std::ostream& _ERR(int level, const char* filename, const char* func, int line)
 //******************************************
 {
   if (Logger::use_colors) std::cerr << RED;
 
   if (Logger::showtrace) {
     std::cout << filename << "::" << func << "[l. " << line << "] : ";
   }
 
   switch (level) {
     case FTL:
       std::cerr << "[ERR FATAL ]: ";
       break;
     case WRN:
       std::cerr << "[ERR WARN  ] : ";
       break;
   }
 
   if (Logger::use_colors) std::cerr << RESET;
 
   return *Logger::__ERR_outstream;
 }
diff --git a/src/Utils/FitLogger.h b/src/Logger/FitLogger.h
similarity index 97%
rename from src/Utils/FitLogger.h
rename to src/Logger/FitLogger.h
index d8b26e9..ce46f6c 100644
--- a/src/Utils/FitLogger.h
+++ b/src/Logger/FitLogger.h
@@ -1,218 +1,221 @@
 // Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret
 
 /*******************************************************************************
 *    This file is part of NUISANCE.
 *
 *    NUISANCE is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    NUISANCE is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with NUISANCE.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
 #ifndef FITLOGGER_HPP
 #define FITLOGGER_HPP
 /*!
  *  \addtogroup FitBase
  *  @{
  */
 
 #include <fstream>
 #include <iosfwd>
 #include <iostream>
 #include <sstream>
-#include "FitParameters.h"
-#include "Initialiser.h"
+
 #include "TRandom3.h"
 
+#include "Initialiser.h"
+
+#include "NuisConfig.h"
+
 #define RESET "\033[0m"
 #define BLACK "\033[30m"              /* Black */
 #define RED "\033[31m"                /* Red */
 #define GREEN "\033[32m"              /* Green */
 #define YELLOW "\033[33m"             /* Yellow */
 #define BLUE "\033[34m"               /* Blue */
 #define MAGENTA "\033[35m"            /* Magenta */
 #define CYAN "\033[36m"               /* Cyan */
 #define WHITE "\033[37m"              /* White */
 #define BOLDBLACK "\033[1m\033[30m"   /* Bold Black */
 #define BOLDRED "\033[1m\033[31m"     /* Bold Red */
 #define BOLDGREEN "\033[1m\033[32m"   /* Bold Green */
 #define BOLDYELLOW "\033[1m\033[33m"  /* Bold Yellow */
 #define BOLDBLUE "\033[1m\033[34m"    /* Bold Blue */
 #define BOLDMAGENTA "\033[1m\033[35m" /* Bold Magenta */
 #define BOLDCYAN "\033[1m\033[36m"    /* Bold Cyan */
 #define BOLDWHITE "\033[1m\033[37m"   /* Bold White */
 
 namespace Logger {
 extern int log_verb;  //!< Current VERBOSITY
 extern int err_verb;  //!< Current ERROR VERBOSITY
 extern bool external_verb;
 extern bool use_colors;          //!< Use BASH Terminal Colors Flag
 extern bool super_rainbow_mode;  //!< For when fitting gets boring.
 extern unsigned int super_rainbow_mode_colour;
 
 extern bool showtrace;  // Quick Tracing for debugging
 extern int nloggercalls;
 extern int timelastlog;
 extern std::streambuf*
     default_cout;  //!< Where the STDOUT stream is currently directed
 extern std::streambuf*
     default_cerr;  //!< Where the STDERR stream is currently directed
 extern std::ofstream
     redirect_stream;  //!< Where should unwanted messages be thrown
 }
 
 /// Returns full path to file currently in
 #define __FILENAME__ \
   (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
 
 // ------ LOGGER FUNCTIONS ------------ //
 namespace Logger {
 /// NULL Output Stream
 extern std::ofstream __LOG_nullstream;
 
 /// Logging Stream
 extern std::ostream* __LOG_outstream;
 }
 
 /// Fitter VERBOSITY Enumerations
 /// These go through the different depths of the fitter.
 ///
 /// 0 QUIET - Little output.
 /// 1 FIT - Top Level Minimizer Status
 /// 2 MIN - Output from the FCN Minimizer Functions
 /// 3 SAM - Output from each of the samples during setup etc
 /// 4 REC - Output during each reconfigure. Percentage progress etc.
 /// 5 SIG - Output during every signal event that is found.
 /// 6 EVT - Output during every event.
 /// -1 DEB - Will print only debugging info wherever a LOG(DEB) statement was
 /// made
 enum __LOG_levels { DEB = -1, QUIET, FIT, MIN, SAM, REC, SIG, EVT };
 
 /// Returns log level for a given file/function
 int __GETLOG_LEVEL(int level, const char* filename, const char* funct);
 
 /// Actually runs the logger
 std::ostream& __OUTLOG(int level, const char* filename, const char* funct,
                        int line);
 
 /// Global Logging Definitions
 #define QLOG(level, stream)                                               \
   {                                                                       \
     if (Logger::log_verb >=                                               \
         __GETLOG_LEVEL(level, __FILENAME__, __FUNCTION__)) {              \
       __OUTLOG(level, __FILENAME__, __FUNCTION__, __LINE__) << stream     \
                                                             << std::endl; \
     }                                                                     \
   };
 
 #define BREAK(level)                                                      \
   {                                                                       \
     \ if (Logger::log_verb >=                                             \
           __GETLOG_LEVEL(level, __FILENAME__, __FUNCTION__)) {            \
       __OUTLOG(level, __FILENAME__, __FUNCTION__, __LINE__) << std::endl; \
     }                                                                     \
   };
 
 /// Return whether logging level is valid
 bool LOGGING(int level);
 
 /// Set Global Verbosity
 void SETVERBOSITY(int level);
 
 /// Set Global Verbosity from String
 void SETVERBOSITY(std::string verb);
 
 /// Set Trace Option
 void SETTRACE(bool val);
 
 // ----------- ERROR FUNCTIONS ---------- //
 
 /// Error Stream
 extern std::ostream* __ERR_outstream;
 
 /// Fitter ERROR VERBOSITY Enumerations
 ///
 /// 0 QUIET - No Error Output
 /// 1 FTL - Show errors only if fatal
 /// 2 WRN - Show Warning messages
 enum __ERR_levels { ERRQUIET = 0, FTL, WRN };
 
 /// Actually runs the error messager
 std::ostream& __OUTERR(int level, const char* filename, const char* funct,
                        int line);
 
 /// Error Logging Function
 #define ERROR(level, stream)                                            \
   {                                                                     \
     __OUTERR(level, __FILENAME__, __FUNCTION__, __LINE__) << stream     \
                                                           << std::endl; \
   };
 
 // ----------- ERROR HANDLING ------------- //
 /// Exit the program with given error message stream
 #define THROW(stream)                                                   \
   {                                                                     \
     __OUTERR(FTL, __FILENAME__, __FUNCTION__, __LINE__) << stream       \
                                                         << std::endl;   \
     __OUTERR(FTL, __FILENAME__, __FUNCTION__, __LINE__)                 \
         << "Attempting to save output file." << std::endl;              \
-    if (FitPar::Config().out && FitPar::Config().out->IsOpen()) {       \
-      FitPar::Config().out->Write();                                    \
-      FitPar::Config().out->Close();                                    \
+    if (Config::Get().out && Config::Get().out->IsOpen()) {       \
+      Config::Get().out->Write();                                    \
+      Config::Get().out->Close();                                    \
       __OUTERR(FTL, __FILENAME__, __FUNCTION__, __LINE__) << "Done."    \
                                                           << std::endl; \
     } else {                                                            \
       __OUTERR(FTL, __FILENAME__, __FUNCTION__, __LINE__)               \
           << "No output file set." << std::endl;                        \
     }                                                                   \
     __OUTERR(FTL, __FILENAME__, __FUNCTION__, __LINE__) << "Exiting!"   \
                                                         << std::endl;   \
     std::abort();                                                       \
   }
 
 // ----------- External Logging ----------- //
 void SETEXTERNALVERBOSITY(int level);
 
 void StopTalking();
 void StartTalking();
 
 extern "C" {
 void shhnuisancepythiaitokay_(void);
 void canihaznuisancepythia_(void);
 }
 
 // ---------- LEGACY FUNCTIONS -------------- //
 
 bool LOG_LEVEL(int level);
 
 //! Set LOG VERBOSITY from a string
 void LOG_VERB(std::string verb);
 inline void LOG_VERB(int verb) { Logger::log_verb = verb; };
 
 void SET_TRACE(bool val);
 
 //! Set ERROR VERBOSITY from a string
 void ERR_VERB(std::string verb);
 inline void ERR_VERB(int verb) { Logger::err_verb = verb; };
 
 /// Logging Function. Use as a string stream.  e.g. LOG(SAM) << "This sample is
 /// dope." << std::endl;
 std::ostream& _LOG(int level, const char* filename, const char* funct,
                    int line);
 #define LOG(level) _LOG(level, __FILENAME__, __FUNCTION__, __LINE__)
 
 //! Error Function. Use as a string stream.  e.g. ERR(FTL) << "The fit is
 //! completely buggered." << std::endl;
 std::ostream& _ERR(int level, const char* filename, const char* funct,
                    int line);
 #define ERR(level) _ERR(level, __FILENAME__, __FUNCTION__, __LINE__)
 
 /*! @} */
 #endif
diff --git a/src/Utils/Initialiser.cxx b/src/Logger/Initialiser.cxx
similarity index 100%
rename from src/Utils/Initialiser.cxx
rename to src/Logger/Initialiser.cxx
diff --git a/src/Utils/Initialiser.h b/src/Logger/Initialiser.h
similarity index 100%
rename from src/Utils/Initialiser.h
rename to src/Logger/Initialiser.h
diff --git a/src/Utils/PythiaQuiet.f b/src/Logger/PythiaQuiet.f
similarity index 100%
rename from src/Utils/PythiaQuiet.f
rename to src/Logger/PythiaQuiet.f
diff --git a/src/MCStudies/ElectronFlux_FlatTree.cxx b/src/MCStudies/ElectronFlux_FlatTree.cxx
index 5ccd5ea..e355f0e 100644
--- a/src/MCStudies/ElectronFlux_FlatTree.cxx
+++ b/src/MCStudies/ElectronFlux_FlatTree.cxx
@@ -1,559 +1,559 @@
 // Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret
 
 /*******************************************************************************
 *    This file is part of NUISANCE.
 *
 *    NUISANCE is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    NUISANCE is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with NUISANCE.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
 
 #include "ElectronFlux_FlatTree.h"
 
 //********************************************************************
 /// @brief Class to perform MC Studies on a custom measurement
 ElectronFlux_FlatTree::ElectronFlux_FlatTree(std::string name, std::string inputfile,
                                        FitWeight *rw, std::string type,
                                        std::string fakeDataFile) {
   //********************************************************************
 
   // Measurement Details
   fName = name;
   eventVariables = NULL;
 
   // Define our energy range for flux calcs
   EnuMin = 0.;
   EnuMax = 100.;  // Arbritrarily high energy limit
 
   // Set default fitter flags
   fIsDiag = true;
   fIsShape = false;
   fIsRawEvents = false;
 
   nu_4mom = new TLorentzVector(0, 0, 0, 0);
   pmu = new TLorentzVector(0, 0, 0, 0);
   ppip = new TLorentzVector(0, 0, 0, 0);
   ppim = new TLorentzVector(0, 0, 0, 0);
   ppi0 = new TLorentzVector(0, 0, 0, 0);
   pprot = new TLorentzVector(0, 0, 0, 0);
   pneut = new TLorentzVector(0, 0, 0, 0);
 
   // This function will sort out the input files automatically and parse all the
   // inputs,flags,etc.
   // There may be complex cases where you have to do this by hand, but usually
   // this will do.
   Measurement1D::SetupMeasurement(inputfile, type, rw, fakeDataFile);
 
   eventVariables = NULL;
   liteMode = FitPar::Config().GetParB("isLiteMode");
 
   // Setup fDataHist as a placeholder
   this->fDataHist = new TH1D(("empty_data"), ("empty-data"), 1, 0, 1);
   this->SetupDefaultHist();
   fFullCovar = StatUtils::MakeDiagonalCovarMatrix(fDataHist);
   covar = StatUtils::GetInvert(fFullCovar);
 
   // 1. The generator is organised in SetupMeasurement so it gives the
   // cross-section in "per nucleon" units.
   //    So some extra scaling for a specific measurement may be required. For
   //    Example to get a "per neutron" measurement on carbon
   //    which we do here, we have to multiple by the number of nucleons 12 and
   //    divide by the number of neutrons 6.
   this->fScaleFactor =
       (GetEventHistogram()->Integral("width") * 1E-38 / (fNEvents + 0.)) /
       this->TotalIntegratedFlux();
 
   LOG(SAM) << " Generic Flux Scaling Factor = " << fScaleFactor << std::endl;
 
   if (fScaleFactor <= 0.0) {
     ERR(WRN) << "SCALE FACTOR TOO LOW " << std::endl;
     sleep(20);
   }
 
   // Setup our TTrees
   this->AddEventVariablesToTree();
   this->AddSignalFlagsToTree();
 }
 
 void ElectronFlux_FlatTree::AddEventVariablesToTree() {
   // Setup the TTree to save everything
   if (!eventVariables) {
-    FitPar::Config().out->cd();
+    Config::Get().out->cd();
     eventVariables = new TTree((this->fName + "_VARS").c_str(),
                                (this->fName + "_VARS").c_str());
   }
 
   LOG(SAM) << "Adding Event Variables" << std::endl;
   eventVariables->Branch("Mode", &Mode, "Mode/I");
 
   eventVariables->Branch("PDGnu", &PDGnu, "PDGnu/I");
   eventVariables->Branch("Enu_true", &Enu_true, "Enu_true/F");
 
   eventVariables->Branch("Nleptons", &Nleptons, "Nleptons/I");
   eventVariables->Branch("MLep", &MLep, "MLep/F");
   eventVariables->Branch("ELep", &ELep, "ELep/F");
   eventVariables->Branch("TLep", &TLep, "TLep/F");
   eventVariables->Branch("CosLep", &CosLep, "CosLep/F");
   eventVariables->Branch("CosPmuPpip", &CosPmuPpip, "CosPmuPpip/F");
   eventVariables->Branch("CosPmuPpim", &CosPmuPpim, "CosPmuPpim/F");
   eventVariables->Branch("CosPmuPpi0", &CosPmuPpi0, "CosPmuPpi0/F");
   eventVariables->Branch("CosPmuPprot", &CosPmuPprot, "CosPmuPprot/F");
   eventVariables->Branch("CosPmuPneut", &CosPmuPneut, "CosPmuPneut/F");
 
   eventVariables->Branch("Nprotons", &Nprotons, "Nprotons/I");
   eventVariables->Branch("MPr", &MPr, "MPr/F");
   eventVariables->Branch("EPr", &EPr, "EPr/F");
   eventVariables->Branch("TPr", &TPr, "TPr/F");
   eventVariables->Branch("CosPr", &CosPr, "CosPr/F");
   eventVariables->Branch("CosPprotPneut", &CosPprotPneut, "CosPprotPneut/F");
 
   eventVariables->Branch("Nneutrons", &Nneutrons, "Nneutrons/I");
   eventVariables->Branch("MNe", &MNe, "MNe/F");
   eventVariables->Branch("ENe", &ENe, "ENe/F");
   eventVariables->Branch("TNe", &TNe, "TNe/F");
   eventVariables->Branch("CosNe", &CosNe, "CosNe/F");
 
   eventVariables->Branch("Npiplus", &Npiplus, "Npiplus/I");
   eventVariables->Branch("MPiP", &MPiP, "MPiP/F");
   eventVariables->Branch("EPiP", &EPiP, "EPiP/F");
   eventVariables->Branch("TPiP", &TPiP, "TPiP/F");
   eventVariables->Branch("CosPiP", &CosPiP, "CosPiP/F");
   eventVariables->Branch("CosPpipPprot", &CosPpipPprot, "CosPpipProt/F");
   eventVariables->Branch("CosPpipPneut", &CosPpipPneut, "CosPpipPneut/F");
   eventVariables->Branch("CosPpipPpim", &CosPpipPpim, "CosPpipPpim/F");
   eventVariables->Branch("CosPpipPpi0", &CosPpipPpi0, "CosPpipPpi0/F");
 
   eventVariables->Branch("Npineg", &Npineg, "Npineg/I");
   eventVariables->Branch("MPiN", &MPiN, "MPiN/F");
   eventVariables->Branch("EPiN", &EPiN, "EPiN/F");
   eventVariables->Branch("TPiN", &TPiN, "TPiN/F");
   eventVariables->Branch("CosPiN", &CosPiN, "CosPiN/F");
   eventVariables->Branch("CosPpimPprot", &CosPpimPprot, "CosPpimPprot/F");
   eventVariables->Branch("CosPpimPneut", &CosPpimPneut, "CosPpimPneut/F");
   eventVariables->Branch("CosPpimPpi0", &CosPpimPpi0, "CosPpimPpi0/F");
 
   eventVariables->Branch("Npi0", &Npi0, "Npi0/I");
   eventVariables->Branch("MPi0", &MPi0, "MPi0/F");
   eventVariables->Branch("EPi0", &EPi0, "EPi0/F");
   eventVariables->Branch("TPi0", &TPi0, "TPi0/F");
   eventVariables->Branch("CosPi0", &CosPi0, "CosPi0/F");
   eventVariables->Branch("CosPi0Pprot", &CosPi0Pprot, "CosPi0Pprot/F");
   eventVariables->Branch("CosPi0Pneut", &CosPi0Pneut, "CosPi0Pneut/F");
 
   eventVariables->Branch("Nother", &Nother, "Nother/I");
 
   eventVariables->Branch("Q2_true", &Q2_true, "Q2_true/F");
   eventVariables->Branch("q0_true", &q0_true, "q0_true/F");
   eventVariables->Branch("q3_true", &q3_true, "q3_true/F");
 
   eventVariables->Branch("Enu_QE", &Enu_QE, "Enu_QE/F");
   eventVariables->Branch("Q2_QE", &Q2_QE, "Q2_QE/F");
 
   eventVariables->Branch("W_nuc_rest", &W_nuc_rest, "W_nuc_rest/F");
   eventVariables->Branch("bjorken_x", &bjorken_x, "bjorken_x/F");
   eventVariables->Branch("bjorken_y", &bjorken_y, "bjorken_y/F");
 
   eventVariables->Branch("Erecoil_true", &Erecoil_true, "Erecoil_true/F");
   eventVariables->Branch("Erecoil_charged", &Erecoil_charged,
                          "Erecoil_charged/F");
   eventVariables->Branch("Erecoil_minerva", &Erecoil_minerva,
                          "Erecoil_minerva/F");
 
   if (!liteMode) {
     eventVariables->Branch("nu_4mom", &nu_4mom);
     eventVariables->Branch("pmu_4mom", &pmu);
     eventVariables->Branch("hm_ppip_4mom", &ppip);
     eventVariables->Branch("hm_ppim_4mom", &ppim);
     eventVariables->Branch("hm_ppi0_4mom", &ppi0);
     eventVariables->Branch("hm_pprot_4mom", &pprot);
     eventVariables->Branch("hm_pneut_4mom", &pneut);
   }
 
   // Event Scaling Information
   eventVariables->Branch("Weight", &Weight, "Weight/F");
   eventVariables->Branch("InputWeight", &InputWeight, "InputWeight/F");
   eventVariables->Branch("RWWeight", &RWWeight, "RWWeight/F");
   eventVariables->Branch("FluxWeight", &FluxWeight, "FluxWeight/F");
   eventVariables->Branch("fScaleFactor", &fScaleFactor, "fScaleFactor/D");
 
   return;
 }
 
 void ElectronFlux_FlatTree::AddSignalFlagsToTree() {
   if (!eventVariables) {
-    FitPar::Config().out->cd();
+    Config::Get().out->cd();
     eventVariables = new TTree((this->fName + "_VARS").c_str(),
                                (this->fName + "_VARS").c_str());
   }
 
   LOG(SAM) << "Adding Samples" << std::endl;
 
   // Signal Definitions from SignalDef.cxx
   eventVariables->Branch("flagCCINC", &flagCCINC, "flagCCINC/O");
   eventVariables->Branch("flagNCINC", &flagNCINC, "flagNCINC/O");
   eventVariables->Branch("flagCCQE", &flagCCQE, "flagCCQE/O");
   eventVariables->Branch("flagCC0pi", &flagCC0pi, "flagCC0pi/O");
   eventVariables->Branch("flagCCQELike", &flagCCQELike, "flagCCQELike/O");
   eventVariables->Branch("flagNCEL", &flagNCEL, "flagNCEL/O");
   eventVariables->Branch("flagNC0pi", &flagNC0pi, "flagNC0pi/O");
   eventVariables->Branch("flagCCcoh", &flagCCcoh, "flagCCcoh/O");
   eventVariables->Branch("flagNCcoh", &flagNCcoh, "flagNCcoh/O");
   eventVariables->Branch("flagCC1pip", &flagCC1pip, "flagCC1pip/O");
   eventVariables->Branch("flagNC1pip", &flagNC1pip, "flagNC1pip/O");
   eventVariables->Branch("flagCC1pim", &flagCC1pim, "flagCC1pim/O");
   eventVariables->Branch("flagNC1pim", &flagNC1pim, "flagNC1pim/O");
   eventVariables->Branch("flagCC1pi0", &flagCC1pi0, "flagCC1pi0/O");
   eventVariables->Branch("flagNC1pi0", &flagNC1pi0, "flagNC1pi0/O");
 };
 
 //********************************************************************
 void ElectronFlux_FlatTree::FillEventVariables(FitEvent *event) {
   //********************************************************************
 
   // Fill Signal Variables
   FillSignalFlags(event);
   LOG(DEB) << "Filling signal" << std::endl;
   // Function used to extract any variables of interest to the event
   Mode = event->Mode;
   Nleptons = 0;
   Nparticles = 0;
   PDGnu = 0;
   PDGLep = 0;
 
   Enu_true = Enu_QE = Q2_true = Q2_QE = TLep = TPr = TNe = TPiP = TPiN = TPi0 =
       -999.9;
 
   Nprotons = 0;
   PPr = EPr = MPr = CosPr = -999.9;
 
   Nneutrons = 0;
   PNe = ENe = MNe = CosNe = -999.9;
 
   Npiplus = 0;
   PPiP = EPiP = MPiP = CosPiP = -999.9;
 
   Npineg = 0;
   PPiN = EPiN = MPiN = CosPiN = -999.9;
 
   Npi0 = 0;
   PPi0 = EPi0 = MPi0 = CosPi0 = -999.9;
 
   // All of the angles Clarence added
   CosPmuPpip = CosPmuPpim = CosPmuPpi0 = CosPmuPprot = CosPmuPneut =
       CosPpipPprot = CosPpipPneut = CosPpipPpim = CosPpipPpi0 = CosPpimPprot =
           CosPpimPneut = CosPpimPpi0 = CosPi0Pprot = CosPi0Pneut =
               CosPprotPneut = -999.9;
 
   float proton_highmom = -999.9;
   float neutron_highmom = -999.9;
   float piplus_highmom = -999.9;
   float pineg_highmom = -999.9;
   float pi0_highmom = -999.9;
 
   (*nu_4mom) = event->PartInfo(0)->fP;
 
   if (!liteMode) {
     (*pmu) = TLorentzVector(0, 0, 0, 0);
     (*ppip) = TLorentzVector(0, 0, 0, 0);
     (*ppim) = TLorentzVector(0, 0, 0, 0);
     (*ppi0) = TLorentzVector(0, 0, 0, 0);
     (*pprot) = TLorentzVector(0, 0, 0, 0);
     (*pneut) = TLorentzVector(0, 0, 0, 0);
   }
 
   Enu_true = nu_4mom->E();
   PDGnu = event->PartInfo(0)->fPID;
 
   bool cc = (abs(event->Mode) < 30);
   (void)cc;
 
   // Add all pion distributions for the event.
 
   // Add classifier for CC0pi or CC1pi or CCOther
   // Save Modes Properly
   // Save low recoil measurements
 
   // Start Particle Loop
   UInt_t npart = event->Npart();
   for (UInt_t i = 0; i < npart; i++) {
     // Skip particles that weren't in the final state
     bool part_alive = event->PartInfo(i)->fIsAlive and event->PartInfo(i)->Status() == kFinalState;
     if (!part_alive) continue;
 
     // PDG Particle
     int PDGpart = event->PartInfo(i)->fPID;
     TLorentzVector part_4mom = event->PartInfo(i)->fP;
 
     Nparticles++;
 
     // Get Charged Lepton
     if (PDGpart == 11){
       Nleptons++;
 
       PDGLep = PDGpart;
 
       TLep = FitUtils::T(part_4mom) * 1000.0;
       PLep = (part_4mom.Vect().Mag());
       ELep = (part_4mom.E());
       MLep = (part_4mom.Mag());
       CosLep = cos(part_4mom.Vect().Angle(nu_4mom->Vect()));
       pmu = &part_4mom;
 
       Q2_true = -1 * (part_4mom - (*nu_4mom)).Mag2();
 
       float ThetaLep = (event->PartInfo(0))
                            ->fP.Vect()
                            .Angle((event->PartInfo(i))->fP.Vect());
 
       q0_true = (part_4mom - (*nu_4mom)).E();
       q3_true = (part_4mom - (*nu_4mom)).Vect().Mag();
 
       // Get W_true with assumption of initial state nucleon at rest
       float m_n = (float)PhysConst::mass_proton * 1000.;
       W_nuc_rest = sqrt(-Q2_true + 2 * m_n * (Enu_true - ELep) + m_n * m_n);
 
       // Get the Bjorken x and y variables
       // Assume that E_had = Enu - Emu as in MINERvA
       bjorken_x = Q2_true / (2 * m_n * (Enu_true - ELep));
       bjorken_y = 1 - ELep / Enu_true;
 
       // Quasi-elastic ----------------------
       // ------------------------------------
 
       // Q2 QE Assuming Carbon Input. Should change this to be dynamic soon.
       Q2_QE =
           FitUtils::Q2QErec(part_4mom, cos(ThetaLep), 34., true) * 1000000.0;
       Enu_QE = FitUtils::EnuQErec(part_4mom, cos(ThetaLep), 34., true) * 1000.0;
 
       // Pion Production ----------------------
       // --------------------------------------
 
     } else if (PDGpart == 2212) {
       Nprotons++;
       if (part_4mom.Vect().Mag() > proton_highmom) {
         proton_highmom = part_4mom.Vect().Mag();
 
         PPr = (part_4mom.Vect().Mag());
         EPr = (part_4mom.E());
         TPr = FitUtils::T(part_4mom) * 1000.;
         MPr = (part_4mom.Mag());
         CosPr = cos(part_4mom.Vect().Angle(nu_4mom->Vect()));
 
         (*pprot) = part_4mom;
       }
     } else if (PDGpart == 2112) {
       Nneutrons++;
       if (part_4mom.Vect().Mag() > neutron_highmom) {
         neutron_highmom = part_4mom.Vect().Mag();
 
         PNe = (part_4mom.Vect().Mag());
         ENe = (part_4mom.E());
         TNe = FitUtils::T(part_4mom) * 1000.;
         MNe = (part_4mom.Mag());
         CosNe = cos(part_4mom.Vect().Angle(nu_4mom->Vect()));
 
         (*pneut) = part_4mom;
       }
     } else if (PDGpart == 211) {
       Npiplus++;
       if (part_4mom.Vect().Mag() > piplus_highmom) {
         piplus_highmom = part_4mom.Vect().Mag();
 
         PPiP = (part_4mom.Vect().Mag());
         EPiP = (part_4mom.E());
         TPiP = FitUtils::T(part_4mom) * 1000.;
         MPiP = (part_4mom.Mag());
         CosPiP = cos(part_4mom.Vect().Angle(nu_4mom->Vect()));
 
         (*ppip) = part_4mom;
       }
     } else if (PDGpart == -211) {
       Npineg++;
       if (part_4mom.Vect().Mag() > pineg_highmom) {
         pineg_highmom = part_4mom.Vect().Mag();
 
         PPiN = (part_4mom.Vect().Mag());
         EPiN = (part_4mom.E());
         TPiN = FitUtils::T(part_4mom) * 1000.;
         MPiN = (part_4mom.Mag());
         CosPiN = cos(part_4mom.Vect().Angle(nu_4mom->Vect()));
 
         (*ppim) = part_4mom;
       }
     } else if (PDGpart == 111) {
       Npi0++;
       if (part_4mom.Vect().Mag() > pi0_highmom) {
         pi0_highmom = part_4mom.Vect().Mag();
 
         PPi0 = (part_4mom.Vect().Mag());
         EPi0 = (part_4mom.E());
         TPi0 = FitUtils::T(part_4mom) * 1000.;
         MPi0 = (part_4mom.Mag());
         CosPi0 = cos(part_4mom.Vect().Angle(nu_4mom->Vect()));
 
         (*ppi0) = part_4mom;
       }
     } else {
       Nother++;
     }
   }
 
   // Get Recoil Definitions ------
   // -----------------------------
   Erecoil_true = FitUtils::GetErecoil_TRUE(event);
   Erecoil_charged = FitUtils::GetErecoil_CHARGED(event);
   Erecoil_minerva = FitUtils::GetErecoil_MINERvA_LowRecoil(event);
 
   // Do the angles between final state particles
   if (Nleptons > 0 && Npiplus > 0)
     CosPmuPpip = cos(pmu->Vect().Angle(ppip->Vect()));
   if (Nleptons > 0 && Npineg > 0)
     CosPmuPpim = cos(pmu->Vect().Angle(ppim->Vect()));
   if (Nleptons > 0 && Npi0 > 0)
     CosPmuPpi0 = cos(pmu->Vect().Angle(ppi0->Vect()));
   if (Nleptons > 0 && Nprotons > 0)
     CosPmuPprot = cos(pmu->Vect().Angle(pprot->Vect()));
   if (Nleptons > 0 && Nneutrons > 0)
     CosPmuPneut = cos(pmu->Vect().Angle(pneut->Vect()));
 
   if (Npiplus > 0 && Nprotons > 0)
     CosPpipPprot = cos(ppip->Vect().Angle(pprot->Vect()));
   if (Npiplus > 0 && Nneutrons > 0)
     CosPpipPneut = cos(ppip->Vect().Angle(pneut->Vect()));
   if (Npiplus > 0 && Npineg > 0)
     CosPpipPpim = cos(ppip->Vect().Angle(ppim->Vect()));
   if (Npiplus > 0 && Npi0 > 0)
     CosPpipPpi0 = cos(ppip->Vect().Angle(ppi0->Vect()));
 
   if (Npineg > 0 && Nprotons > 0)
     CosPpimPprot = cos(ppim->Vect().Angle(pprot->Vect()));
   if (Npineg > 0 && Nneutrons > 0)
     CosPpimPneut = cos(ppim->Vect().Angle(pneut->Vect()));
   if (Npineg > 0 && Npi0 > 0)
     CosPpimPpi0 = cos(ppim->Vect().Angle(ppi0->Vect()));
 
   if (Npi0 > 0 && Nprotons > 0)
     CosPi0Pprot = cos(ppi0->Vect().Angle(pprot->Vect()));
   if (Npi0 > 0 && Nneutrons > 0)
     CosPi0Pneut = cos(ppi0->Vect().Angle(pneut->Vect()));
 
   if (Nprotons > 0 && Nneutrons > 0)
     CosPprotPneut = cos(pprot->Vect().Angle(pneut->Vect()));
 
   // Event Weights ----
   // ------------------
   Weight = event->RWWeight * event->InputWeight;
   RWWeight = event->RWWeight;
   InputWeight = event->InputWeight;
   FluxWeight =
       GetFluxHistogram()->GetBinContent(GetFluxHistogram()->FindBin(Enu)) / GetFluxHistogram()->Integral();
 
   xsecScaling = fScaleFactor;
 
   if (fScaleFactor <= 0.0) {
     ERR(WRN) << "SCALE FACTOR TOO LOW " << std::endl;
     sleep(20);
   }
 
   // Fill the eventVariables Tree
   eventVariables->Fill();
   return;
 };
 
 //********************************************************************
 void ElectronFlux_FlatTree::Write(std::string drawOpt) {
   //********************************************************************
 
   // First save the TTree
   eventVariables->Write();
 
   // Save Flux and Event Histograms too
   GetInput()->GetFluxHistogram()->Write();
   GetInput()->GetEventHistogram()->Write();
 
   return;
 }
 
 //********************************************************************
 void ElectronFlux_FlatTree::FillSignalFlags(FitEvent *event) {
   //********************************************************************
 
   // Some example flags are given from SignalDef.
   // See src/Utils/SignalDef.cxx for more.
   int nuPDG = event->PartInfo(0)->fPID;
 
   // Generic signal flags
   flagCCINC = SignalDef::isCCINC(event, nuPDG);
   flagNCINC = SignalDef::isNCINC(event, nuPDG);
   flagCCQE = SignalDef::isCCQE(event, nuPDG);
   flagCCQELike = SignalDef::isCCQELike(event, nuPDG);
   flagCC0pi = SignalDef::isCC0pi(event, nuPDG);
   flagNCEL = SignalDef::isNCEL(event, nuPDG);
   flagNC0pi = SignalDef::isNC0pi(event, nuPDG);
   flagCCcoh = SignalDef::isCCCOH(event, nuPDG, 211);
   flagNCcoh = SignalDef::isNCCOH(event, nuPDG, 111);
   flagCC1pip = SignalDef::isCC1pi(event, nuPDG, 211);
   flagNC1pip = SignalDef::isNC1pi(event, nuPDG, 211);
   flagCC1pim = SignalDef::isCC1pi(event, nuPDG, -211);
   flagNC1pim = SignalDef::isNC1pi(event, nuPDG, -211);
   flagCC1pi0 = SignalDef::isCC1pi(event, nuPDG, 111);
   flagNC1pi0 = SignalDef::isNC1pi(event, nuPDG, 111);
 }
 
 // -------------------------------------------------------------------
 // Purely MC Plot
 // Following functions are just overrides to handle this
 // -------------------------------------------------------------------
 //********************************************************************
 /// Everything is classed as signal...
 bool ElectronFlux_FlatTree::isSignal(FitEvent *event) {
   //********************************************************************
   (void)event;
   return true;
 };
 
 //********************************************************************
 void ElectronFlux_FlatTree::ScaleEvents() {
   //********************************************************************
   // Saving everything to a TTree so no scaling required
   return;
 }
 
 //********************************************************************
 void ElectronFlux_FlatTree::ApplyNormScale(float norm) {
   //********************************************************************
 
   // Saving everything to a TTree so no scaling required
   this->fCurrentNorm = norm;
   return;
 }
 
 //********************************************************************
 void ElectronFlux_FlatTree::FillHistograms() {
   //********************************************************************
   // No Histograms need filling........
   return;
 }
 
 //********************************************************************
 void ElectronFlux_FlatTree::ResetAll() {
   //********************************************************************
   eventVariables->Reset();
   return;
 }
 
 //********************************************************************
 float ElectronFlux_FlatTree::GetChi2() {
   //********************************************************************
   // No Likelihood to test, purely MC
   return 0.0;
 }
diff --git a/src/MCStudies/GenericFlux_Tester.cxx b/src/MCStudies/GenericFlux_Tester.cxx
index a98932e..e3383b5 100644
--- a/src/MCStudies/GenericFlux_Tester.cxx
+++ b/src/MCStudies/GenericFlux_Tester.cxx
@@ -1,559 +1,559 @@
 // Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret
 
 /*******************************************************************************
 *    This file is part of NUISANCE.
 *
 *    NUISANCE is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    NUISANCE is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with NUISANCE.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
 
 #include "GenericFlux_Tester.h"
 
 //********************************************************************
 /// @brief Class to perform MC Studies on a custom measurement
 GenericFlux_Tester::GenericFlux_Tester(std::string name, std::string inputfile,
                                        FitWeight *rw, std::string type,
                                        std::string fakeDataFile) {
   //********************************************************************
 
   // Measurement Details
   fName = name;
   eventVariables = NULL;
 
   // Define our energy range for flux calcs
   EnuMin = 0.;
   EnuMax = 100.;  // Arbritrarily high energy limit
 
   // Set default fitter flags
   fIsDiag = true;
   fIsShape = false;
   fIsRawEvents = false;
 
   nu_4mom = new TLorentzVector(0, 0, 0, 0);
   pmu = new TLorentzVector(0, 0, 0, 0);
   ppip = new TLorentzVector(0, 0, 0, 0);
   ppim = new TLorentzVector(0, 0, 0, 0);
   ppi0 = new TLorentzVector(0, 0, 0, 0);
   pprot = new TLorentzVector(0, 0, 0, 0);
   pneut = new TLorentzVector(0, 0, 0, 0);
 
   // This function will sort out the input files automatically and parse all the
   // inputs,flags,etc.
   // There may be complex cases where you have to do this by hand, but usually
   // this will do.
   Measurement1D::SetupMeasurement(inputfile, type, rw, fakeDataFile);
 
   eventVariables = NULL;
   liteMode = FitPar::Config().GetParB("isLiteMode");
 
   // Setup fDataHist as a placeholder
   this->fDataHist = new TH1D(("empty_data"), ("empty-data"), 1, 0, 1);
   this->SetupDefaultHist();
   fFullCovar = StatUtils::MakeDiagonalCovarMatrix(fDataHist);
   covar = StatUtils::GetInvert(fFullCovar);
 
   // 1. The generator is organised in SetupMeasurement so it gives the
   // cross-section in "per nucleon" units.
   //    So some extra scaling for a specific measurement may be required. For
   //    Example to get a "per neutron" measurement on carbon
   //    which we do here, we have to multiple by the number of nucleons 12 and
   //    divide by the number of neutrons 6.
   this->fScaleFactor =
       (GetEventHistogram()->Integral("width") * 1E-38 / (fNEvents + 0.)) /
       this->TotalIntegratedFlux();
 
   LOG(SAM) << " Generic Flux Scaling Factor = " << fScaleFactor << std::endl;
 
   if (fScaleFactor <= 0.0) {
     ERR(WRN) << "SCALE FACTOR TOO LOW " << std::endl;
     sleep(20);
   }
 
   // Setup our TTrees
   this->AddEventVariablesToTree();
   this->AddSignalFlagsToTree();
 }
 
 void GenericFlux_Tester::AddEventVariablesToTree() {
   // Setup the TTree to save everything
   if (!eventVariables) {
-    FitPar::Config().out->cd();
+    Config::Get().out->cd();
     eventVariables = new TTree((this->fName + "_VARS").c_str(),
                                (this->fName + "_VARS").c_str());
   }
 
   LOG(SAM) << "Adding Event Variables" << std::endl;
   eventVariables->Branch("Mode", &Mode, "Mode/I");
 
   eventVariables->Branch("PDGnu", &PDGnu, "PDGnu/I");
   eventVariables->Branch("Enu_true", &Enu_true, "Enu_true/F");
 
   eventVariables->Branch("Nleptons", &Nleptons, "Nleptons/I");
   eventVariables->Branch("MLep", &MLep, "MLep/F");
   eventVariables->Branch("ELep", &ELep, "ELep/F");
   eventVariables->Branch("TLep", &TLep, "TLep/F");
   eventVariables->Branch("CosLep", &CosLep, "CosLep/F");
   eventVariables->Branch("CosPmuPpip", &CosPmuPpip, "CosPmuPpip/F");
   eventVariables->Branch("CosPmuPpim", &CosPmuPpim, "CosPmuPpim/F");
   eventVariables->Branch("CosPmuPpi0", &CosPmuPpi0, "CosPmuPpi0/F");
   eventVariables->Branch("CosPmuPprot", &CosPmuPprot, "CosPmuPprot/F");
   eventVariables->Branch("CosPmuPneut", &CosPmuPneut, "CosPmuPneut/F");
 
   eventVariables->Branch("Nprotons", &Nprotons, "Nprotons/I");
   eventVariables->Branch("MPr", &MPr, "MPr/F");
   eventVariables->Branch("EPr", &EPr, "EPr/F");
   eventVariables->Branch("TPr", &TPr, "TPr/F");
   eventVariables->Branch("CosPr", &CosPr, "CosPr/F");
   eventVariables->Branch("CosPprotPneut", &CosPprotPneut, "CosPprotPneut/F");
 
   eventVariables->Branch("Nneutrons", &Nneutrons, "Nneutrons/I");
   eventVariables->Branch("MNe", &MNe, "MNe/F");
   eventVariables->Branch("ENe", &ENe, "ENe/F");
   eventVariables->Branch("TNe", &TNe, "TNe/F");
   eventVariables->Branch("CosNe", &CosNe, "CosNe/F");
 
   eventVariables->Branch("Npiplus", &Npiplus, "Npiplus/I");
   eventVariables->Branch("MPiP", &MPiP, "MPiP/F");
   eventVariables->Branch("EPiP", &EPiP, "EPiP/F");
   eventVariables->Branch("TPiP", &TPiP, "TPiP/F");
   eventVariables->Branch("CosPiP", &CosPiP, "CosPiP/F");
   eventVariables->Branch("CosPpipPprot", &CosPpipPprot, "CosPpipProt/F");
   eventVariables->Branch("CosPpipPneut", &CosPpipPneut, "CosPpipPneut/F");
   eventVariables->Branch("CosPpipPpim", &CosPpipPpim, "CosPpipPpim/F");
   eventVariables->Branch("CosPpipPpi0", &CosPpipPpi0, "CosPpipPpi0/F");
 
   eventVariables->Branch("Npineg", &Npineg, "Npineg/I");
   eventVariables->Branch("MPiN", &MPiN, "MPiN/F");
   eventVariables->Branch("EPiN", &EPiN, "EPiN/F");
   eventVariables->Branch("TPiN", &TPiN, "TPiN/F");
   eventVariables->Branch("CosPiN", &CosPiN, "CosPiN/F");
   eventVariables->Branch("CosPpimPprot", &CosPpimPprot, "CosPpimPprot/F");
   eventVariables->Branch("CosPpimPneut", &CosPpimPneut, "CosPpimPneut/F");
   eventVariables->Branch("CosPpimPpi0", &CosPpimPpi0, "CosPpimPpi0/F");
 
   eventVariables->Branch("Npi0", &Npi0, "Npi0/I");
   eventVariables->Branch("MPi0", &MPi0, "MPi0/F");
   eventVariables->Branch("EPi0", &EPi0, "EPi0/F");
   eventVariables->Branch("TPi0", &TPi0, "TPi0/F");
   eventVariables->Branch("CosPi0", &CosPi0, "CosPi0/F");
   eventVariables->Branch("CosPi0Pprot", &CosPi0Pprot, "CosPi0Pprot/F");
   eventVariables->Branch("CosPi0Pneut", &CosPi0Pneut, "CosPi0Pneut/F");
 
   eventVariables->Branch("Nother", &Nother, "Nother/I");
 
   eventVariables->Branch("Q2_true", &Q2_true, "Q2_true/F");
   eventVariables->Branch("q0_true", &q0_true, "q0_true/F");
   eventVariables->Branch("q3_true", &q3_true, "q3_true/F");
 
   eventVariables->Branch("Enu_QE", &Enu_QE, "Enu_QE/F");
   eventVariables->Branch("Q2_QE", &Q2_QE, "Q2_QE/F");
 
   eventVariables->Branch("W_nuc_rest", &W_nuc_rest, "W_nuc_rest/F");
   eventVariables->Branch("bjorken_x", &bjorken_x, "bjorken_x/F");
   eventVariables->Branch("bjorken_y", &bjorken_y, "bjorken_y/F");
 
   eventVariables->Branch("Erecoil_true", &Erecoil_true, "Erecoil_true/F");
   eventVariables->Branch("Erecoil_charged", &Erecoil_charged,
                          "Erecoil_charged/F");
   eventVariables->Branch("Erecoil_minerva", &Erecoil_minerva,
                          "Erecoil_minerva/F");
 
   if (!liteMode) {
     eventVariables->Branch("nu_4mom", &nu_4mom);
     eventVariables->Branch("pmu_4mom", &pmu);
     eventVariables->Branch("hm_ppip_4mom", &ppip);
     eventVariables->Branch("hm_ppim_4mom", &ppim);
     eventVariables->Branch("hm_ppi0_4mom", &ppi0);
     eventVariables->Branch("hm_pprot_4mom", &pprot);
     eventVariables->Branch("hm_pneut_4mom", &pneut);
   }
 
   // Event Scaling Information
   eventVariables->Branch("Weight", &Weight, "Weight/F");
   eventVariables->Branch("InputWeight", &InputWeight, "InputWeight/F");
   eventVariables->Branch("RWWeight", &RWWeight, "RWWeight/F");
   eventVariables->Branch("FluxWeight", &FluxWeight, "FluxWeight/F");
   eventVariables->Branch("fScaleFactor", &fScaleFactor, "fScaleFactor/D");
 
   return;
 }
 
 void GenericFlux_Tester::AddSignalFlagsToTree() {
   if (!eventVariables) {
-    FitPar::Config().out->cd();
+    Config::Get().out->cd();
     eventVariables = new TTree((this->fName + "_VARS").c_str(),
                                (this->fName + "_VARS").c_str());
   }
 
   LOG(SAM) << "Adding Samples" << std::endl;
 
   // Signal Definitions from SignalDef.cxx
   eventVariables->Branch("flagCCINC", &flagCCINC, "flagCCINC/O");
   eventVariables->Branch("flagNCINC", &flagNCINC, "flagNCINC/O");
   eventVariables->Branch("flagCCQE", &flagCCQE, "flagCCQE/O");
   eventVariables->Branch("flagCC0pi", &flagCC0pi, "flagCC0pi/O");
   eventVariables->Branch("flagCCQELike", &flagCCQELike, "flagCCQELike/O");
   eventVariables->Branch("flagNCEL", &flagNCEL, "flagNCEL/O");
   eventVariables->Branch("flagNC0pi", &flagNC0pi, "flagNC0pi/O");
   eventVariables->Branch("flagCCcoh", &flagCCcoh, "flagCCcoh/O");
   eventVariables->Branch("flagNCcoh", &flagNCcoh, "flagNCcoh/O");
   eventVariables->Branch("flagCC1pip", &flagCC1pip, "flagCC1pip/O");
   eventVariables->Branch("flagNC1pip", &flagNC1pip, "flagNC1pip/O");
   eventVariables->Branch("flagCC1pim", &flagCC1pim, "flagCC1pim/O");
   eventVariables->Branch("flagNC1pim", &flagNC1pim, "flagNC1pim/O");
   eventVariables->Branch("flagCC1pi0", &flagCC1pi0, "flagCC1pi0/O");
   eventVariables->Branch("flagNC1pi0", &flagNC1pi0, "flagNC1pi0/O");
 };
 
 //********************************************************************
 void GenericFlux_Tester::FillEventVariables(FitEvent *event) {
   //********************************************************************
 
   // Fill Signal Variables
   FillSignalFlags(event);
   LOG(DEB) << "Filling signal" << std::endl;
   // Function used to extract any variables of interest to the event
   Mode = event->Mode;
   Nleptons = 0;
   Nparticles = 0;
   PDGnu = 0;
   PDGLep = 0;
 
   Enu_true = Enu_QE = Q2_true = Q2_QE = TLep = TPr = TNe = TPiP = TPiN = TPi0 =
       -999.9;
 
   Nprotons = 0;
   PPr = EPr = MPr = CosPr = -999.9;
 
   Nneutrons = 0;
   PNe = ENe = MNe = CosNe = -999.9;
 
   Npiplus = 0;
   PPiP = EPiP = MPiP = CosPiP = -999.9;
 
   Npineg = 0;
   PPiN = EPiN = MPiN = CosPiN = -999.9;
 
   Npi0 = 0;
   PPi0 = EPi0 = MPi0 = CosPi0 = -999.9;
 
   // All of the angles Clarence added
   CosPmuPpip = CosPmuPpim = CosPmuPpi0 = CosPmuPprot = CosPmuPneut =
       CosPpipPprot = CosPpipPneut = CosPpipPpim = CosPpipPpi0 = CosPpimPprot =
           CosPpimPneut = CosPpimPpi0 = CosPi0Pprot = CosPi0Pneut =
               CosPprotPneut = -999.9;
 
   float proton_highmom = -999.9;
   float neutron_highmom = -999.9;
   float piplus_highmom = -999.9;
   float pineg_highmom = -999.9;
   float pi0_highmom = -999.9;
 
   (*nu_4mom) = event->PartInfo(0)->fP;
 
   if (!liteMode) {
     (*pmu) = TLorentzVector(0, 0, 0, 0);
     (*ppip) = TLorentzVector(0, 0, 0, 0);
     (*ppim) = TLorentzVector(0, 0, 0, 0);
     (*ppi0) = TLorentzVector(0, 0, 0, 0);
     (*pprot) = TLorentzVector(0, 0, 0, 0);
     (*pneut) = TLorentzVector(0, 0, 0, 0);
   }
 
   Enu_true = nu_4mom->E();
   PDGnu = event->PartInfo(0)->fPID;
 
   bool cc = (abs(event->Mode) < 30);
   (void)cc;
 
   // Add all pion distributions for the event.
 
   // Add classifier for CC0pi or CC1pi or CCOther
   // Save Modes Properly
   // Save low recoil measurements
 
   // Start Particle Loop
   UInt_t npart = event->Npart();
   for (UInt_t i = 0; i < npart; i++) {
     // Skip particles that weren't in the final state
     bool part_alive = event->PartInfo(i)->fIsAlive and event->PartInfo(i)->Status() == kFinalState;
     if (!part_alive) continue;
 
     // PDG Particle
     int PDGpart = event->PartInfo(i)->fPID;
     TLorentzVector part_4mom = event->PartInfo(i)->fP;
 
     Nparticles++;
 
     // Get Charged Lepton
     if (abs(PDGpart) == abs(PDGnu) - 1) {
       Nleptons++;
 
       PDGLep = PDGpart;
 
       TLep = FitUtils::T(part_4mom) * 1000.0;
       PLep = (part_4mom.Vect().Mag());
       ELep = (part_4mom.E());
       MLep = (part_4mom.Mag());
       CosLep = cos(part_4mom.Vect().Angle(nu_4mom->Vect()));
       (*pmu) = part_4mom;
 
       Q2_true = -1 * (part_4mom - (*nu_4mom)).Mag2();
 
       float ThetaLep = (event->PartInfo(0))
                            ->fP.Vect()
                            .Angle((event->PartInfo(i))->fP.Vect());
 
       q0_true = (part_4mom - (*nu_4mom)).E();
       q3_true = (part_4mom - (*nu_4mom)).Vect().Mag();
 
       // Get W_true with assumption of initial state nucleon at rest
       float m_n = (float)PhysConst::mass_proton * 1000.;
       W_nuc_rest = sqrt(-Q2_true + 2 * m_n * (Enu_true - ELep) + m_n * m_n);
 
       // Get the Bjorken x and y variables
       // Assume that E_had = Enu - Emu as in MINERvA
       bjorken_x = Q2_true / (2 * m_n * (Enu_true - ELep));
       bjorken_y = 1 - ELep / Enu_true;
 
       // Quasi-elastic ----------------------
       // ------------------------------------
 
       // Q2 QE Assuming Carbon Input. Should change this to be dynamic soon.
       Q2_QE =
           FitUtils::Q2QErec(part_4mom, cos(ThetaLep), 34., true) * 1000000.0;
       Enu_QE = FitUtils::EnuQErec(part_4mom, cos(ThetaLep), 34., true) * 1000.0;
 
       // Pion Production ----------------------
       // --------------------------------------
 
     } else if (PDGpart == 2212) {
       Nprotons++;
       if (part_4mom.Vect().Mag() > proton_highmom) {
         proton_highmom = part_4mom.Vect().Mag();
 
         PPr = (part_4mom.Vect().Mag());
         EPr = (part_4mom.E());
         TPr = FitUtils::T(part_4mom) * 1000.;
         MPr = (part_4mom.Mag());
         CosPr = cos(part_4mom.Vect().Angle(nu_4mom->Vect()));
 
         (*pprot) = part_4mom;
       }
     } else if (PDGpart == 2112) {
       Nneutrons++;
       if (part_4mom.Vect().Mag() > neutron_highmom) {
         neutron_highmom = part_4mom.Vect().Mag();
 
         PNe = (part_4mom.Vect().Mag());
         ENe = (part_4mom.E());
         TNe = FitUtils::T(part_4mom) * 1000.;
         MNe = (part_4mom.Mag());
         CosNe = cos(part_4mom.Vect().Angle(nu_4mom->Vect()));
 
         (*pneut) = part_4mom;
       }
     } else if (PDGpart == 211) {
       Npiplus++;
       if (part_4mom.Vect().Mag() > piplus_highmom) {
         piplus_highmom = part_4mom.Vect().Mag();
 
         PPiP = (part_4mom.Vect().Mag());
         EPiP = (part_4mom.E());
         TPiP = FitUtils::T(part_4mom) * 1000.;
         MPiP = (part_4mom.Mag());
         CosPiP = cos(part_4mom.Vect().Angle(nu_4mom->Vect()));
 
         (*ppip) = part_4mom;
       }
     } else if (PDGpart == -211) {
       Npineg++;
       if (part_4mom.Vect().Mag() > pineg_highmom) {
         pineg_highmom = part_4mom.Vect().Mag();
 
         PPiN = (part_4mom.Vect().Mag());
         EPiN = (part_4mom.E());
         TPiN = FitUtils::T(part_4mom) * 1000.;
         MPiN = (part_4mom.Mag());
         CosPiN = cos(part_4mom.Vect().Angle(nu_4mom->Vect()));
 
         (*ppim) = part_4mom;
       }
     } else if (PDGpart == 111) {
       Npi0++;
       if (part_4mom.Vect().Mag() > pi0_highmom) {
         pi0_highmom = part_4mom.Vect().Mag();
 
         PPi0 = (part_4mom.Vect().Mag());
         EPi0 = (part_4mom.E());
         TPi0 = FitUtils::T(part_4mom) * 1000.;
         MPi0 = (part_4mom.Mag());
         CosPi0 = cos(part_4mom.Vect().Angle(nu_4mom->Vect()));
 
         (*ppi0) = part_4mom;
       }
     } else {
       Nother++;
     }
   }
 
   // Get Recoil Definitions ------
   // -----------------------------
   Erecoil_true = FitUtils::GetErecoil_TRUE(event);
   Erecoil_charged = FitUtils::GetErecoil_CHARGED(event);
   Erecoil_minerva = FitUtils::GetErecoil_MINERvA_LowRecoil(event);
 
   // Do the angles between final state particles
   if (Nleptons > 0 && Npiplus > 0)
     CosPmuPpip = cos(pmu->Vect().Angle(ppip->Vect()));
   if (Nleptons > 0 && Npineg > 0)
     CosPmuPpim = cos(pmu->Vect().Angle(ppim->Vect()));
   if (Nleptons > 0 && Npi0 > 0)
     CosPmuPpi0 = cos(pmu->Vect().Angle(ppi0->Vect()));
   if (Nleptons > 0 && Nprotons > 0)
     CosPmuPprot = cos(pmu->Vect().Angle(pprot->Vect()));
   if (Nleptons > 0 && Nneutrons > 0)
     CosPmuPneut = cos(pmu->Vect().Angle(pneut->Vect()));
 
   if (Npiplus > 0 && Nprotons > 0)
     CosPpipPprot = cos(ppip->Vect().Angle(pprot->Vect()));
   if (Npiplus > 0 && Nneutrons > 0)
     CosPpipPneut = cos(ppip->Vect().Angle(pneut->Vect()));
   if (Npiplus > 0 && Npineg > 0)
     CosPpipPpim = cos(ppip->Vect().Angle(ppim->Vect()));
   if (Npiplus > 0 && Npi0 > 0)
     CosPpipPpi0 = cos(ppip->Vect().Angle(ppi0->Vect()));
 
   if (Npineg > 0 && Nprotons > 0)
     CosPpimPprot = cos(ppim->Vect().Angle(pprot->Vect()));
   if (Npineg > 0 && Nneutrons > 0)
     CosPpimPneut = cos(ppim->Vect().Angle(pneut->Vect()));
   if (Npineg > 0 && Npi0 > 0)
     CosPpimPpi0 = cos(ppim->Vect().Angle(ppi0->Vect()));
 
   if (Npi0 > 0 && Nprotons > 0)
     CosPi0Pprot = cos(ppi0->Vect().Angle(pprot->Vect()));
   if (Npi0 > 0 && Nneutrons > 0)
     CosPi0Pneut = cos(ppi0->Vect().Angle(pneut->Vect()));
 
   if (Nprotons > 0 && Nneutrons > 0)
     CosPprotPneut = cos(pprot->Vect().Angle(pneut->Vect()));
 
   // Event Weights ----
   // ------------------
   Weight = event->RWWeight * event->InputWeight;
   RWWeight = event->RWWeight;
   InputWeight = event->InputWeight;
   FluxWeight =
       GetFluxHistogram()->GetBinContent(GetFluxHistogram()->FindBin(Enu)) / GetFluxHistogram()->Integral();
 
   xsecScaling = fScaleFactor;
 
   if (fScaleFactor <= 0.0) {
     ERR(WRN) << "SCALE FACTOR TOO LOW " << std::endl;
     sleep(20);
   }
 
   // Fill the eventVariables Tree
   eventVariables->Fill();
   return;
 };
 
 //********************************************************************
 void GenericFlux_Tester::Write(std::string drawOpt) {
   //********************************************************************
 
   // First save the TTree
   eventVariables->Write();
 
   // Save Flux and Event Histograms too
   GetInput()->GetFluxHistogram()->Write();
   GetInput()->GetEventHistogram()->Write();
 
   return;
 }
 
 //********************************************************************
 void GenericFlux_Tester::FillSignalFlags(FitEvent *event) {
   //********************************************************************
 
   // Some example flags are given from SignalDef.
   // See src/Utils/SignalDef.cxx for more.
   int nuPDG = event->PartInfo(0)->fPID;
 
   // Generic signal flags
   flagCCINC = SignalDef::isCCINC(event, nuPDG);
   flagNCINC = SignalDef::isNCINC(event, nuPDG);
   flagCCQE = SignalDef::isCCQE(event, nuPDG);
   flagCCQELike = SignalDef::isCCQELike(event, nuPDG);
   flagCC0pi = SignalDef::isCC0pi(event, nuPDG);
   flagNCEL = SignalDef::isNCEL(event, nuPDG);
   flagNC0pi = SignalDef::isNC0pi(event, nuPDG);
   flagCCcoh = SignalDef::isCCCOH(event, nuPDG, 211);
   flagNCcoh = SignalDef::isNCCOH(event, nuPDG, 111);
   flagCC1pip = SignalDef::isCC1pi(event, nuPDG, 211);
   flagNC1pip = SignalDef::isNC1pi(event, nuPDG, 211);
   flagCC1pim = SignalDef::isCC1pi(event, nuPDG, -211);
   flagNC1pim = SignalDef::isNC1pi(event, nuPDG, -211);
   flagCC1pi0 = SignalDef::isCC1pi(event, nuPDG, 111);
   flagNC1pi0 = SignalDef::isNC1pi(event, nuPDG, 111);
 }
 
 // -------------------------------------------------------------------
 // Purely MC Plot
 // Following functions are just overrides to handle this
 // -------------------------------------------------------------------
 //********************************************************************
 /// Everything is classed as signal...
 bool GenericFlux_Tester::isSignal(FitEvent *event) {
   //********************************************************************
   (void)event;
   return true;
 };
 
 //********************************************************************
 void GenericFlux_Tester::ScaleEvents() {
   //********************************************************************
   // Saving everything to a TTree so no scaling required
   return;
 }
 
 //********************************************************************
 void GenericFlux_Tester::ApplyNormScale(float norm) {
   //********************************************************************
 
   // Saving everything to a TTree so no scaling required
   this->fCurrentNorm = norm;
   return;
 }
 
 //********************************************************************
 void GenericFlux_Tester::FillHistograms() {
   //********************************************************************
   // No Histograms need filling........
   return;
 }
 
 //********************************************************************
 void GenericFlux_Tester::ResetAll() {
   //********************************************************************
   eventVariables->Reset();
   return;
 }
 
 //********************************************************************
 float GenericFlux_Tester::GetChi2() {
   //********************************************************************
   // No Likelihood to test, purely MC
   return 0.0;
 }
diff --git a/src/MCStudies/GenericFlux_Vectors.cxx b/src/MCStudies/GenericFlux_Vectors.cxx
index e27e1e4..eb75ee7 100644
--- a/src/MCStudies/GenericFlux_Vectors.cxx
+++ b/src/MCStudies/GenericFlux_Vectors.cxx
@@ -1,237 +1,237 @@
 // Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret
 
 /*******************************************************************************
 *    This file is part of NUISANCE.
 *
 *    NUISANCE is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    NUISANCE is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with NUISANCE.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
 
 #include "GenericFlux_Vectors.h"
 
 GenericFlux_Vectors::GenericFlux_Vectors(std::string name, std::string inputfile,
                                        FitWeight *rw, std::string type,
                                        std::string fakeDataFile) {
   // Measurement Details
   fName = name;
   eventVariables = NULL;
 
   // Define our energy range for flux calcs
   EnuMin = 0.;
   EnuMax = 100.;  // Arbritrarily high energy limit
 
   // Set default fitter flags
   fIsDiag = true;
   fIsShape = false;
   fIsRawEvents = false;
 
   // This function will sort out the input files automatically and parse all the
   // inputs,flags,etc.
   // There may be complex cases where you have to do this by hand, but usually
   // this will do.
   Measurement1D::SetupMeasurement(inputfile, type, rw, fakeDataFile);
 
   eventVariables = NULL;
 
   // Setup fDataHist as a placeholder
   this->fDataHist = new TH1D(("empty_data"), ("empty-data"), 1, 0, 1);
   this->SetupDefaultHist();
   fFullCovar = StatUtils::MakeDiagonalCovarMatrix(fDataHist);
   covar = StatUtils::GetInvert(fFullCovar);
 
   // 1. The generator is organised in SetupMeasurement so it gives the
   // cross-section in "per nucleon" units.
   //    So some extra scaling for a specific measurement may be required. For
   //    Example to get a "per neutron" measurement on carbon
   //    which we do here, we have to multiple by the number of nucleons 12 and
   //    divide by the number of neutrons 6.
   this->fScaleFactor =
       (GetEventHistogram()->Integral("width") * 1E-38 / (fNEvents + 0.)) /
       this->TotalIntegratedFlux();
 
   LOG(SAM) << " Generic Flux Scaling Factor = " << fScaleFactor << std::endl;
 
   if (fScaleFactor <= 0.0) {
     ERR(WRN) << "SCALE FACTOR TOO LOW " << std::endl;
   }
 
   // Setup our TTrees
   this->AddEventVariablesToTree();
 }
 
 void GenericFlux_Vectors::AddEventVariablesToTree() {
   // Setup the TTree to save everything
   if (!eventVariables) {
-    FitPar::Config().out->cd();
+    Config::Get().out->cd();
     eventVariables = new TTree((this->fName + "_VARS").c_str(),
                                (this->fName + "_VARS").c_str());
   }
 
   LOG(SAM) << "Adding Event Variables" << std::endl;
 
   eventVariables->Branch("Mode",   &Mode,   "Mode/I"  );
   eventVariables->Branch("cc",     &cc,     "cc/B"    );
   eventVariables->Branch("PDGnu",  &PDGnu,  "PDGnu/I" );
   eventVariables->Branch("tgt",    &tgt,    "tgt/I"   );
   eventVariables->Branch("PDGLep", &PDGLep, "PDGLep/I");
   eventVariables->Branch("ELep",   &ELep,   "ELep/F"  );
   eventVariables->Branch("CosLep", &CosLep, "CosLep/F");
 
   // Basic interaction kinematics
   eventVariables->Branch("Q2",     &Q2,     "Q2/F");
   eventVariables->Branch("q0",     &q0,     "q0/F");
   eventVariables->Branch("q3",     &q3,     "q3/F");
   eventVariables->Branch("Enu_QE", &Enu_QE, "Enu_QE/F");
   eventVariables->Branch("Q2_QE",  &Q2_QE,  "Q2_QE/F");
   eventVariables->Branch("W_nuc_rest", &W_nuc_rest, "W_nuc_rest/F");
   eventVariables->Branch("W", 	   &W, 	    "W/F");
   eventVariables->Branch("x", 	   &x, 	    "x/F");
   eventVariables->Branch("y", 	   &y, 	    "y/F");
 
   // Save outgoing particle vectors
   eventVariables->Branch("nfsp", &nfsp, "nfsp/I");
   eventVariables->Branch("px",   px,    "px[nfsp]/F");
   eventVariables->Branch("py",   py,    "py[nfsp]/F");
   eventVariables->Branch("pz",   pz,    "pz[nfsp]/F");
   eventVariables->Branch("E",    E,     "E[nfsp]/F");
   eventVariables->Branch("pdg",  pdg,   "pdg[nfsp]/I");
 
   // Event Scaling Information
   eventVariables->Branch("Weight", &Weight, "Weight/F");
   eventVariables->Branch("InputWeight", &InputWeight, "InputWeight/F");
   eventVariables->Branch("RWWeight", &RWWeight, "RWWeight/F");
   eventVariables->Branch("fScaleFactor", &fScaleFactor, "fScaleFactor/F");
 
   return;
 }
 
 
 void GenericFlux_Vectors::FillEventVariables(FitEvent *event) {
 
   // Reset all Function used to extract any variables of interest to the event
   PDGnu = tgt = PDGLep = 0;
 
   Enu = ELep = CosLep = Q2 = q0 = q3 = Enu_QE = Q2_QE = W_nuc_rest = W = x = y =
       -999.9;
 
   nfsp = 0;
   for (int i = 0; i < kMAX; ++i){
     px[i] = py[i] = pz[i] = E[i] = -999;
     pdg[i] = 0;
-  } 
+  }
 
   Weight = InputWeight = RWWeight = 0;
 
   partList.clear();
 
   // Now fill the information
   Mode = event->Mode;
   cc = (abs(event->Mode) < 30);
 
   // Get the incoming neutrino and outgoing lepton
   FitParticle *nu  = event->GetNeutrinoIn();
   FitParticle *lep = event->GetHMFSAnyLepton();
-  
+
   PDGnu = nu->fPID;
   Enu = nu->fP.E()/1E3;
   tgt = event->fTargetPDG;
   PDGLep = lep->fPID;
   ELep = lep->fP.E()/1E3;
   CosLep = cos(nu->fP.Vect().Angle(lep->fP.Vect()));
 
   // Basic interaction kinematics
   Q2 = -1*(nu->fP - lep->fP).Mag2()/1E6;
   q0 = (nu->fP - lep->fP).E()/1E3;
   q3 = (nu->fP - lep->fP).Vect().Mag()/1E3;
 
-  // Get W_true with assumption of initial state nucleon at rest                                                                                                           
+  // Get W_true with assumption of initial state nucleon at rest
   float m_n = (float)PhysConst::mass_proton;
   W_nuc_rest = sqrt(-Q2 + 2 * m_n * q0 + m_n * m_n);
   W = sqrt(-Q2 + 2 * m_n * q0 + m_n * m_n);
   x = Q2/(2 * m_n * q0);
   y = 1 - ELep/Enu;
 
   // These assume C12 binding from MINERvA... not ideal
   Q2_QE  = FitUtils::Q2QErec(lep->fP, CosLep, 34., true);
   Enu_QE = FitUtils::EnuQErec(lep->fP, CosLep, 34., true);
 
   // Loop over the particles and store all the final state particles in a vector
   for (UInt_t i = 0; i < event->Npart(); ++i) {
 
     bool part_alive = event->PartInfo(i)->fIsAlive and event->PartInfo(i)->Status() == kFinalState;
     if (!part_alive) continue;
 
     partList .push_back(event->PartInfo(i));
   }
 
   // Save outgoing particle vectors
   nfsp = (int)partList.size();
 
   for (int i = 0; i < nfsp; ++i){
     px[i]  = partList[i]->fP.X()/1E3;
     py[i]  = partList[i]->fP.Y()/1E3;
     pz[i]  = partList[i]->fP.Z()/1E3;
     E[i]   = partList[i]->fP.E()/1E3;
     pdg[i] = partList[i]->fPID;
   }
 
   // Fill event weights
   Weight = event->RWWeight * event->InputWeight;
   RWWeight = event->RWWeight;
   InputWeight = event->InputWeight;
 
   // Fill the eventVariables Tree
   eventVariables->Fill();
   return;
 };
 
 void GenericFlux_Vectors::Write(std::string drawOpt) {
 
   // First save the TTree
   eventVariables->Write();
 
   // Save Flux and Event Histograms too
   GetInput()->GetFluxHistogram()->Write();
   GetInput()->GetEventHistogram()->Write();
 
   return;
 }
 
 
 // Override functions which aren't really necessary
 bool GenericFlux_Vectors::isSignal(FitEvent *event) {
   (void)event;
   return true;
 };
 
 void GenericFlux_Vectors::ScaleEvents() {
   return;
 }
 
 void GenericFlux_Vectors::ApplyNormScale(float norm) {
   this->fCurrentNorm = norm;
   return;
 }
 
 void GenericFlux_Vectors::FillHistograms() {
   return;
 }
 
 void GenericFlux_Vectors::ResetAll() {
   eventVariables->Reset();
   return;
 }
 
 float GenericFlux_Vectors::GetChi2() {
   return 0.0;
 }
diff --git a/src/MCStudies/MCStudy_CCQEHistograms.cxx b/src/MCStudies/MCStudy_CCQEHistograms.cxx
index bde660b..9a997f0 100644
--- a/src/MCStudies/MCStudy_CCQEHistograms.cxx
+++ b/src/MCStudies/MCStudy_CCQEHistograms.cxx
@@ -1,225 +1,230 @@
 // Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret
 
 /*******************************************************************************
 *    This file is part of NUISANCE.
 *
 *    NUISANCE is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    NUISANCE is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with NUISANCE.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
 
 #include "MCStudy_CCQEHistograms.h"
 
 #include "T2K_SignalDef.h"
 #include "MINERvA_SignalDef.h"
 
 //********************************************************************
 /// @brief Class to perform MC Studies on a custom measurement
 MCStudy_CCQEHistograms::MCStudy_CCQEHistograms(std::string name, std::string inputfile,
                                        FitWeight *rw, std::string type,
                                        std::string fakeDataFile) {
   //********************************************************************
 
   // Measurement Details
   fName = name;
   fEventTree = NULL;
 
   // Define our energy range for flux calcs
   EnuMin = 0.;
   EnuMax = 100.;  // Arbritrarily high energy limit
 
   // Set default fitter flags
   fIsDiag = true;
   fIsShape = false;
   fIsRawEvents = false;
 
   // This function will sort out the input files automatically and parse all the
   // inputs,flags,etc.
   // There may be complex cases where you have to do this by hand, but usually
   // this will do.
   Measurement1D::SetupMeasurement(inputfile, type, rw, fakeDataFile);
   fEventTree = NULL;
 
   // Setup fDataHist as a placeholder
   this->fDataHist = new TH1D(("approximate_data"), ("kaon_data"), 5, 1.0, 6.0);
-  
+
   this->SetupDefaultHist();
   fFullCovar = StatUtils::MakeDiagonalCovarMatrix(fDataHist);
   covar = StatUtils::GetInvert(fFullCovar);
 
   // 1. The generator is organised in SetupMeasurement so it gives the
   // cross-section in "per nucleon" units.
   //    So some extra scaling for a specific measurement may be required. For
   //    Example to get a "per neutron" measurement on carbon
   //    which we do here, we have to multiple by the number of nucleons 12 and
   //    divide by the number of neutrons 6.
   this->fScaleFactor = (this->fEventHist->Integral("width") * 1E-38 / (fNEvents + 0.)) /
     this->TotalIntegratedFlux();
-  
-  
+
+
   hist_Enu = new TH1D("MCStudy_CCQE_Enu","MCStudy_CCQE_Enu",30,0.0,2.0);
   hist_TLep = new TH1D("MCStudy_CCQE_TLep","MCStudy_CCQE_TLep",30,0.0,4.0);
   hist_CosLep = new TH1D("MCStudy_CCQE_CosLep","MCStudy_CCQE_CosLep",30,-1.0,1.0);
-  hist_Q2 = new TH1D("MCStudy_CCQE_Q2","MCStudy_CCQE_Q2",30,0.0,2.0);
-  hist_Q2QE = new TH1D("MCStudy_CCQE_Q2QE","MCStudy_CCQE_Q2QE",30,0.0,2.0);
+  hist_Q2 = new TH1D("MCStudy_CCQE_Q2;Q^{2} (GeV^{2});d#sigma/dQ^{2} (cm^{2}/nucleon/GeV^{2})","MCStudy_CCQE_Q2",30,0.0,3.0);
+  hist_Q2QE = new TH1D("MCStudy_CCQE_Q2QE","MCStudy_CCQE_Q2QE",30,0.0,3.0);
   hist_EQE = new TH1D("MCStudy_CCQE_EQE","MCStudy_CCQE_EQE",30,0.0,5.0);
   hist_q0 = new TH1D("MCStudy_CCQE_q0","MCStudy_CCQE_q0",30,0.0,2.0);
   hist_q3 = new TH1D("MCStudy_CCQE_q3","MCStudy_CCQE_q3",30,0.0,2.0);
   hist_TLepCosLep = new TH2D("MCStudy_CCQE_TLepCosLep","MCStudy_CCQE_TLepCosLep",15,0.0,5.0,15,-1.0,1.0);
   hist_Total = new TH1D("MCStudy_CCQE_TotalXSec","MXStudy_CCQE_TotalXSec",1,0.0,1.0);
 
+  hist_q0q3 = new TH2D("MCStudy_CCQE_q0q3","MCStudy_CCQE_q0q3;q_{3} (GeV); q_{0} (GeV); d#sigma/dq_{0}dq_{3} (cm^{2}/nucleon/GeV^{2})",40,0.0,2.0,40,0.0,2.0);
+
   return;
 }
 
 //********************************************************************
 void MCStudy_CCQEHistograms::FillEventVariables(FitEvent *event) {
 //********************************************************************
 
 //  std::cout << "Event fBound = " << event->fBound << " " << event->Mode << std::endl;
-  if (event->fBound > 0) return;
+//  if (event->fBound > 0) return;
   if (abs(event->Mode) != 1) return;
-  std::cout << "Event fBound = " << event->fBound << " " << event->Mode << "-> Signal " << std::endl;
+  //  std::cout << "Event fBound = " << event->fBound << " " << event->Mode << "-> Signal " << std::endl;
 
 
   FitParticle* muon = NULL;
   FitParticle* nu   = event->GetNeutrinoIn();
   bool IsNuMu = event->PDGnu() > 0;
-  
+
   if (IsNuMu)  muon = event->GetHMFSParticle(13);
   else muon = event->GetHMFSParticle(-13);
 
   // Reset Variables
   Enu    = -999.9;
   TLep   = -999.9;
   CosLep = -999.9;
   Q2     = -999.9;
   Q2QE   = -999.9;
   EQE    = -999.9;
   q0     = -999.9;
   q3     = -999.9;
 
   // Fill Variables
   if (muon){
 
     Enu = event->Enu() / 1.E3;
 
     TLep   = (muon->fP.E() - muon->fP.Mag()) / 1.E3;
-    CosLep = cos(muon->fP.Vect().Angle( nu->fP.Vect() )); 
+    CosLep = cos(muon->fP.Vect().Angle( nu->fP.Vect() ));
 
     Q2   = fabs((muon->fP - nu->fP).Mag2() / 1.E6);
 
     Q2QE = FitUtils::Q2QErec(muon->fP, CosLep, 34., IsNuMu);
     EQE  = FitUtils::EnuQErec(muon->fP, CosLep, 34., IsNuMu);
-    
+
     q0 = fabs((muon->fP - nu->fP).E()) / 1.E3;
     q3 = fabs((muon->fP - nu->fP).Vect().Mag()) / 1.E3;
 
     LocalRWWeight = event->RWWeight;
     LocalInputWeight = event->InputWeight;
-    
+
   }
 
   // Fill Tree
   if (abs(Mode) == 1 and Signal){
     hist_Enu->Fill(Enu,event->Weight);
     hist_TLep->Fill(TLep,event->Weight);
     hist_CosLep->Fill(CosLep,event->Weight);
     hist_Q2->Fill(Q2,event->Weight);
     hist_Q2QE->Fill(Q2QE,event->Weight);
     hist_EQE->Fill(EQE,event->Weight);
     hist_q0->Fill(q0,event->Weight);
     hist_q3->Fill(q3,event->Weight);
     hist_TLepCosLep->Fill(TLep,CosLep,event->Weight);
-
+    hist_q0q3->Fill(q3,q0,event->Weight);
     hist_Total->Fill(0.5,event->Weight);
-    
+
     fXVar = Q2;
   }
 
   return;
 };
 
 //********************************************************************
 void MCStudy_CCQEHistograms::Write(std::string drawOpt) {
 //********************************************************************
 //  Measurement1D::Write(drawOpt);
 
   LOG(FIT) << "Writing MCStudy_CCQEHistograms " << std::endl;
-  //  FitPar::Config().out->cd();
+  //  Config::Get().out->cd();
   hist_Enu->Write();
   hist_TLep->Write();
   hist_CosLep->Write();
   hist_Q2->Write();
   hist_Q2QE->Write();
   hist_EQE->Write();
   hist_q0->Write();
   hist_q3->Write();
   hist_TLepCosLep->Write();
+  hist_q0q3->Write();
   hist_Total->Write();
 
   return;
 }
 
-//********************************************************************                                                                                                                                 
+//********************************************************************
 void MCStudy_CCQEHistograms::ResetAll(){
-  //********************************************************************                                                                                                                                 
+  //********************************************************************
   hist_Enu->Reset();
   hist_TLep->Reset();
   hist_CosLep->Reset();
   hist_Q2->Reset();
   hist_Q2QE->Reset();
   hist_EQE->Reset();
   hist_q0->Reset();
   hist_q3->Reset();
+  hist_q0q3->Reset();
   hist_TLepCosLep->Reset();
   hist_Total->Reset();
 
   return;
 }
 
 
-//********************************************************************                                                                                                                     
+//********************************************************************
 void MCStudy_CCQEHistograms::ScaleEvents(){
-//********************************************************************                                                                                                                                
+//********************************************************************
 
   hist_Enu->Scale(fScaleFactor,"width");
   hist_TLep->Scale(fScaleFactor,"width");
   hist_CosLep->Scale(fScaleFactor,"width");
   hist_Q2->Scale(fScaleFactor,"width");
   hist_Q2QE->Scale(fScaleFactor,"width");
   hist_EQE->Scale(fScaleFactor,"width");
   hist_q0->Scale(fScaleFactor,"width");
   hist_q3->Scale(fScaleFactor,"width");
+  hist_q0q3->Scale(fScaleFactor,"width");
   hist_TLepCosLep->Scale(fScaleFactor,"width");
   hist_Total->Scale(fScaleFactor,"width");
 
   return;
 }
 
 
 
 //********************************************************************
 /// Select only events with final state Muons
 bool MCStudy_CCQEHistograms::isSignal(FitEvent *event) {
 //********************************************************************
 
 
   if (abs(event->Mode) != 1) return false;
-  if (event->fBound > 0) return false;
+  //if (event->fBound > 0) return false;
   //  if (!event->HasFSMuon()) return false;
-  
+
   // Do we want any other signal?
   return true;
 };
 
 
 
diff --git a/src/MCStudies/MCStudy_CCQEHistograms.h b/src/MCStudies/MCStudy_CCQEHistograms.h
index 455a9f2..4799ef3 100644
--- a/src/MCStudies/MCStudy_CCQEHistograms.h
+++ b/src/MCStudies/MCStudy_CCQEHistograms.h
@@ -1,75 +1,76 @@
 // Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret
 
 /*******************************************************************************
 *    This file is part of NUISANCE.
 *
 *    NUISANCE is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    NUISANCE is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with NUISANCE.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
 
 #ifndef MCStudy_CCQEHistograms_H_SEEN
 #define MCStudy_CCQEHistograms_H_SEEN
 #include "Measurement1D.h"
 
 //********************************************************************
 class MCStudy_CCQEHistograms : public Measurement1D {
 //********************************************************************
 
 public:
 
   MCStudy_CCQEHistograms(std::string name, std::string inputfile, FitWeight *rw, std::string type, std::string fakeDataFile);
   virtual ~MCStudy_CCQEHistograms() {};
 
   //! Grab info from event
   void FillEventVariables(FitEvent *event);
 
   void ScaleEvents();
   void ResetAll();
 
   //! Define this samples signal
   bool isSignal(FitEvent *nvect);
 
   //! Write Files
   void Write(std::string drawOpt);
 
  private:
   
   double fEventScaleFactor;
   TTree* fEventTree;
   TH1D* hist_Enu;
   float Enu;
   TH1D* hist_TLep;
   float TLep  ;
   TH1D* hist_CosLep;
   float CosLep;
   TH1D* hist_Q2;
   float Q2    ;
   TH1D* hist_Q2QE;
   float Q2QE  ;
   TH1D* hist_EQE;
   float EQE   ;
   TH1D* hist_q0;
   float q0    ;
   TH1D* hist_q3;
   float q3    ;
+  TH2D* hist_q0q3;
 
   TH1D* hist_Total;
   
   TH2D* hist_TLepCosLep;
 
   double LocalRWWeight;
   double LocalInputWeight;
 
 };
 
 #endif
diff --git a/src/MCStudies/MCStudy_KaonPreSelection.cxx b/src/MCStudies/MCStudy_KaonPreSelection.cxx
index adee159..8a0a53c 100644
--- a/src/MCStudies/MCStudy_KaonPreSelection.cxx
+++ b/src/MCStudies/MCStudy_KaonPreSelection.cxx
@@ -1,234 +1,234 @@
 // Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret
 
 /*******************************************************************************
 *    This file is part of NUISANCE.
 *
 *    NUISANCE is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    NUISANCE is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with NUISANCE.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
 
 #include "MCStudy_KaonPreSelection.h"
 
 #include "T2K_SignalDef.h"
 #include "MINERvA_SignalDef.h"
 
 //********************************************************************
 /// @brief Class to perform MC Studies on a custom measurement
 MCStudy_KaonPreSelection::MCStudy_KaonPreSelection(std::string name, std::string inputfile,
                                        FitWeight *rw, std::string type,
                                        std::string fakeDataFile) {
   //********************************************************************
 
   // Measurement Details
   fName = name;
   fEventTree = NULL;
 
   // Define our energy range for flux calcs
   EnuMin = 0.;
   EnuMax = 100.;  // Arbritrarily high energy limit
 
   // Set default fitter flags
   fIsDiag = true;
   fIsShape = false;
   fIsRawEvents = false;
 
   // This function will sort out the input files automatically and parse all the
   // inputs,flags,etc.
   // There may be complex cases where you have to do this by hand, but usually
   // this will do.
   Measurement1D::SetupMeasurement(inputfile, type, rw, fakeDataFile);
   fEventTree = NULL;
 
   // Setup fDataHist as a placeholder
   this->fDataHist = new TH1D(("approximate_data"), ("kaon_data"), 5, 1.0, 6.0);
 
   // Approximate data points for now
   fDataHist->SetBinContent(1,0.225E-39);
   fDataHist->SetBinContent(2,0.215E-39);
   fDataHist->SetBinContent(3,0.175E-39);
   fDataHist->SetBinContent(4,0.230E-39);
   fDataHist->SetBinContent(5,0.210E-39);
 
   this->SetupDefaultHist();
   fFullCovar = StatUtils::MakeDiagonalCovarMatrix(fDataHist);
   covar = StatUtils::GetInvert(fFullCovar);
 
   // 1. The generator is organised in SetupMeasurement so it gives the
   // cross-section in "per nucleon" units.
   //    So some extra scaling for a specific measurement may be required. For
   //    Example to get a "per neutron" measurement on carbon
   //    which we do here, we have to multiple by the number of nucleons 12 and
   //    divide by the number of neutrons 6.
   this->fScaleFactor = (GetEventHistogram()->Integral("width") * 1E-38 / (fNEvents + 0.)) /
     this->TotalIntegratedFlux();
 
   // Create a new TTree and add Nuisance Events Branches
-  FitPar::Config().out->cd();
+  Config::Get().out->cd();
   fEventTree = new TTree("nuisance_events","nuisance_events");
   GetInput()->GetNuisanceEvent(0)->AddBranchesToTree(fEventTree);
 
   fEventTree->Branch("nlep",&nlep, "nlep/I");
   fEventTree->Branch("nkplus",&nkplus, "nkplus/I");
   //fEventTree->Branch("nkaon",&nkaon, "nkaon/I");
   fEventTree->Branch("kplus_mom", &kplusmom, "kplus_mom/D");
   //  fEventTree->Branch("kaon_mom", &kaonmom, "kaon_mom/D");
 
   // Add Event Scaling Information
   // This scale factor is used to get the predicted event rate for this sample given
   // the input flux. Use this when merging different output event ttrees
   fEventTree->Branch("EventScaleFactor", &fEventScaleFactor, "EventScaleFactor/D");
   fEventScaleFactor = GetEventHistogram()->Integral("width") * 1E-38 / (fNEvents + 0.);
 
   // NOTES:
   // To get normalised predictions weight event event by 'EventScaleFactor' to get the
   // predicted event rate for that sample given the flux used. Then to get cross-sections
   // divide by the integrated flux from all samples.
   // e.g. To get the numu+numubar prediction, add the event rate predictions from both
   // samples together, then divide by the integral of the 'nuisance_flux' histograms in each
   // sample.
 
   // Every particle in the nuisance event is saved into the TTree. The list of particle
   // status codes are given in src/FitBase/FitParticle.h. The neutrino is usually the first
   // particle in the list.
   // If selecting final state kaons, select only kaons with state=2.
 
   /*
     enum particle_state{
     kUndefinedState = 5,
     kInitialState   = 0,
     kFSIState       = 1,
     kFinalState     = 2,
     kNuclearInitial = 3,
     kNuclearRemnant = 4
     };
   */
 
   // The structure of the particle lists are a dimensional array for each particle mom, then a 1D array
   // for the PDG and state. Mode gives the true NEUT interaction channel code.
   /*
     tn->Branch("Mode", &fMode, "Mode/I");
     tn->Branch("EventNo", &fEventNo, "EventNo/i");
     tn->Branch("TotCrs", &fTotCrs, "TotCrs/D");
     tn->Branch("TargetA", &fTargetA, "TargetA/I");
     tn->Branch("TargetH", &fTargetH, "TargetH/I");
     tn->Branch("Bound", &fBound, "Bound/O");
 
     tn->Branch("InputWeight", &InputWeight, "InputWeight/D");
 
     tn->Branch("NParticles", &fNParticles, "NParticles/I");
     tn->Branch("ParticleState", fParticleState, "ParticleState[NParticles]/i");
     tn->Branch("ParticlePDG", fParticlePDG, "ParticlePDG[NParticles]/I");
     tn->Branch("ParticleMom", fParticleMom, "ParticleMom[NParticles][4]/D");
   */
 
   // Logging Flag
   fKaonLogging = FitPar::Config().GetParB("KaonLogging");
 
   return;
 }
 
 //********************************************************************
 void MCStudy_KaonPreSelection::FillEventVariables(FitEvent *event) {
 //********************************************************************
-  
+
   // Reset
   kplusmom = -999.9;
 
   // Save Some Extra Information
   nkplus = event->NumFSParticle(PhysConst::pdg_kplus);
 
   // Nmuons
   nlep = event->NumFSParticle(13) + event->NumFSParticle(-13);
 
   // Leading K+ Mom
   if (event->GetHMFSParticle(PhysConst::pdg_kplus)){
     kplusmom = FitUtils::T(event->GetHMFSParticle(PhysConst::pdg_kplus)->fP)*1000.0;
   }
 
   // Fill XVar
   fXVar = kplusmom / 1.E3;
 
   // Fill If Signal
   if (isSignal(event)){
     fEventTree->Fill();
 
     if (fKaonLogging){
       int nstrangemesons = event->NumParticle(321);
       int nstrangefsmesons = event->NumFSParticle(321);
-      
+
       if (nstrangemesons > 0){
 	std::cout << "New Event ----------------------------" << std::endl;
 	std::cout << "N S Mesons vs NFS S Mesons : " << nstrangemesons << " : " << nstrangefsmesons << std::endl;
 	event->PrintChris();
 	event->fNeutVect->Dump();
       }
     }
   }
 
   return;
 };
 
 //********************************************************************
 void MCStudy_KaonPreSelection::Write(std::string drawOpt) {
 //********************************************************************
 
   // Save the event ttree
   fEventTree->Write();
 
   // Save Flux and Event Histograms too
   GetInput()->GetFluxHistogram()->Write("nuisance_fluxhist");
   GetInput()->GetEventHistogram()->Write("nuisance_eventhist");
 
   return;
 }
 
 
 //********************************************************************
 /// Select only events with final state Kaons
 bool MCStudy_KaonPreSelection::isSignal(FitEvent *event) {
 //********************************************************************
 
   // Update to include all events
   return true;
 
   // Apply a Kaon Pre-selection
   // Search for Strange Mesons (included full list from MC PDG)
 
   /*
   PhystConst::pdg_strangemesons = {130,310,311,321,
 				   9000311,9000321,
 				   10311,10321,100311,100321,
 				   9010311,9010321,9020311,9020321,
 				   313,323,
 				   10313,10323,
 				   20313,20323,
 				   100313,100323,
 				   9000313,9000323,
 				   30313,30323,
 				   315,325,
 				   9000315,9000325,
 				   10315,10325,
 				   20315,20325,
 				   9010315,9010325,9020315,9020325,
 				   317,327,
 				   9010317,9010327};
   PhysConst::pdg_antistrangemesons = {above * -1.0};
   */
   int nstrangemesons = event->NumParticle(PhysConst::pdg_strangemesons);
   nstrangemesons += event->NumParticle(PhysConst::pdg_antistrangemesons);
   if (nstrangemesons < 1) return false;
 
   // Do we want any other signal?
   return true;
 };
 
diff --git a/src/MCStudies/MCStudy_MuonValidation.cxx b/src/MCStudies/MCStudy_MuonValidation.cxx
index 2b85815..6ad9a9b 100644
--- a/src/MCStudies/MCStudy_MuonValidation.cxx
+++ b/src/MCStudies/MCStudy_MuonValidation.cxx
@@ -1,167 +1,167 @@
 // Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret
 
 /*******************************************************************************
 *    This file is part of NUISANCE.
 *
 *    NUISANCE is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    NUISANCE is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with NUISANCE.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
 
 #include "MCStudy_MuonValidation.h"
 
 #include "T2K_SignalDef.h"
 #include "MINERvA_SignalDef.h"
 
 //********************************************************************
 /// @brief Class to perform MC Studies on a custom measurement
 MCStudy_MuonValidation::MCStudy_MuonValidation(std::string name, std::string inputfile,
                                        FitWeight *rw, std::string type,
                                        std::string fakeDataFile) {
   //********************************************************************
 
   // Measurement Details
   fName = name;
   fEventTree = NULL;
 
   // Define our energy range for flux calcs
   EnuMin = 0.;
   EnuMax = 100.;  // Arbritrarily high energy limit
 
   // Set default fitter flags
   fIsDiag = true;
   fIsShape = false;
   fIsRawEvents = false;
 
   // This function will sort out the input files automatically and parse all the
   // inputs,flags,etc.
   // There may be complex cases where you have to do this by hand, but usually
   // this will do.
   Measurement1D::SetupMeasurement(inputfile, type, rw, fakeDataFile);
   fEventTree = NULL;
 
   // Setup fDataHist as a placeholder
   this->fDataHist = new TH1D(("approximate_data"), ("kaon_data"), 5, 1.0, 6.0);
 
   this->SetupDefaultHist();
   fFullCovar = StatUtils::MakeDiagonalCovarMatrix(fDataHist);
   covar = StatUtils::GetInvert(fFullCovar);
 
   // 1. The generator is organised in SetupMeasurement so it gives the
   // cross-section in "per nucleon" units.
   //    So some extra scaling for a specific measurement may be required. For
   //    Example to get a "per neutron" measurement on carbon
   //    which we do here, we have to multiple by the number of nucleons 12 and
   //    divide by the number of neutrons 6.
   this->fScaleFactor = (GetEventHistogram()->Integral("width") * 1E-38 / (fNEvents + 0.)) /
     this->TotalIntegratedFlux();
 
   // Create a new TTree and add Nuisance Events Branches
-  FitPar::Config().out->cd();
+  Config::Get().out->cd();
   fEventTree = new TTree((fName + "_EVENTS").c_str(),(fName + "_EVENTS").c_str());
 
   fEventTree->Branch("ScaleFactor", &fScaleFactor, "ScaleFactor/D");
   fEventTree->Branch("InputWeight", &LocalInputWeight, "InputWeight/D");
   fEventTree->Branch("RWWeight", &LocalRWWeight, "RWWeight/D");
   fEventTree->Branch("Mode", &Mode, "Mode/I");
   fEventTree->Branch("Enu",&Enu,"Enu/F");
   fEventTree->Branch("TLep",&TLep,"TLep/F");
   fEventTree->Branch("CosLep",&CosLep,"CosLep/F");
   fEventTree->Branch("Q2",&Q2,"Q2/F");
   fEventTree->Branch("Q2QE",&Q2QE,"Q2QE/F");
   fEventTree->Branch("EQE",&EQE,"EQE/F");
   fEventTree->Branch("q0",&q0,"q0/F");
   fEventTree->Branch("q3",&q3,"q3/F");
 
   // the input flux. Use this when merging different output event ttrees
   fEventTree->Branch("EventScaleFactor", &fEventScaleFactor, "EventScaleFactor/D");
   fEventScaleFactor = GetEventHistogram()->Integral("width") * 1E-38 / (fNEvents + 0.);
 
   return;
 }
 
 //********************************************************************
 void MCStudy_MuonValidation::FillEventVariables(FitEvent *event) {
 //********************************************************************
 
   FitParticle* muon = NULL;
   FitParticle* nu   = event->GetNeutrinoIn();
   bool IsNuMu = event->PDGnu() > 0;
 
   if (IsNuMu)  muon = event->GetHMFSParticle(13);
   else muon = event->GetHMFSParticle(-13);
 
   // Reset Variables
   Enu    = -999.9;
   TLep   = -999.9;
   CosLep = -999.9;
   Q2     = -999.9;
   Q2QE   = -999.9;
   EQE    = -999.9;
   q0     = -999.9;
   q3     = -999.9;
 
   // Fill Variables
   if (muon){
 
     Enu = event->Enu() / 1.E3;
 
     TLep   = (muon->fP.E() - muon->fP.Mag()) / 1.E3;
     CosLep = cos(muon->fP.Vect().Angle( nu->fP.Vect() ));
 
     Q2   = fabs((muon->fP - nu->fP).Mag2() / 1.E6);
 
     Q2QE = FitUtils::Q2QErec(muon->fP, CosLep, 34., IsNuMu);
     EQE  = FitUtils::EnuQErec(muon->fP, CosLep, 34., IsNuMu);
 
     q0 = fabs((muon->fP - nu->fP).E()) / 1.E3;
     q3 = fabs((muon->fP - nu->fP).Vect().Mag()) / 1.E3;
 
     LocalRWWeight = event->RWWeight;
     LocalInputWeight = event->InputWeight;
 
   }
 
   // Fill Tree
   if (isSignal(event)){
     fEventTree->Fill();
   }
 
   return;
 };
 
 //********************************************************************
 void MCStudy_MuonValidation::Write(std::string drawOpt) {
 //********************************************************************
 
   // Save the event ttree
   fEventTree->Write();
 
   // Save Flux and Event Histograms too
   GetInput()->GetFluxHistogram()->Write((fName + "_FLUX").c_str());
   GetInput()->GetEventHistogram()->Write((fName + "_EVT").c_str());
 
   return;
 }
 
 
 //********************************************************************
 /// Select only events with final state Muons
 bool MCStudy_MuonValidation::isSignal(FitEvent *event) {
 //********************************************************************
 
   if (!event->HasFSMuon()) return false;
 
   // Do we want any other signal?
   return true;
 };
 
diff --git a/src/MCStudies/MCStudy_NCpi0PreSelection.cxx b/src/MCStudies/MCStudy_NCpi0PreSelection.cxx
index 424d5d1..9d5d3ed 100644
--- a/src/MCStudies/MCStudy_NCpi0PreSelection.cxx
+++ b/src/MCStudies/MCStudy_NCpi0PreSelection.cxx
@@ -1,215 +1,215 @@
 // Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret
 
 /*******************************************************************************
 *    This file is part of NUISANCE.
 *
 *    NUISANCE is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    NUISANCE is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with NUISANCE.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
 
 #include "MCStudy_NCpi0PreSelection.h"
 
 #include "T2K_SignalDef.h"
 #include "MINERvA_SignalDef.h"
 
 //********************************************************************
 /// @brief Class to perform MC Studies on a custom measurement
 MCStudy_NCpi0PreSelection::MCStudy_NCpi0PreSelection(std::string name, std::string inputfile,
                                        FitWeight *rw, std::string type,
                                        std::string fakeDataFile) {
   //********************************************************************
 
   // Measurement Details
   fName = name;
   fEventTree = NULL;
 
   // Define our energy range for flux calcs
   EnuMin = 0.;
   EnuMax = 100.;  // Arbritrarily high energy limit
 
   // Set default fitter flags
   fIsDiag = true;
   fIsShape = false;
   fIsRawEvents = false;
 
   // This function will sort out the input files automatically and parse all the
   // inputs,flags,etc.
   // There may be complex cases where you have to do this by hand, but usually
   // this will do.
   Measurement1D::SetupMeasurement(inputfile, type, rw, fakeDataFile);
   fEventTree = NULL;
 
   // Setup fDataHist as a placeholder
   this->fDataHist = new TH1D(("approximate_data"), ("kaon_data"), 5, 1.0, 6.0);
 
   // Approximate data points for now
   fDataHist->SetBinContent(1,0.225E-39);
   fDataHist->SetBinContent(2,0.215E-39);
   fDataHist->SetBinContent(3,0.175E-39);
   fDataHist->SetBinContent(4,0.230E-39);
   fDataHist->SetBinContent(5,0.210E-39);
 
   this->SetupDefaultHist();
   fFullCovar = StatUtils::MakeDiagonalCovarMatrix(fDataHist);
   covar = StatUtils::GetInvert(fFullCovar);
 
   // 1. The generator is organised in SetupMeasurement so it gives the
   // cross-section in "per nucleon" units.
   //    So some extra scaling for a specific measurement may be required. For
   //    Example to get a "per neutron" measurement on carbon
   //    which we do here, we have to multiple by the number of nucleons 12 and
   //    divide by the number of neutrons 6.
   this->fScaleFactor = (GetEventHistogram()->Integral("width") * 1E-38 / (fNEvents + 0.)) /
     this->TotalIntegratedFlux();
 
   // Create a new TTree and add Nuisance Events Branches
-  FitPar::Config().out->cd();
+  Config::Get().out->cd();
   fEventTree = new TTree("nuisance_events","nuisance_events");
   GetInput()->GetEventPointer()->AddBranchesToTree(fEventTree);
 
   fEventTree->Branch("nlep",&nlep, "nlep/I");
   fEventTree->Branch("nkplus",&nkplus, "nkplus/I");
   //fEventTree->Branch("nkaon",&nkaon, "nkaon/I");
   fEventTree->Branch("kplus_mom", &kplusmom, "kplus_mom/D");
   //  fEventTree->Branch("kaon_mom", &kaonmom, "kaon_mom/D");
 
   // Add Event Scaling Information
   // This scale factor is used to get the predicted event rate for this sample given
   // the input flux. Use this when merging different output event ttrees
   fEventTree->Branch("EventScaleFactor", &fEventScaleFactor, "EventScaleFactor/D");
   fEventScaleFactor = GetEventHistogram()->Integral("width") * 1E-38 / (fNEvents + 0.);
 
   // NOTES:
   // To get normalised predictions weight event event by 'EventScaleFactor' to get the
   // predicted event rate for that sample given the flux used. Then to get cross-sections
   // divide by the integrated flux from all samples.
   // e.g. To get the numu+numubar prediction, add the event rate predictions from both
   // samples together, then divide by the integral of the 'nuisance_flux' histograms in each
   // sample.
 
   // Every particle in the nuisance event is saved into the TTree. The list of particle
   // status codes are given in src/FitBase/FitParticle.h. The neutrino is usually the first
   // particle in the list.
   // If selecting final state kaons, select only kaons with state=2.
 
   /*
     enum particle_state{
     kUndefinedState = 5,
     kInitialState   = 0,
     kFSIState       = 1,
     kFinalState     = 2,
     kNuclearInitial = 3,
     kNuclearRemnant = 4
     };
   */
 
   // The structure of the particle lists are a dimensional array for each particle mom, then a 1D array
   // for the PDG and state. Mode gives the true NEUT interaction channel code.
   /*
     tn->Branch("Mode", &fMode, "Mode/I");
     tn->Branch("EventNo", &fEventNo, "EventNo/i");
     tn->Branch("TotCrs", &fTotCrs, "TotCrs/D");
     tn->Branch("TargetA", &fTargetA, "TargetA/I");
     tn->Branch("TargetH", &fTargetH, "TargetH/I");
     tn->Branch("Bound", &fBound, "Bound/O");
 
     tn->Branch("InputWeight", &InputWeight, "InputWeight/D");
 
     tn->Branch("NParticles", &fNParticles, "NParticles/I");
     tn->Branch("ParticleState", fParticleState, "ParticleState[NParticles]/i");
     tn->Branch("ParticlePDG", fParticlePDG, "ParticlePDG[NParticles]/I");
     tn->Branch("ParticleMom", fParticleMom, "ParticleMom[NParticles][4]/D");
   */
 
   // Logging Flag
   fNCpi0Logging = FitPar::Config().GetParB("NCpi0Logging");
 
   return;
 }
 
 //********************************************************************
 void MCStudy_NCpi0PreSelection::FillEventVariables(FitEvent *event) {
 //********************************************************************
-  
+
   // Reset
   kplusmom = -999.9;
 
   // Save Some Extra Information
   nkplus = event->NumFSParticle(PhysConst::pdg_kplus);
 
   // Nmuons
   nlep = event->NumFSParticle(13) + event->NumFSParticle(-13);
 
   // Leading K+ Mom
   if (event->GetHMFSParticle(PhysConst::pdg_kplus)){
     kplusmom = FitUtils::T(event->GetHMFSParticle(PhysConst::pdg_kplus)->fP)*1000.0;
   }
 
   // Fill XVar
   fXVar = kplusmom / 1.E3;
 
   // Fill If Signal
   if (isSignal(event)){
 
     fEventTree->Fill();
     if (fNCpi0Logging){
       int nstrangemesons = event->NumParticle(321);
       int nstrangefsmesons = event->NumFSParticle(321);
-      
+
       if (nstrangemesons > 0){
 	std::cout << "New Event ----------------------------" << std::endl;
 	std::cout << "N S Mesons vs NFS S Mesons : " << nstrangemesons << " : " << nstrangefsmesons << std::endl;
 	event->PrintChris();
 	event->fNeutVect->Dump();
       }
     }
   }
 
   return;
 };
 
 
 //********************************************************************
 void MCStudy_NCpi0PreSelection::Write(std::string drawOpt) {
 //********************************************************************
 
   // Save the event ttree
   fEventTree->Write();
 
   // Save Flux and Event Histograms too
   GetInput()->GetFluxHistogram()->Write("nuisance_fluxhist");
   GetInput()->GetEventHistogram()->Write("nuisance_eventhist");
 
   return;
 }
 
 
 //********************************************************************
 /// Select only events with final state NCpi0s
 bool MCStudy_NCpi0PreSelection::isSignal(FitEvent *event) {
 //********************************************************************
 
   // Apply a NCpi0 Pre-selection
   // Search for Strange Mesons (included full list from MC PDG)
   int npi0 = event->NumParticle(111);
   if (npi0 <= 0) return false;
 
 
-  int nlep = (event->NumFSParticle(11) + event->NumFSParticle(13) + event->NumFSParticle(15) + 
+  int nlep = (event->NumFSParticle(11) + event->NumFSParticle(13) + event->NumFSParticle(15) +
 	      event->NumFSParticle(-11) + event->NumFSParticle(-13) + event->NumFSParticle(-15));
   if (nlep > 0) return false;
 
   // Do we want any other signal?
   return true;
 };
 
diff --git a/src/MCStudies/Smear_SVDUnfold_Propagation_Osc.cxx b/src/MCStudies/Smear_SVDUnfold_Propagation_Osc.cxx
index 67896da..7b6df60 100644
--- a/src/MCStudies/Smear_SVDUnfold_Propagation_Osc.cxx
+++ b/src/MCStudies/Smear_SVDUnfold_Propagation_Osc.cxx
@@ -1,823 +1,823 @@
 // Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret
 
 /*******************************************************************************
 *    This file is part of NUISANCE.
 *
 *    NUISANCE is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    NUISANCE is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with NUISANCE.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
 
 #include "Smear_SVDUnfold_Propagation_Osc.h"
 
 #include "SmearceptanceUtils.h"
 
 #include "OscWeightEngine.h"
 
 #include "HistogramInputHandler.h"
 
 void Smear_SVDUnfold_Propagation_Osc::AddNDInputs(nuiskey &samplekey) {
   NDSample nds;
 
   // Plot Setup -------------------------------------------------------
   // Check that we have the relevant near detector histograms specified.
 
   if (!NDSamples.size()) {  // If this is the first ND sample, take from the
                             // sample input
     InputHandlerBase *InputBase = GetInput();
     if (InputBase->GetType() != kHISTO) {
       THROW(
           "Smear_SVDUnfold_Propagation_Osc expects a Histogram input that "
           "contains the ND observed spectrum.");
     }
     HistoInputHandler *HInput = dynamic_cast<HistoInputHandler *>(InputBase);
     if (!HInput) {
       THROW(
           "Smear_SVDUnfold_Propagation_Osc expects a Histogram input that "
           "contains the ND observed spectrum.");
     }
     if (HInput->NHistograms() != 2) {
       THROW(
           "Input expected to contain 2 histograms. "
           "HISTO:input.root[NDObs_TH1D,NDSmear_TH2D]");
     }
     nds.NDDataHist = dynamic_cast<TH1D *>(HInput->GetHistogram(0));
     nds.NDToSpectrumSmearingMatrix =
         dynamic_cast<TH2D *>(HInput->GetHistogram(1));
 
     if (!nds.NDDataHist) {
       THROW("Expected a valid TH1D input for the ND observed spectrum.");
     }
 
     if (!nds.NDToSpectrumSmearingMatrix) {
       THROW("Expected a valid TH2D input for the ND observed smearing.");
     }
   } else {
     std::vector<TH1 *> NDObsInputs =
         PlotUtils::GetTH1sFromRootFile(samplekey.GetS("ObsInput"));
     if (NDObsInputs.size() < 2) {
       THROW(
           "Near detector sample must contain the observed ERec spectrum and "
           "the "
           "ND ETrue/ERec smearing matrix. e.g. "
           "ObsInput=\"input.root[NDObs_species,NDSmearing_species]\"");
     }
 
     nds.NDDataHist = dynamic_cast<TH1D *>(NDObsInputs[0]);
     if (!nds.NDDataHist) {
       ERROR(FTL,
             "First histogram from ObsInput attribute was not a TH1D containing "
             "the near detector observed ERec spectrum ("
                 << samplekey.GetS("ObsInput") << ").");
       THROW(
           "Near detector sample must contain the observed ERec spectrum and "
           "the "
           "ND ETrue/ERec smearing matrix. e.g. "
           "ObsInput=\"input.root[FDObs_species,FDSmearing_species]\"");
     }
 
     nds.NDToSpectrumSmearingMatrix = dynamic_cast<TH2D *>(NDObsInputs[1]);
     if (!nds.NDToSpectrumSmearingMatrix) {
       ERROR(
           FTL,
           "Second histogram from ObsInput attribute was not a TH2D containing "
           "the near detector ETrue/ERec smearing matrix ("
               << samplekey.GetS("ObsInput") << ").");
       THROW(
           "Near detector sample must contain the observed ERec spectrum and "
           "the "
           "ND ETrue/ERec smearing matrix. e.g. "
           "ObsInput=\"input.root[FDObs_species,FDSmearing_species]\"");
     }
   }
 
   nds.NDDataHist->Scale(ScalePOT);
 
   if (UseRateErrors) {
     for (Int_t bi_it = 1; bi_it < nds.NDDataHist->GetXaxis()->GetNbins() + 1;
          ++bi_it) {
       nds.NDDataHist->SetBinError(bi_it,
                                   sqrt(nds.NDDataHist->GetBinContent(bi_it)));
     }
   }
 
   nds.TruncateStart = 0;
   if (samplekey.Has("TruncateStart")) {
     nds.TruncateStart = samplekey.GetI("TruncateStart");
   }
 
   nds.TruncateUpTo = 0;
   if (samplekey.Has("TruncateUpTo")) {
     nds.TruncateUpTo = samplekey.GetI("TruncateUpTo");
     QLOG(SAM, "\tAllowed to truncate unfolding matrix by up to "
                   << nds.TruncateUpTo
                   << " singular values to limit negative ENu spectra.");
   }
   nds.NuPDG = 14;
   if (samplekey.Has("NuPDG")) {
     nds.NuPDG = samplekey.GetI("NuPDG");
   }
 
   NDSamples.push_back(nds);
 }
 
 void Smear_SVDUnfold_Propagation_Osc::SetupNDInputs() {
   for (size_t nd_it = 0; nd_it < NDSamples.size(); ++nd_it) {
     NDSample &nds = NDSamples[nd_it];
 
     TMatrixD NDToSpectrumResponseMatrix_l = SmearceptanceUtils::GetMatrix(
         SmearceptanceUtils::SVDGetInverse(nds.NDToSpectrumSmearingMatrix));
 
     nds.NDToSpectrumResponseMatrix.ResizeTo(NDToSpectrumResponseMatrix_l);
     nds.NDToSpectrumResponseMatrix = NDToSpectrumResponseMatrix_l;
 
     if (nds.TruncateStart != 0) {
       TMatrixD NDToSpectrumResponseMatrix_l =
           SmearceptanceUtils::GetMatrix(SmearceptanceUtils::SVDGetInverse(
               nds.NDToSpectrumSmearingMatrix, nds.TruncateStart));
 
       nds.NDToSpectrumResponseMatrix.ResizeTo(NDToSpectrumResponseMatrix_l);
       nds.NDToSpectrumResponseMatrix = NDToSpectrumResponseMatrix_l;
     }
 
     if (nds.TruncateStart >= nds.TruncateUpTo) {
       nds.TruncateUpTo = nds.TruncateStart + 1;
     }
 
     UnfoldToNDETrueSpectrum(nd_it);
   }
 }
 
 void Smear_SVDUnfold_Propagation_Osc::ReadExtraConfig(nuiskey &samplekey) {
   UseRateErrors = false;
   if (samplekey.Has("SetErrorsFromRate")) {
     UseRateErrors = samplekey.GetI("SetErrorsFromRate");
   }
 
   NDetectorInfo.first = 0xdeadbeef;
   if (samplekey.Has("DetectorVolume") && samplekey.Has("DetectorDensity")) {
     NDetectorInfo.first = samplekey.GetD("DetectorVolume");
     NDetectorInfo.second = samplekey.GetD("DetectorDensity");
 
     double TargetMass_kg = NDetectorInfo.first * NDetectorInfo.second;
 
     QLOG(SAM, "\tND sample detector mass : ");
     QLOG(SAM, "\t\tTarget volume : " << NDetectorInfo.first);
     QLOG(SAM, "\t\tTarget density : " << NDetectorInfo.second);
     QLOG(SAM, "\t\tTarget mass : " << TargetMass_kg << " kg");
   }
 
   ScalePOT = 1;
   if (samplekey.Has("ScalePOT")) {
     ScalePOT = samplekey.GetD("ScalePOT");
   }
 }
 
 void Smear_SVDUnfold_Propagation_Osc::AddFDTarget(nuiskey &nk) {
   FDSample fds;
 
   fds.FitRegion_Min = 0xdeadbeef;
   if (nk.Has("FitRegion_Min")) {
     fds.FitRegion_Min = nk.GetD("FitRegion_Min");
   }
   if ((FitRegion_Min == 0xdeadbeef) || FitRegion_Min > fds.FitRegion_Min) {
     FitRegion_Min = fds.FitRegion_Min;
   }
 
   fds.FitRegion_Max = 0xdeadbeef;
   if (nk.Has("FitRegion_Max")) {
     fds.FitRegion_Max = nk.GetD("FitRegion_Max");
   }
   if ((FitRegion_Max == 0xdeadbeef) || FitRegion_Max < fds.FitRegion_Max) {
     FitRegion_Max = fds.FitRegion_Max;
   }
 
   fds.OscillateToPDG = 0;
   if (nk.Has("OscillateToPDG")) {
     fds.OscillateToPDG = nk.GetD("OscillateToPDG");
   }
 
   std::vector<nuiskey> FDNDRatioElements = nk.GetListOfChildNodes("FDNDRatio");
   for (size_t fdnd_it = 0; fdnd_it < FDNDRatioElements.size(); ++fdnd_it) {
     nuiskey &fnr = FDNDRatioElements[fdnd_it];
     if (fnr.Has("FromPDG") && fnr.Has("DivergenceFactor")) {
       fds.FDNDRatios[fnr.GetI("FromPDG")] = fnr.GetD("DivergenceFactor");
       QLOG(SAM, "FDND DivergenceFactor for far detector sample index: "
                     << FDSamples.size() << " for PDG: " << fnr.GetI("FromPDG")
                     << " -> " << fds.OscillateToPDG << " = "
                     << fnr.GetD("DivergenceFactor"));
     } else {
       THROW(
           "Far detector sample contained FDNDRatio element, but couldn't find "
           "both FromPDG and Factor attributes.");
     }
   }
 
   fds.FDNDMassRatio = 1;
   if (NDetectorInfo.first != 0xdeadbeef) {
     if ((!nk.Has("DetectorVolume")) || (!nk.Has("DetectorDensity"))) {
       THROW(
           "Near detector sample has specified volume but FD doesn't. This is "
           "needed to scale the predicted event rate by the mass ratio.");
     }
     fds.DetectorInfo.first = nk.GetD("DetectorVolume");
     fds.DetectorInfo.second = nk.GetD("DetectorDensity");
     double TargetMass_kg = fds.DetectorInfo.first * fds.DetectorInfo.second;
 
     fds.FDNDMassRatio =
         TargetMass_kg / (NDetectorInfo.first * NDetectorInfo.second);
 
     QLOG(SAM, "\tFD[" << FDSamples.size() << "] Event rate prediction : ");
     QLOG(SAM, "\t\tTarget volume : " << fds.DetectorInfo.first);
     QLOG(SAM, "\t\tTarget density : " << fds.DetectorInfo.second);
     QLOG(SAM, "\t\tFD/ND mass : " << fds.FDNDMassRatio);
   }
 
   if (!nk.Has("ObsInput")) {
     THROW("Far detector sample must specify at least ObsInput.");
   }
 
   std::vector<TH1 *> FDObsInputs =
       PlotUtils::GetTH1sFromRootFile(nk.GetS("ObsInput"));
   if (FDObsInputs.size() < 2) {
     THROW(
         "Far detector sample must contain the observed ERec spectrum and the "
         "FD ETrue/ERec smearing matrix. "
         "ObsInput=\"input.root[FDObs_species,FDSmearing_species]\"");
   }
 
   fds.FDDataHist = NULL;
   for (size_t hist_it = 0; hist_it < FDObsInputs.size() - 1; ++hist_it) {
     if (!dynamic_cast<TH1D *>(FDObsInputs[hist_it])) {
       ERROR(FTL, "Input spectrum index "
                      << hist_it
                      << " from ObsInput attribute was not a TH1D containing "
                         "a far detector observed ERec spectrum ("
                      << nk.GetS("ObsInput") << ").");
       THROW(
           "Far detector sample must contain the observed ERec spectrum and the "
           "FD ETrue/ERec smearing matrix. "
           "ObsInput=\"input.root[FDObs_species,(FDObs_species2),FDSmearing_"
           "species]\"");
     }
     FDObsInputs[hist_it]->Scale(ScalePOT);
     if (!fds.FDDataHist) {
       fds.FDDataHist = dynamic_cast<TH1D *>(FDObsInputs[hist_it]);
     } else {
       fds.FDDataHist->Add(dynamic_cast<TH1D *>(FDObsInputs[hist_it]));
     }
     QLOG(SAM, "Added " << (FDObsInputs.size() - 1)
                        << " far detector component spectra to form Observed "
                           "spectra for sample index "
                        << FDSamples.size() << ".");
   }
 
   fds.SpectrumToFDSmearingMatrix_TH2 = dynamic_cast<TH2D *>(FDObsInputs.back());
   if (!fds.SpectrumToFDSmearingMatrix_TH2) {
     ERROR(FTL,
           "last histogram from ObsInput attribute was not a TH2D containing "
           "the far detector ETrue/ERec smearing matrix ("
               << nk.GetS("ObsInput") << ").");
     THROW(
         "Far detector sample must contain the observed ERec spectrum and the "
         "FD ETrue/ERec smearing matrix. "
         "ObsInput=\"input.root[FDObs_species,FDSmearing_species]\"");
   }
 
   TMatrixD SpectrumToFDSmearingMatrix_l =
       SmearceptanceUtils::GetMatrix(fds.SpectrumToFDSmearingMatrix_TH2);
 
   fds.SpectrumToFDSmearingMatrix.ResizeTo(SpectrumToFDSmearingMatrix_l);
   fds.SpectrumToFDSmearingMatrix = SpectrumToFDSmearingMatrix_l;
 
   FDSamples.push_back(fds);
 }
 
 void Smear_SVDUnfold_Propagation_Osc::FinaliseFDSamples() {
   std::stringstream ss("");
 
   for (size_t fds_it = 0; fds_it < FDSamples.size(); ++fds_it) {
     FDSample &fds = FDSamples[fds_it];
     // Set up FD histograms.
     // ==============================
 
     for (size_t nd_it = 0; nd_it < NDSamples.size(); ++nd_it) {
       NDSample &nds = NDSamples[nd_it];
 
       TH1D *sampleHist =
           static_cast<TH1D *>(nds.ND_Unfolded_Spectrum_Hist->Clone());
       sampleHist->Reset();
       ss.str("");
       ss << "FD_Propagated_Spectrum_Hist_" << fds_it << "_NDSample_" << nd_it;
       sampleHist->SetName(ss.str().c_str());
 
       fds.FD_Propagated_Spectrum_Hist_NDSamples.push_back(sampleHist);
     }
 
     fds.FD_Propagated_Spectrum_Hist = static_cast<TH1D *>(
         fds.FD_Propagated_Spectrum_Hist_NDSamples[0]->Clone());
     fds.FD_Propagated_Spectrum_Hist->Reset();
     ss.str("");
     ss << "FD_Propagated_Spectrum_Hist_" << fds_it;
 
     fds.FD_Propagated_Spectrum_Hist->SetName(ss.str().c_str());
 
     for (size_t nd_it = 0; nd_it < NDSamples.size(); ++nd_it) {
       NDSample &nds = NDSamples[nd_it];
 
       TH1D *sampleHist =
           static_cast<TH1D *>(fds.FD_Propagated_Spectrum_Hist->Clone());
       sampleHist->Reset();
       ss.str("");
       ss << "NDFD_Corrected_Spectrum_Hist_" << fds_it << "_NDSample_" << nd_it;
       sampleHist->SetName(ss.str().c_str());
 
       fds.NDFD_Corrected_Spectrum_Hist_NDSamples.push_back(sampleHist);
     }
 
     fds.NDFD_Corrected_Spectrum_Hist =
         static_cast<TH1D *>(fds.FD_Propagated_Spectrum_Hist->Clone());
     fds.NDFD_Corrected_Spectrum_Hist->Reset();
     ss.str("");
     ss << "NDFD_Corrected_Spectrum_Hist_" << fds_it;
 
     fds.NDFD_Corrected_Spectrum_Hist->SetName(ss.str().c_str());
 
     fds.FD_Smeared_Spectrum_Hist =
         new TH1D(*fds.SpectrumToFDSmearingMatrix_TH2->ProjectionX());
     fds.FD_Smeared_Spectrum_Hist->SetDirectory(NULL);
     fds.FD_Smeared_Spectrum_Hist->Reset();
     ss.str("");
     ss << "FD_Smeared_Spectrum_Hist_" << fds_it;
 
     fds.FD_Smeared_Spectrum_Hist->SetName(ss.str().c_str());
 
     for (size_t nd_it = 0; nd_it < NDSamples.size(); ++nd_it) {
       NDSample &nds = NDSamples[nd_it];
 
       if (!fds.FDNDRatios.count(nds.NuPDG)) {
         ERROR(WRN, "Have an ND sample that provides PDG:"
                        << nds.NuPDG
                        << " neutrinos but far detector sample index " << fds_it
                        << " doesn't have an NDFD ratio for this sample. "
                           "Setting to 0 (contribution from sample ignored.)");
         fds.FDNDRatios[nds.NuPDG] = 0;
       }
     }
   }
 }
 
 Int_t Smear_SVDUnfold_Propagation_Osc::GetFDSampleNAnalysisBins(size_t fds_it) {
   if (fds_it >= FDSamples.size()) {
     THROW("Requested FD sample index " << fds_it << " but only initialised "
                                        << FDSamples.size());
   }
   FDSample &fds = FDSamples[fds_it];
   Int_t NAnalysisBins = 0;
   for (Int_t bi_it = 1; bi_it < fds.FDDataHist->GetXaxis()->GetNbins() + 1;
        ++bi_it) {
     if ((fds.FitRegion_Min != 0xdeadbeef) &&
         (fds.FDDataHist->GetXaxis()->GetBinUpEdge(bi_it) <=
          fds.FitRegion_Min)) {
       continue;
     }
     if ((fds.FitRegion_Max != 0xdeadbeef) &&
         (fds.FDDataHist->GetXaxis()->GetBinLowEdge(bi_it) >
          fds.FitRegion_Max)) {
       continue;
     }
     NAnalysisBins++;
   }
   return NAnalysisBins;
 }
 
 void Smear_SVDUnfold_Propagation_Osc::SetupChi2Hists() {
   fDataHist =
       new TH1D("SmearSVDUnfold", "", NFDAnalysisBins, 0, NFDAnalysisBins);
   fDataHist->SetNameTitle((fSettings.GetName() + "_data").c_str(),
                           (fSettings.GetFullTitles()).c_str());
 
   Int_t CurrAnalysisBin = 1;
   for (size_t fds_it = 0; fds_it < FDSamples.size(); ++fds_it) {
     FDSample &fds = FDSamples[fds_it];
     for (Int_t bi_it = 1; bi_it < fds.FDDataHist->GetXaxis()->GetNbins() + 1;
          ++bi_it) {
       if ((fds.FitRegion_Min != 0xdeadbeef) &&
           (fds.FDDataHist->GetXaxis()->GetBinUpEdge(bi_it) <=
            fds.FitRegion_Min)) {
         continue;
       }
       if ((fds.FitRegion_Max != 0xdeadbeef) &&
           (fds.FDDataHist->GetXaxis()->GetBinLowEdge(bi_it) >
            fds.FitRegion_Max)) {
         continue;
       }
       fDataHist->SetBinContent(CurrAnalysisBin,
                                fds.FDDataHist->GetBinContent(bi_it));
       if (UseRateErrors) {
         fDataHist->SetBinError(CurrAnalysisBin,
                                sqrt(fds.FDDataHist->GetBinContent(bi_it)));
       } else {
         fDataHist->SetBinError(CurrAnalysisBin,
                                fds.FDDataHist->GetBinError(bi_it));
       }
       CurrAnalysisBin++;
     }
   }
 
   fMCHist = static_cast<TH1D *>(fDataHist->Clone());
   fMCHist->SetNameTitle((fSettings.GetName() + "_MC").c_str(),
                         (fSettings.GetFullTitles()).c_str());
   fMCHist->Reset();
 }
 
 void Smear_SVDUnfold_Propagation_Osc::UpdateChi2Hists() {
   Int_t CurrAnalysisBin = 1;
   for (size_t fds_it = 0; fds_it < FDSamples.size(); ++fds_it) {
     FDSample &fds = FDSamples[fds_it];
     for (Int_t bi_it = 1;
          bi_it < fds.FD_Smeared_Spectrum_Hist->GetXaxis()->GetNbins() + 1;
          ++bi_it) {
       if ((fds.FitRegion_Min != 0xdeadbeef) &&
           (fds.FD_Smeared_Spectrum_Hist->GetXaxis()->GetBinUpEdge(bi_it) <=
            fds.FitRegion_Min)) {
         continue;
       }
       if ((fds.FitRegion_Max != 0xdeadbeef) &&
           (fds.FD_Smeared_Spectrum_Hist->GetXaxis()->GetBinLowEdge(bi_it) >
            fds.FitRegion_Max)) {
         continue;
       }
       fMCHist->SetBinContent(
           CurrAnalysisBin, fds.FD_Smeared_Spectrum_Hist->GetBinContent(bi_it));
 
       fMCHist->SetBinError(CurrAnalysisBin,
                            fds.FD_Smeared_Spectrum_Hist->GetBinError(bi_it));
       CurrAnalysisBin++;
     }
   }
 }
 
 //********************************************************************
 Smear_SVDUnfold_Propagation_Osc::Smear_SVDUnfold_Propagation_Osc(
     nuiskey samplekey) {
   //********************************************************************
 
   // Sample overview ---------------------------------------------------
   std::string descrip =
       "Simple measurement class for doing fake data oscillation studies.\n";
 
   // Setup common settings
   fSettings = LoadSampleSettings(samplekey);
 
   fSettings.SetTitle("Osc Studies");
   fSettings.SetDescription(descrip);
   fSettings.SetXTitle("XXX");
   fSettings.SetYTitle("Number of events");
   fSettings.SetEnuRange(0.0, 50);
   fSettings.SetAllowedTypes("EVT/SHAPE/DIAG", "EVT/SHAPE/DIAG");
   fSettings.DefineAllowedTargets("*");
   fSettings.DefineAllowedSpecies("numu");
 
   FinaliseSampleSettings();
 
   // Scaling Setup ---------------------------------------------------
   // ScaleFactor automatically setup for DiffXSec/cm2/Nucleon
   fScaleFactor = GetEventHistogram()->Integral("width") / (fNEvents + 0.);
 
   fMCHist = NULL;
   fDataHist = NULL;
 
   ReadExtraConfig(samplekey);
 
   AddNDInputs(samplekey);
   std::vector<nuiskey> NDTargets = samplekey.GetListOfChildNodes("NDObs");
   for (size_t nd_it = 0; nd_it < NDTargets.size(); ++nd_it) {
     AddNDInputs(NDTargets[nd_it]);
   }
 
   std::vector<nuiskey> FDTargets = samplekey.GetListOfChildNodes("FDObs");
   NFDAnalysisBins = 0;
   if (!FDTargets.size()) {  // If no child elements, assume that everything is
                             // contained on the sample element
     AddFDTarget(samplekey);
   } else {
     for (size_t fd_it = 0; fd_it < FDTargets.size(); ++fd_it) {
       AddFDTarget(FDTargets[fd_it]);
       NFDAnalysisBins += GetFDSampleNAnalysisBins(fd_it);
     }
   }
 
   SetupNDInputs();
 
   FinaliseFDSamples();
 
   QLOG(SAM, "Set up " << FDSamples.size()
                       << " samples for oscillation analysis with "
                       << NFDAnalysisBins << " analysis bins.");
 
   SetupChi2Hists();
 
   SetCovarFromDiagonal();
 
   // Final setup  ---------------------------------------------------
   FinaliseMeasurement();
 };
 
 void Smear_SVDUnfold_Propagation_Osc::FillEventVariables(FitEvent *event){};
 
 bool Smear_SVDUnfold_Propagation_Osc::isSignal(FitEvent *event) {
   return false;
 }
 
 void Smear_SVDUnfold_Propagation_Osc::UnfoldToNDETrueSpectrum(size_t nd_it) {
   if (nd_it >= NDSamples.size()) {
     THROW("Attempting to unfold ND sample index "
           << nd_it << " but only have " << NDSamples.size() << " ND samples.");
   }
 
   NDSample &nds = NDSamples[nd_it];
 
   nds.ND_Unfolded_Spectrum_Hist =
       new TH1D(*nds.NDToSpectrumSmearingMatrix->ProjectionY());
   nds.ND_Unfolded_Spectrum_Hist->SetDirectory(NULL);
   nds.ND_Unfolded_Spectrum_Hist->Clear();
   std::stringstream ss("");
   ss << "ND_Unfolded_Spectrum_Hist_" << nd_it;
   nds.ND_Unfolded_Spectrum_Hist->SetName(ss.str().c_str());
 
   bool HasNegValue = false;
   int truncations = nds.TruncateStart;
   do {
     if (truncations >= nds.TruncateUpTo) {
       THROW("Unfolded enu spectrum had negative values even after "
             << truncations << " SVD singular value truncations.");
     }
 
     // Unfold ND ERec -> Enu spectrum
     // ------------------------------
     SmearceptanceUtils::PushTH1ThroughMatrixWithErrors(
         nds.NDDataHist, nds.ND_Unfolded_Spectrum_Hist,
         nds.NDToSpectrumResponseMatrix, 1000, false);
 
     HasNegValue = false;
 
     for (Int_t bi_it = 1;
          bi_it < nds.ND_Unfolded_Spectrum_Hist->GetXaxis()->GetNbins() + 1;
          ++bi_it) {
       if ((FitRegion_Min != 0xdeadbeef) &&
           (nds.ND_Unfolded_Spectrum_Hist->GetXaxis()->GetBinUpEdge(bi_it) <=
            FitRegion_Min)) {
         continue;
       }
       if ((FitRegion_Max != 0xdeadbeef) &&
           (nds.ND_Unfolded_Spectrum_Hist->GetXaxis()->GetBinLowEdge(bi_it) >
            FitRegion_Max)) {
         continue;
       }
 
       if (nds.ND_Unfolded_Spectrum_Hist->GetBinContent(bi_it) < 0) {
         HasNegValue = true;
         break;
       }
     }
 
     if (HasNegValue) {
       TMatrixD NDToSpectrumResponseMatrix_l =
           SmearceptanceUtils::GetMatrix(SmearceptanceUtils::SVDGetInverse(
               nds.NDToSpectrumSmearingMatrix, truncations));
 
       nds.NDToSpectrumResponseMatrix.ResizeTo(NDToSpectrumResponseMatrix_l);
       nds.NDToSpectrumResponseMatrix = NDToSpectrumResponseMatrix_l;
     }
 
     truncations++;
   } while (HasNegValue);
 }
 
 void Smear_SVDUnfold_Propagation_Osc::PropagateFDSample(size_t fds_it) {
   if (fds_it >= FDSamples.size()) {
     THROW("Requested FD sample index " << fds_it << " but only initialised "
                                        << FDSamples.size());
   }
   FDSample &fds = FDSamples[fds_it];
 
   // Apply Oscillations
   // ------------------------------
   FitWeight *fw = FitBase::GetRW();
   OscWeightEngine *oscWE =
       dynamic_cast<OscWeightEngine *>(fw->GetRWEngine(kOSCILLATION));
 
   if (!oscWE) {
     THROW(
         "Couldn't load oscillation weight engine for sample: "
         "Smear_SVDUnfold_Propagation_Osc.");
   }
 
   for (Int_t bi_it = 1;
        bi_it < fds.NDFD_Corrected_Spectrum_Hist->GetXaxis()->GetNbins() + 1;
        ++bi_it) {
     double content_osc = 0;
     double error_osc = 0;
     double content_fdnd = 0;
     double error_fdnd = 0;
     // Oscillate each ND sample to FD neutrino
     for (size_t nd_it = 0; nd_it < NDSamples.size(); ++nd_it) {
       NDSample &nds = NDSamples[nd_it];
 
       double oscWeight = oscWE->CalcWeight(
           nds.ND_Unfolded_Spectrum_Hist->GetXaxis()->GetBinCenter(bi_it),
           nds.NuPDG, fds.OscillateToPDG);
 
       double sample_content_osc =
           nds.ND_Unfolded_Spectrum_Hist->GetBinContent(bi_it) * oscWeight;
       double sample_error_osc =
           nds.ND_Unfolded_Spectrum_Hist->GetBinError(bi_it) * oscWeight;
 
       fds.FD_Propagated_Spectrum_Hist_NDSamples[nd_it]->SetBinContent(
           bi_it, sample_content_osc);
       fds.FD_Propagated_Spectrum_Hist_NDSamples[nd_it]->SetBinError(
           bi_it, sample_error_osc);
 
       double sample_content_fdnd =
           sample_content_osc * fds.FDNDRatios[nds.NuPDG] * fds.FDNDMassRatio;
       double sample_error_fdnd =
           sample_error_osc * fds.FDNDRatios[nds.NuPDG] * fds.FDNDMassRatio;
 
       fds.NDFD_Corrected_Spectrum_Hist_NDSamples[nd_it]->SetBinContent(
           bi_it, sample_content_fdnd);
       fds.NDFD_Corrected_Spectrum_Hist_NDSamples[nd_it]->SetBinError(
           bi_it, sample_error_fdnd);
 
       content_osc += sample_content_osc;
       error_osc += sample_error_osc * sample_error_osc;
 
       content_fdnd += sample_content_fdnd;
       error_fdnd += sample_error_fdnd * sample_error_fdnd;
     }
 
     fds.FD_Propagated_Spectrum_Hist->SetBinContent(bi_it, content_osc);
     fds.FD_Propagated_Spectrum_Hist->SetBinError(bi_it, sqrt(error_osc));
 
     fds.NDFD_Corrected_Spectrum_Hist->SetBinContent(bi_it, content_fdnd);
     fds.NDFD_Corrected_Spectrum_Hist->SetBinError(bi_it, sqrt(error_fdnd));
   }
 
   // Forward fold Spectrum -> ERec FD
   // ------------------------------
   SmearceptanceUtils::PushTH1ThroughMatrixWithErrors(
       fds.NDFD_Corrected_Spectrum_Hist, fds.FD_Smeared_Spectrum_Hist,
       fds.SpectrumToFDSmearingMatrix, 1000, true);
 }
 
 void Smear_SVDUnfold_Propagation_Osc::ConvertEventRates(void) {
   for (size_t fds_it = 0; fds_it < FDSamples.size(); ++fds_it) {
     PropagateFDSample(fds_it);
   }
   UpdateChi2Hists();
 }
 
 void Smear_SVDUnfold_Propagation_Osc::Write(std::string drawOpt) {
   TDirectory *ogDir = gDirectory;
 
   ConvertEventRates();
 
   FitWeight *fw = FitBase::GetRW();
   OscWeightEngine *oscWE =
       dynamic_cast<OscWeightEngine *>(fw->GetRWEngine(kOSCILLATION));
 
   if (!oscWE) {
     THROW(
         "Couldn't load oscillation weight engine for sample: "
         "Smear_SVDUnfold_Propagation_Osc.");
   }
   oscWE->Print();
 
   // Write ND samples
   //----------------
   for (size_t nd_it = 0; nd_it < NDSamples.size(); ++nd_it) {
     NDSample &nds = NDSamples[nd_it];
     std::stringstream ss("");
     ss << "Smear_SVDUnfold_Propagation_Osc_NDSample_" << nd_it;
     if (ogDir) {
       ogDir->mkdir(ss.str().c_str());
       ogDir->cd(ss.str().c_str());
     } else {
-      FitPar::Config().out->mkdir(ss.str().c_str());
-      FitPar::Config().out->cd(ss.str().c_str());
+      Config::Get().out->mkdir(ss.str().c_str());
+      Config::Get().out->cd(ss.str().c_str());
     }
 
     nds.NDToSpectrumSmearingMatrix->Write("SmearingMatrix_ND",
                                           TObject::kOverwrite);
     nds.NDDataHist->Write("Obs_ND", TObject::kOverwrite);
 
     nds.ND_Unfolded_Spectrum_Hist->Write(
         nds.ND_Unfolded_Spectrum_Hist->GetName(), TObject::kOverwrite);
 
     if (ogDir) {
       ogDir->cd();
     } else {
-      FitPar::Config().out->cd();
+      Config::Get().out->cd();
     }
   }
 
   // Write FD samples
   //----------------
   for (size_t fds_it = 0; fds_it < FDSamples.size(); ++fds_it) {
     FDSample &fds = FDSamples[fds_it];
 
     std::stringstream ss("");
     ss << "Smear_SVDUnfold_Propagation_Osc_FDSample_" << fds_it;
     if (ogDir) {
       ogDir->mkdir(ss.str().c_str());
       ogDir->cd(ss.str().c_str());
     } else {
-      FitPar::Config().out->mkdir(ss.str().c_str());
-      FitPar::Config().out->cd(ss.str().c_str());
+      Config::Get().out->mkdir(ss.str().c_str());
+      Config::Get().out->cd(ss.str().c_str());
     }
 
     // Calc oscillation probability
     // ------------------------------
     FitWeight *fw = FitBase::GetRW();
     OscWeightEngine *oscWE =
         dynamic_cast<OscWeightEngine *>(fw->GetRWEngine(kOSCILLATION));
 
     if (!oscWE) {
       THROW(
           "Couldn't load oscillation weight engine for sample: "
           "Smear_SVDUnfold_Propagation_Osc.");
     }
 
     for (size_t nd_it = 0; nd_it < NDSamples.size(); ++nd_it) {
       NDSample &nds = NDSamples[nd_it];
       ss.str("");
       ss << "NDSample_" << nd_it << "_contribution";
       fds.FD_Propagated_Spectrum_Hist_NDSamples[nd_it]->Write(
           ss.str().c_str(), TObject::kOverwrite);
       ss.str("");
 
       ss << "NDSample_" << nd_it << "_FDNDCorrected_contribution";
       fds.NDFD_Corrected_Spectrum_Hist_NDSamples[nd_it]->Write(
           ss.str().c_str(), TObject::kOverwrite);
 
       ss.str("");
       ss << "NDSample_" << nd_it << "_OscillationProb";
 
       TGraph POsc;
 
       POsc.Set(1E4 - 1);
 
       double min = nds.ND_Unfolded_Spectrum_Hist->GetXaxis()->GetBinLowEdge(1);
       double step =
           (nds.ND_Unfolded_Spectrum_Hist->GetXaxis()->GetBinUpEdge(
                nds.ND_Unfolded_Spectrum_Hist->GetXaxis()->GetNbins()) -
            nds.ND_Unfolded_Spectrum_Hist->GetXaxis()->GetBinLowEdge(1)) /
           double(1E4);
 
       for (size_t i = 1; i < 1E4; ++i) {
         double enu = min + i * step;
         double ow = oscWE->CalcWeight(enu, nds.NuPDG, fds.OscillateToPDG);
         if (ow != ow) {
           std::cout << "Bad osc weight for ENu: " << enu << std::endl;
         }
         POsc.SetPoint(i - 1, enu, ow);
       }
 
       POsc.Write(ss.str().c_str(), TObject::kOverwrite);
     }
 
     fds.FDDataHist->Write("Obs_FD", TObject::kOverwrite);
 
     fds.FD_Propagated_Spectrum_Hist->Write(
         fds.FD_Propagated_Spectrum_Hist->GetName(), TObject::kOverwrite);
 
     fds.NDFD_Corrected_Spectrum_Hist->Write(
         fds.NDFD_Corrected_Spectrum_Hist->GetName(), TObject::kOverwrite);
 
     fds.SpectrumToFDSmearingMatrix_TH2->Write("SmearingMatrix_FD",
                                               TObject::kOverwrite);
 
     fds.FD_Smeared_Spectrum_Hist->Write(fds.FD_Smeared_Spectrum_Hist->GetName(),
                                         TObject::kOverwrite);
 
     if (ogDir) {
       ogDir->cd();
     } else {
-      FitPar::Config().out->cd();
+      Config::Get().out->cd();
     }
   }
 
   fMCHist->Write("Pred_FD", TObject::kOverwrite);
   fDataHist->Write("Obs_FD", TObject::kOverwrite);
 
   Measurement1D::Write(drawOpt);
 }
diff --git a/src/MCStudies/Smearceptance_Tester.cxx b/src/MCStudies/Smearceptance_Tester.cxx
index 67677e2..17f3de7 100644
--- a/src/MCStudies/Smearceptance_Tester.cxx
+++ b/src/MCStudies/Smearceptance_Tester.cxx
@@ -1,785 +1,788 @@
 // Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret
 
 /*******************************************************************************
 *    This file is part of NUISANCE.
 *
 *    NUISANCE is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    NUISANCE is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with NUISANCE.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
 
 #include "Smearceptance_Tester.h"
 
 #include "SmearceptanceUtils.h"
 
 #include "Smearcepterton.h"
 
 #define DEBUG_SMEARTESTER
 
 //********************************************************************
 /// @brief Class to perform smearceptance MC Studies on a custom measurement
 Smearceptance_Tester::Smearceptance_Tester(nuiskey samplekey) {
   //********************************************************************
 
+  samplekey.Print();
+
   // Sample overview ---------------------------------------------------
   std::string descrip =
       "Simple measurement class for producing an event summary tree of smeared "
       "events.\n";
 
-  if (Config::Get().GetConfigNode("NPOT")) {
-    samplekey.SetS("NPOT", Config::Get().ConfS("NPOT"));
+  if (Config::HasPar("NPOT")) {
+    samplekey.SetS("NPOT", Config::GetParS("NPOT"));
   }
-  if (Config::Get().GetConfigNode("FluxIntegralOverride")) {
+  if (Config::HasPar("FluxIntegralOverride")) {
     samplekey.SetS("FluxIntegralOverride",
-                   Config::Get().ConfS("FluxIntegralOverride"));
+                   Config::GetParS("FluxIntegralOverride"));
   }
-  if (Config::Get().GetConfigNode("TargetVolume")) {
-    samplekey.SetS("TargetVolume", Config::Get().ConfS("TargetVolume"));
+  if (Config::HasPar("TargetVolume")) {
+    samplekey.SetS("TargetVolume", Config::GetParS("TargetVolume"));
   }
-  if (Config::Get().GetConfigNode("TargetMaterialDensity")) {
+  if (Config::HasPar("TargetMaterialDensity")) {
     samplekey.SetS("TargetMaterialDensity",
-                   Config::Get().ConfS("TargetMaterialDensity"));
+                   Config::GetParS("TargetMaterialDensity"));
   }
 
   OutputSummaryTree = true;
-  if (Config::Get().GetConfigNode("smear.OutputSummaryTree")) {
-    OutputSummaryTree = Config::Get().ConfI("smear.OutputSummaryTree");
+  if (Config::HasPar("smear.OutputSummaryTree")) {
+    OutputSummaryTree = Config::GetParI("smear.OutputSummaryTree");
   }
 
   // Setup common settings
   fSettings = LoadSampleSettings(samplekey);
 
   fSettings.SetTitle("Smearceptance Studies");
   fSettings.SetDescription(descrip);
   fSettings.SetXTitle("XXX");
   fSettings.SetYTitle("Number of events");
   fSettings.SetEnuRange(0.0, 1E5);
   fSettings.SetAllowedTypes("EVT/SHAPE/DIAG", "EVT/SHAPE/DIAG");
   fSettings.DefineAllowedTargets("*");
   fSettings.DefineAllowedSpecies("*");
 
   FinaliseSampleSettings();
 
   // Scaling Setup ---------------------------------------------------
   // ScaleFactor automatically setup for DiffXSec/cm2/Nucleon
   fScaleFactor =
       (GetEventHistogram()->Integral("width") * 1E-38 / (fNEvents + 0.)) /
       TotalIntegratedFlux();
 
   // Measurement Details
   std::vector<std::string> splitName = GeneralUtils::ParseToStr(fName, "_");
   size_t firstUS = fName.find_first_of("_");
 
-  std::string smearceptorName = fName.substr(firstUS + 1);
+  std::string smearceptorName = samplekey.GetS("smearceptor");
+  QLOG(SAM, "Using smearceptor: " << smearceptorName
+                                  << " (parsed from: " << fName << ").");
 
   fDataHist = new TH1D(("empty_data"), ("empty-data"), 1, 0, 1);
   SetupDefaultHist();
   fFullCovar = StatUtils::MakeDiagonalCovarMatrix(fDataHist);
   covar = StatUtils::GetInvert(fFullCovar);
 
   eventVariables = NULL;
 
-  LOG(SAM) << "Smearceptance Flux Scaling Factor = " << fScaleFactor
-           << std::endl;
+  QLOG(SAM, "Smearceptance Flux Scaling Factor = " << fScaleFactor);
 
   if (fScaleFactor <= 0.0) {
-    ERR(WRN) << "SCALE FACTOR TOO LOW " << std::endl;
+    ERROR(WRN, "SCALE FACTOR TOO LOW ");
     sleep(20);
   }
 
   // Setup our TTrees
   AddEventVariablesToTree();
 
   smearceptor = &Smearcepterton::Get().GetSmearcepter(smearceptorName);
 
   Int_t RecNBins = 20, TrueNBins = 20;
   double RecBinL = 0xdeadbeef, TrueBinL = 0, RecBinH = 10, TrueBinH = 10;
 
-  if (Config::Get().GetConfigNode("smear.reconstructed.binning")) {
+  if (Config::HasPar("smear.reconstructed.binning")) {
     std::vector<std::string> args = GeneralUtils::ParseToStr(
-        Config::Get().ConfS("smear.reconstructed.binning"), ",");
+        Config::GetParS("smear.reconstructed.binning"), ",");
     RecNBins = GeneralUtils::StrToInt(args[0]);
     RecBinL = GeneralUtils::StrToDbl(args[1]);
     RecBinH = GeneralUtils::StrToDbl(args[2]);
     TrueNBins = RecNBins;
     TrueBinL = RecBinL;
     TrueBinH = RecBinH;
   }
 
-  if (Config::Get().GetConfigNode("smear.true.binning")) {
-    std::vector<std::string> args = GeneralUtils::ParseToStr(
-        Config::Get().ConfS("smear.true.binning"), ",");
+  if (Config::HasPar("smear.true.binning")) {
+    std::vector<std::string> args =
+        GeneralUtils::ParseToStr(Config::GetParS("smear.true.binning"), ",");
     TrueNBins = GeneralUtils::StrToInt(args[0]);
     TrueBinL = GeneralUtils::StrToDbl(args[1]);
     TrueBinH = GeneralUtils::StrToDbl(args[2]);
   }
   SVDTruncation = 0;
-  if (Config::Get().GetConfigNode("smear.true.binning")) {
-    SVDTruncation = Config::Get().ConfI("smear.SVD.truncation");
+  if (Config::HasPar("smear.true.binning")) {
+    SVDTruncation = Config::GetParI("smear.SVD.truncation");
     QLOG(SAM, "Applying SVD truncation of: " << SVDTruncation)
   }
 
   ETrueDistrib = NULL;
   ETrueDistrib_noweight = NULL;
   ERecDistrib = NULL;
   RecoSmear = NULL;
   if (RecBinL != 0xdeadbeef) {
     QLOG(SAM, "Using binning True: " << TrueNBins << ", [" << TrueBinL << " -- "
                                      << TrueBinH << "], Rec: " << RecNBins
                                      << ", [" << RecBinL << " -- " << RecBinH
                                      << "]");
 
     ETrueDistrib = new TH1D("ELep_rate", ";True E_{#nu};Count", TrueNBins,
                             TrueBinL, TrueBinH);
     ETrueDistrib_noweight =
         new TH1D("ELep_rate_noweight", ";True E_{#nu};Count", TrueNBins,
                  TrueBinL, TrueBinH);
     ERecDistrib = new TH1D("ELepRec_rate", ";Rec E_{#nu};Count", RecNBins,
                            RecBinL, RecBinH);
     ETrueDistrib->Sumw2();
     ERecDistrib->Sumw2();
 
     RecoSmear =
         new TH2D("ELepHadVis_Recon", ";True E_{#nu};Recon. E_{#nu}", RecNBins,
                  RecBinL, RecBinH, TrueNBins, TrueBinL, TrueBinH);
     RecoSmear->Sumw2();
   }
 
   // Final setup  ---------------------------------------------------
   FinaliseMeasurement();
 }
 
 void Smearceptance_Tester::AddEventVariablesToTree() {
   if (OutputSummaryTree) {
     // Setup the TTree to save everything
     if (!eventVariables) {
-      FitPar::Config().out->cd();
+      Config::Get().out->cd();
       eventVariables =
           new TTree((fName + "_VARS").c_str(), (fName + "_VARS").c_str());
     }
 
     LOG(SAM) << "Adding Event Variables" << std::endl;
 
     eventVariables->Branch("Omega_true", &Omega_true, "Omega_true/F");
     eventVariables->Branch("Q2_true", &Q2_true, "Q2_true/F");
     eventVariables->Branch("Mode_true", &Mode_true, "Mode_true/I");
 
     eventVariables->Branch("EISLep_true", &EISLep_true, "EISLep_true/F");
 
     eventVariables->Branch("HMFS_mu_true", &HMFS_mu_true);
     eventVariables->Branch("HMFS_pip_true", &HMFS_pip_true);
     eventVariables->Branch("HMFS_pim_true", &HMFS_pim_true);
     eventVariables->Branch("HMFS_cpi_true", &HMFS_cpi_true);
     eventVariables->Branch("HMFS_p_true", &HMFS_p_true);
 
     eventVariables->Branch("KEFSHad_cpip_true", &KEFSHad_cpip_true,
                            "KEFSHad_cpip_true/F");
     eventVariables->Branch("KEFSHad_cpim_true", &KEFSHad_cpim_true,
                            "KEFSHad_cpim_true/F");
     eventVariables->Branch("KEFSHad_cpi_true", &KEFSHad_cpi_true,
                            "KEFSHad_cpi_true/F");
     eventVariables->Branch("TEFSHad_pi0_true", &TEFSHad_pi0_true,
                            "TEFSHad_pi0_true/F");
     eventVariables->Branch("KEFSHad_p_true", &KEFSHad_p_true,
                            "KEFSHad_p_true/F");
     eventVariables->Branch("KEFSHad_n_true", &KEFSHad_n_true,
                            "KEFSHad_n_true/F");
 
     eventVariables->Branch("EFSHad_true", &EFSHad_true, "EFSHad_true/F");
     eventVariables->Branch("EFSChargedEMHad_true", &EFSChargedEMHad_true,
                            "EFSChargedEMHad_true/F");
 
     eventVariables->Branch("EFSLep_true", &EFSLep_true, "EFSLep_true/F");
     eventVariables->Branch("EFSgamma_true", &EFSgamma_true, "EFSgamma_true/F");
 
     eventVariables->Branch("PDGISLep_true", &PDGISLep_true, "PDGISLep_true/I");
     eventVariables->Branch("PDGFSLep_true", &PDGFSLep_true, "PDGFSLep_true/I");
 
     eventVariables->Branch("Nprotons_true", &Nprotons_true, "Nprotons_true/I");
     eventVariables->Branch("Nneutrons_true", &Nneutrons_true,
                            "Nneutrons_true/I");
     eventVariables->Branch("Ncpiplus_true", &Ncpiplus_true, "Ncpiplus_true/I");
     eventVariables->Branch("Ncpiminus_true", &Ncpiminus_true,
                            "Ncpiminus_true/I");
     eventVariables->Branch("Ncpi_true", &Ncpi_true, "Ncpi_true/I");
     eventVariables->Branch("Npi0_true", &Npi0_true, "Npi0_true/I");
 
     eventVariables->Branch("HMFS_mu_rec", &HMFS_mu_rec);
     eventVariables->Branch("HMFS_pip_rec", &HMFS_pip_rec);
     eventVariables->Branch("HMFS_pim_rec", &HMFS_pim_rec);
     eventVariables->Branch("HMFS_cpi_rec", &HMFS_cpi_rec);
     eventVariables->Branch("HMFS_p_rec", &HMFS_p_rec);
 
     eventVariables->Branch("KEFSHad_cpip_rec", &KEFSHad_cpip_rec,
                            "KEFSHad_cpip_rec/F");
     eventVariables->Branch("KEFSHad_cpim_rec", &KEFSHad_cpim_rec,
                            "KEFSHad_cpim_rec/F");
     eventVariables->Branch("KEFSHad_cpi_rec", &KEFSHad_cpi_rec,
                            "KEFSHad_cpi_rec/F");
     eventVariables->Branch("TEFSHad_pi0_rec", &TEFSHad_pi0_rec,
                            "TEFSHad_pi0_rec/F");
     eventVariables->Branch("KEFSHad_p_rec", &KEFSHad_p_rec, "KEFSHad_p_rec/F");
     eventVariables->Branch("KEFSHad_n_rec", &KEFSHad_n_rec, "KEFSHad_n_rec/F");
 
     eventVariables->Branch("EFSHad_rec", &EFSHad_rec, "EFSHad_rec/F");
     eventVariables->Branch("EFSLep_rec", &EFSLep_rec, "EFSLep_rec/F");
 
     eventVariables->Branch("EFSVis_cpip", &EFSVis_cpip, "EFSVis_cpip/F");
     eventVariables->Branch("EFSVis_cpim", &EFSVis_cpim, "EFSVis_cpim/F");
     eventVariables->Branch("EFSVis_cpi", &EFSVis_cpi, "EFSVis_cpi/F");
     eventVariables->Branch("EFSVis_pi0", &EFSVis_pi0, "EFSVis_pi0/F");
     eventVariables->Branch("EFSVis_p", &EFSVis_p, "EFSVis_p/F");
     eventVariables->Branch("EFSVis_n", &EFSVis_n, "EFSVis_n/F");
     eventVariables->Branch("EFSVis_gamma", &EFSVis_gamma, "EFSVis_gamma/F");
     eventVariables->Branch("EFSVis_other", &EFSVis_other, "EFSVis_other/F");
     eventVariables->Branch("EFSVis", &EFSVis, "EFSVis/F");
 
     eventVariables->Branch("FSCLep_seen", &FSCLep_seen, "FSCLep_seen/I");
     eventVariables->Branch("Nprotons_seen", &Nprotons_seen, "Nprotons_seen/I");
     eventVariables->Branch("Nneutrons_seen", &Nneutrons_seen,
                            "Nneutrons_seen/I");
     eventVariables->Branch("Ncpip_seen", &Ncpip_seen, "Ncpip_seen/I");
     eventVariables->Branch("Ncpim_seen", &Ncpim_seen, "Ncpim_seen/I");
     eventVariables->Branch("Ncpi_seen", &Ncpi_seen, "Ncpi_seen/I");
     eventVariables->Branch("Npi0_seen", &Npi0_seen, "Npi0_seen/I");
     eventVariables->Branch("Nothers_seen", &Nothers_seen, "Nothers_seen/I");
 
     eventVariables->Branch("EISLep_QE_rec", &EISLep_QE_rec, "EISLep_QE_rec/F");
     eventVariables->Branch("EISLep_LepHad_rec", &EISLep_LepHad_rec,
                            "EISLep_LepHad_rec/F");
     eventVariables->Branch("EISLep_LepHadVis_rec", &EISLep_LepHadVis_rec,
                            "EISLep_LepHadVis_rec/F");
 
     eventVariables->Branch("Nprotons_contributed", &Nprotons_contributed,
                            "Nprotons_contributed/I");
     eventVariables->Branch("Nneutrons_contributed", &Nneutrons_contributed,
                            "Nneutrons_contributed/I");
     eventVariables->Branch("Ncpip_contributed", &Ncpip_contributed,
                            "Ncpip_contributed/I");
     eventVariables->Branch("Ncpim_contributed", &Ncpim_contributed,
                            "Ncpim_contributed/I");
     eventVariables->Branch("Ncpi_contributed", &Ncpi_contributed,
                            "Ncpi_contributed/I");
     eventVariables->Branch("Npi0_contributed", &Npi0_contributed,
                            "Npi0_contributed/I");
     eventVariables->Branch("Ngamma_contributed", &Ngamma_contributed,
                            "Ngamma_contributed/I");
     eventVariables->Branch("Nothers_contibuted", &Nothers_contibuted,
                            "Nothers_contibuted/I");
 
     eventVariables->Branch("Weight", &Weight, "Weight/F");
     eventVariables->Branch("RWWeight", &RWWeight, "RWWeight/F");
     eventVariables->Branch("InputWeight", &InputWeight, "InputWeight/F");
     eventVariables->Branch("FluxWeight", &FluxWeight, "FluxWeight/F");
     eventVariables->Branch("EffWeight", &EffWeight, "EffWeight/F");
 
     xsecScaling = fScaleFactor;
     eventVariables->Branch("xsecScaling", &xsecScaling, "xsecScaling/F");
 
     eventVariables->Branch("flagCCINC_true", &flagCCINC_true,
                            "flagCCINC_true/O");
     eventVariables->Branch("flagCC0Pi_true", &flagCC0Pi_true,
                            "flagCC0Pi_true/O");
     eventVariables->Branch("flagCC1Pi_true", &flagCC1Pi_true,
                            "flagCC1Pi_true/O");
 
     eventVariables->Branch("flagCCINC_rec", &flagCCINC_rec, "flagCCINC_rec/O");
     eventVariables->Branch("flagCC0Pi_rec", &flagCC0Pi_rec, "flagCC0Pi_rec/O");
     eventVariables->Branch("flagCC1Pi_rec", &flagCC1Pi_rec, "flagCC1Pi_rec/O");
   }
 
   PredEvtRateWeight = 1;
   if (fEvtRateScaleFactor != 0xdeadbeef) {
     if (OutputSummaryTree) {
       eventVariables->Branch("PredEvtRateWeight", &PredEvtRateWeight,
                              "PredEvtRateWeight/F");
     }
     PredEvtRateWeight = fScaleFactor * fEvtRateScaleFactor;
   }
 }
 
 template <size_t N>
 int CountNPdgsSeen(RecoInfo ri, int const (&pdgs)[N]) {
   int sum = 0;
   for (size_t pdg_it = 0; pdg_it < N; ++pdg_it) {
     sum +=
         std::count(ri.RecObjClass.begin(), ri.RecObjClass.end(), pdgs[pdg_it]);
   }
   return sum;
 }
 
 template <size_t N>
 int CountNNotPdgsSeen(RecoInfo ri, int const (&pdgs)[N]) {
   int sum = 0;
   for (size_t pdg_it = 0; pdg_it < N; ++pdg_it) {
     sum +=
         (std::count(ri.RecObjClass.begin(), ri.RecObjClass.end(), pdgs[pdg_it])
              ? 0
              : 1);
   }
   return sum;
 }
 
 template <size_t N>
 int CountNPdgsContributed(RecoInfo ri, int const (&pdgs)[N]) {
   int sum = 0;
   for (size_t pdg_it = 0; pdg_it < N; ++pdg_it) {
     sum += std::count(ri.TrueContribPDGs.begin(), ri.TrueContribPDGs.end(),
                       pdgs[pdg_it]);
   }
   return sum;
 }
 
 template <size_t N>
 int CountNNotPdgsContributed(RecoInfo ri, int const (&pdgs)[N]) {
   int sum = 0;
   for (size_t pdg_it = 0; pdg_it < N; ++pdg_it) {
     sum += (std::count(ri.TrueContribPDGs.begin(), ri.TrueContribPDGs.end(),
                        pdgs[pdg_it])
                 ? 0
                 : 1);
   }
   return sum;
 }
 
 TLorentzVector GetHMFSRecParticles(RecoInfo ri, int pdg) {
   TLorentzVector mom(0, 0, 0, 0);
   for (size_t p_it = 0; p_it < ri.RecObjMom.size(); ++p_it) {
     if ((ri.RecObjClass[p_it] == pdg) &&
         (mom.Mag() < ri.RecObjMom[p_it].Mag())) {
       mom.SetXYZM(ri.RecObjMom[p_it].X(), ri.RecObjMom[p_it].Y(),
                   ri.RecObjMom[p_it].Z(),
                   PhysConst::GetMass(ri.RecObjClass[p_it]) * 1.0E3);
     }
   }
   return mom;
 }
 
 template <size_t N>
 double SumKE_RecoInfo(RecoInfo ri, int const (&pdgs)[N], double mass) {
   double sum = 0;
   for (size_t p_it = 0; p_it < ri.RecObjMom.size(); ++p_it) {
     if (!std::count(pdgs, pdgs + N,
                     ri.RecObjClass[p_it])) {  // If we don't care about this
                                               // particle type.
       continue;
     }
     sum += sqrt(ri.RecObjMom[p_it].Mag2() + mass * mass) - mass;
   }
 
   return sum;
 }
 
 template <size_t N>
 double SumTE_RecoInfo(RecoInfo ri, int const (&pdgs)[N], double mass) {
   double sum = 0;
   for (size_t p_it = 0; p_it < ri.RecObjMom.size(); ++p_it) {
     if (!std::count(pdgs, pdgs + N,
                     ri.RecObjClass[p_it])) {  // If we don't care about this
                                               // particle type.
       continue;
     }
     sum += sqrt(ri.RecObjMom[p_it].Mag2() + mass * mass);
   }
 
   return sum;
 }
 
 template <size_t N>
 double SumVisE_RecoInfo(RecoInfo ri, int const (&pdgs)[N]) {
   double sum = 0;
 
   for (size_t p_it = 0; p_it < ri.RecVisibleEnergy.size(); ++p_it) {
     if (!std::count(pdgs, pdgs + N,
                     ri.TrueContribPDGs[p_it])) {  // If we don't care about this
                                                   // particle type.
       continue;
     }
     sum += ri.RecVisibleEnergy[p_it];
   }
 
   return sum;
 }
 
 template <size_t N>
 double SumVisE_RecoInfo_NotPdgs(RecoInfo ri, int const (&pdgs)[N]) {
   double sum = 0;
 
   for (size_t p_it = 0; p_it < ri.RecVisibleEnergy.size(); ++p_it) {
     if (std::count(pdgs, pdgs + N,
                    ri.TrueContribPDGs[p_it])) {  // If we know about this
                                                  // particle type.
       continue;
     }
     sum += ri.RecVisibleEnergy[p_it];
   }
 
   return sum;
 }
 
 //********************************************************************
 void Smearceptance_Tester::FillEventVariables(FitEvent *event) {
   //********************************************************************
 
   static int const cpipPDG[] = {211};
   static int const cpimPDG[] = {-211};
   static int const pi0PDG[] = {111};
   static int const ProtonPDG[] = {2212};
   static int const NeutronPDG[] = {2112};
   static int const GammaPDG[] = {22};
   static int const CLeptonPDGs[] = {11, 13, 15};
   static int const ExplicitPDGs[] = {211, -211, 111, 2212, 2112, 22,
                                      11,  13,   15,  12,   14,   16};
 
   RecoInfo *ri = smearceptor->Smearcept(event);
 
   HMFS_mu_true = TLorentzVector(0, 0, 0, 0);
   HMFS_mu_rec = TLorentzVector(0, 0, 0, 0);
   FitParticle *fsMu = event->GetHMFSMuon();
   if (fsMu) {
     HMFS_mu_true = fsMu->P4();
     HMFS_mu_rec = GetHMFSRecParticles(*ri, 13);
   }
 
   HMFS_pip_true = TLorentzVector(0, 0, 0, 0);
   HMFS_pip_rec = TLorentzVector(0, 0, 0, 0);
   FitParticle *fsPip = event->GetHMFSPiPlus();
   if (fsPip) {
     HMFS_pip_true = fsPip->P4();
     HMFS_pip_rec = GetHMFSRecParticles(*ri, 211);
   }
 
   HMFS_pim_true = TLorentzVector(0, 0, 0, 0);
   HMFS_pim_rec = TLorentzVector(0, 0, 0, 0);
   FitParticle *fsPim = event->GetHMFSPiMinus();
   if (fsPim) {
     HMFS_pim_true = fsPim->P4();
     HMFS_pim_rec = GetHMFSRecParticles(*ri, -211);
   }
 
   HMFS_cpi_true = TLorentzVector(0, 0, 0, 0);
   HMFS_cpi_rec = TLorentzVector(0, 0, 0, 0);
   if (fsPip || fsPim) {
     if (!fsPip) {
       HMFS_cpi_true = HMFS_pim_true;
       HMFS_cpi_rec = HMFS_pim_rec;
     } else if (!fsPim) {
       HMFS_cpi_true = HMFS_pip_true;
       HMFS_cpi_rec = HMFS_pip_rec;
     } else {
       HMFS_cpi_true =
           (fsPip->p2() > fsPim->p2()) ? HMFS_pip_true : HMFS_pim_true;
       HMFS_cpi_rec = (fsPip->p2() > fsPim->p2()) ? HMFS_pip_rec : HMFS_pim_rec;
     }
   }
 
   HMFS_p_true = TLorentzVector(0, 0, 0, 0);
   HMFS_p_rec = TLorentzVector(0, 0, 0, 0);
   FitParticle *fsP = event->GetHMFSProton();
   if (fsP) {
     HMFS_p_true = fsP->P4();
     HMFS_p_rec = GetHMFSRecParticles(*ri, 2212);
   }
 
   TLorentzVector FourMomentumTransfer =
       (event->GetHMISAnyLeptons()->P4() - event->GetHMFSAnyLeptons()->P4());
 
   Omega_true = FourMomentumTransfer.E();
   Q2_true = -1 * FourMomentumTransfer.Mag2();
   Mode_true = event->Mode;
 
   EISLep_true = event->GetHMISAnyLeptons()->E();
   KEFSHad_cpip_true = FitUtils::SumTE_PartVect(event->GetAllFSPiPlus());
   KEFSHad_cpim_true = FitUtils::SumTE_PartVect(event->GetAllFSPiMinus());
   KEFSHad_cpi_true = KEFSHad_cpip_true + KEFSHad_cpim_true;
   TEFSHad_pi0_true = FitUtils::SumTE_PartVect(event->GetAllFSPiZero());
   KEFSHad_p_true = FitUtils::SumKE_PartVect(event->GetAllFSProton());
   KEFSHad_n_true = FitUtils::SumKE_PartVect(event->GetAllFSNeutron());
   EFSHad_true =
       KEFSHad_cpi_true + TEFSHad_pi0_true + KEFSHad_p_true + KEFSHad_n_true;
   EFSChargedEMHad_true = KEFSHad_cpi_true + TEFSHad_pi0_true + KEFSHad_p_true;
 
   EFSLep_true = event->GetHMFSAnyLeptons()->E();
   EFSgamma_true = FitUtils::SumTE_PartVect(event->GetAllFSPhoton());
 
   PDGISLep_true = event->GetHMISAnyLeptons()->PDG();
   PDGFSLep_true = event->GetHMFSAnyLeptons()->PDG();
 
   Nprotons_true = event->GetAllFSProton().size();
   Nneutrons_true = event->GetAllFSNeutron().size();
   Ncpiplus_true = event->GetAllFSPiPlus().size();
   Ncpiminus_true = event->GetAllFSPiMinus().size();
   Ncpi_true = Ncpiplus_true + Ncpiminus_true;
   Npi0_true = event->GetAllFSPiZero().size();
 
   KEFSHad_cpip_rec =
       SumKE_RecoInfo(*ri, cpipPDG, PhysConst::mass_cpi * PhysConst::mass_MeV);
   KEFSHad_cpim_rec =
       SumKE_RecoInfo(*ri, cpimPDG, PhysConst::mass_cpi * PhysConst::mass_MeV);
   KEFSHad_cpi_rec = KEFSHad_cpip_rec + KEFSHad_cpim_rec;
 
   TEFSHad_pi0_rec =
       SumTE_RecoInfo(*ri, pi0PDG, PhysConst::mass_pi0 * PhysConst::mass_MeV);
   KEFSHad_p_rec = SumKE_RecoInfo(*ri, ProtonPDG,
                                  PhysConst::mass_proton * PhysConst::mass_MeV);
   KEFSHad_n_rec = SumKE_RecoInfo(*ri, NeutronPDG,
                                  PhysConst::mass_neutron * PhysConst::mass_MeV);
   EFSHad_rec =
       KEFSHad_cpi_rec + TEFSHad_pi0_rec + KEFSHad_p_rec + KEFSHad_n_rec;
 
   TLorentzVector FSLepMom_rec(0, 0, 0, 0);
   if (event->GetHMFSAnyLeptons()) {
     FSLepMom_rec = GetHMFSRecParticles(*ri, event->GetHMFSAnyLeptons()->PDG());
     EFSLep_rec = FSLepMom_rec.E();
   } else {
     EFSLep_rec = 0;
   }
 
   EFSVis_cpip = SumVisE_RecoInfo(*ri, cpipPDG);
   EFSVis_cpim = SumVisE_RecoInfo(*ri, cpimPDG);
   EFSVis_cpi = EFSVis_cpip + EFSVis_cpim;
   EFSVis_pi0 = SumVisE_RecoInfo(*ri, pi0PDG);
   EFSVis_p = SumVisE_RecoInfo(*ri, ProtonPDG);
   EFSVis_n = SumVisE_RecoInfo(*ri, NeutronPDG);
   EFSVis_gamma = SumVisE_RecoInfo(*ri, GammaPDG);
   EFSVis_other = SumVisE_RecoInfo_NotPdgs(*ri, ExplicitPDGs);
   EFSVis = EFSVis_cpi + EFSVis_pi0 + EFSVis_p + EFSVis_n + EFSVis_gamma;
 
   FSCLep_seen = CountNPdgsSeen(*ri, CLeptonPDGs);
   Nprotons_seen = CountNPdgsSeen(*ri, ProtonPDG);
   Nneutrons_seen = CountNPdgsSeen(*ri, NeutronPDG);
   Ncpip_seen = CountNPdgsSeen(*ri, cpipPDG);
   Ncpim_seen = CountNPdgsSeen(*ri, cpimPDG);
   Ncpi_seen = Ncpip_seen + Ncpim_seen;
   Npi0_seen = CountNPdgsSeen(*ri, pi0PDG);
   Nothers_seen = CountNNotPdgsSeen(*ri, ExplicitPDGs);
 
   if (FSCLep_seen && (FSLepMom_rec.Mag() > 1E-8)) {
     EISLep_QE_rec =
         FitUtils::EnuQErec(FSLepMom_rec.Mag() / 1000.0, FSLepMom_rec.CosTheta(),
                            34, PDGFSLep_true > 0) *
         1000.0;
   } else {
     EISLep_QE_rec = 0;
   }
   EISLep_LepHad_rec = EFSLep_rec + EFSHad_rec;
   EISLep_LepHadVis_rec = EFSLep_rec + EFSHad_rec + EFSVis;
 
   Nprotons_contributed = CountNPdgsContributed(*ri, ProtonPDG);
   Nneutrons_contributed = CountNPdgsContributed(*ri, NeutronPDG);
   Ncpip_contributed = CountNPdgsContributed(*ri, cpipPDG);
   Ncpim_contributed = CountNPdgsContributed(*ri, cpimPDG);
   Ncpi_contributed = Ncpip_contributed + Ncpim_contributed;
   Npi0_contributed = CountNPdgsContributed(*ri, pi0PDG);
   Ngamma_contributed = CountNPdgsContributed(*ri, GammaPDG);
   Nothers_contibuted = CountNNotPdgsContributed(*ri, ExplicitPDGs);
 
   Weight = event->RWWeight * event->InputWeight;
   RWWeight = event->RWWeight;
   InputWeight = event->InputWeight;
   FluxWeight = GetFluxHistogram()->GetBinContent(
                    GetFluxHistogram()->FindBin(EISLep_true)) /
                GetFluxHistogram()->Integral();
   EffWeight = ri->Weight;
 
   flagCCINC_true = PDGFSLep_true & 1;
   flagCC0Pi_true = (Ncpi_true + Npi0_true) == 0;
   flagCC1Pi_true = (Ncpi_true + Npi0_true) == 1;
 
   flagCCINC_rec = FSCLep_seen && PDGFSLep_true & 1;
   flagCC0Pi_rec = ((Ncpi_seen + Npi0_seen) == 0) && flagCCINC_rec;
   flagCC1Pi_rec = ((Ncpi_seen + Npi0_seen) == 1) && flagCCINC_rec;
 
   if (OutputSummaryTree) {
     // Fill the eventVariables Tree
     eventVariables->Fill();
   }
 
   if (RecoSmear) {
     RecoSmear->Fill(EISLep_true / 1000.0,
                     flagCCINC_rec ? EISLep_LepHadVis_rec / 1000.0 : -1, Weight);
     ETrueDistrib_noweight->Fill(EISLep_true / 1000.0,
                                 flagCCINC_true ? Weight : 0);
 
     ETrueDistrib->Fill(EISLep_true / 1000.0,
                        flagCCINC_true ? Weight * PredEvtRateWeight : 0);
 
     ERecDistrib->Fill(EISLep_LepHadVis_rec / 1000.0,
                       flagCCINC_rec ? Weight * PredEvtRateWeight : 0);
   }
 };
 
 //********************************************************************
 void Smearceptance_Tester::Write(std::string drawOpt) {
   //********************************************************************
 
   if (OutputSummaryTree) {
     // First save the TTree
     eventVariables->Write();
   }
 
   // Save Flux and Event Histograms too
   GetInput()->GetFluxHistogram()->Write();
   GetInput()->GetEventHistogram()->Write();
 
   if (!RecoSmear) {
     return;
   }
 
   TH2D *SmearMatrix_ev =
       static_cast<TH2D *>(RecoSmear->Clone("ELepHadVis_Smear_ev"));
 
   for (Int_t trueAxis_it = 1;
        trueAxis_it < RecoSmear->GetXaxis()->GetNbins() + 1; ++trueAxis_it) {
     double NEISLep = ETrueDistrib_noweight->GetBinContent(trueAxis_it);
 
     for (Int_t recoAxis_it = 1;
          recoAxis_it < RecoSmear->GetYaxis()->GetNbins() + 1; ++recoAxis_it) {
       if (NEISLep > std::numeric_limits<double>::epsilon()) {
         SmearMatrix_ev->SetBinContent(
             trueAxis_it, recoAxis_it,
             SmearMatrix_ev->GetBinContent(trueAxis_it, recoAxis_it) / NEISLep);
       }
     }
   }
 
   ETrueDistrib_noweight->Write();
   ETrueDistrib->Write();
   ERecDistrib->Write();
 
   RecoSmear->Write();
 
   SmearMatrix_ev->Write();
 
   TH2D *ResponseMatrix_ev =
       SmearceptanceUtils::SVDGetInverse(SmearMatrix_ev, SVDTruncation);
   ResponseMatrix_ev->SetName("ResponseMatrix_ev");
   ResponseMatrix_ev->Write();
 
 #ifdef DEBUG_SMEARTESTER
 
   TMatrixD SmearMatrix_ev_md = SmearceptanceUtils::GetMatrix(SmearMatrix_ev);
 
   TH1D *SmearedEvt = static_cast<TH1D *>(ERecDistrib->Clone());
   SmearedEvt->SetNameTitle("SmearedEvt", ";Rec E_{#nu}; count");
 
   SmearceptanceUtils::PushTH1ThroughMatrixWithErrors(
       ETrueDistrib, SmearedEvt, SmearMatrix_ev_md, 5000, false);
 
   SmearedEvt->Write();
 
   SmearedEvt->Scale(1, "width");
   SmearedEvt->SetName("SmearedEvt_bw");
   SmearedEvt->Write();
 
 #endif
 
   FitWeight *fw = FitBase::GetRW();
   if (fw->HasRWEngine(kOSCILLATION)) {
     OscWeightEngine *oscWE =
         dynamic_cast<OscWeightEngine *>(fw->GetRWEngine(kOSCILLATION));
     TGraph POsc;
 
     POsc.Set(1E4 - 1);
 
     double min = ETrueDistrib->GetXaxis()->GetBinLowEdge(1);
     double step = (ETrueDistrib->GetXaxis()->GetBinUpEdge(
                        ETrueDistrib->GetXaxis()->GetNbins()) -
                    ETrueDistrib->GetXaxis()->GetBinLowEdge(1)) /
                   double(1E4);
 
     for (size_t i = 1; i < 1E4; ++i) {
       double enu = min + i * step;
       double ow = oscWE->CalcWeight(enu, 14);
       if (ow != ow) {
         std::cout << "Bad osc weight for ENu: " << enu << std::endl;
       }
       POsc.SetPoint(i - 1, enu, ow);
     }
 
     POsc.Write("POsc", TObject::kOverwrite);
   }
 
   TMatrixD ResponseMatrix_evt_md =
       SmearceptanceUtils::GetMatrix(ResponseMatrix_ev);
 
   TH1D *Unfolded_enu_obs = static_cast<TH1D *>(ETrueDistrib->Clone());
   Unfolded_enu_obs->SetNameTitle("UnfoldedENu_evt", ";True E_{#nu};count");
 
   SmearceptanceUtils::PushTH1ThroughMatrixWithErrors(
       ERecDistrib, Unfolded_enu_obs, ResponseMatrix_evt_md, 5000, false);
 
   Unfolded_enu_obs->Write();
 
   Unfolded_enu_obs->Scale(1, "width");
   Unfolded_enu_obs->SetName("UnfoldedENu_evt_bw");
   Unfolded_enu_obs->Write();
 
   ETrueDistrib->Scale(1, "width");
   ETrueDistrib->SetName("ELep_rate_bw");
   ETrueDistrib->Write();
 
   ERecDistrib->Scale(1, "width");
   ERecDistrib->SetName("ELepRec_rate_bw");
   ERecDistrib->Write();
 }
 
 // -------------------------------------------------------------------
 // Purely MC Plot
 // Following functions are just overrides to handle this
 // -------------------------------------------------------------------
 //********************************************************************
 /// Everything is classed as signal...
 bool Smearceptance_Tester::isSignal(FitEvent *event) {
   //********************************************************************
   (void)event;
   return true;
 };
 
 //********************************************************************
 void Smearceptance_Tester::ScaleEvents() {
   //********************************************************************
   // Saving everything to a TTree so no scaling required
   return;
 }
 
 //********************************************************************
 void Smearceptance_Tester::ApplyNormScale(float norm) {
   //********************************************************************
 
   // Saving everything to a TTree so no scaling required
   fCurrentNorm = norm;
   return;
 }
 
 //********************************************************************
 void Smearceptance_Tester::FillHistograms() {
   //********************************************************************
   // No Histograms need filling........
   return;
 }
 
 //********************************************************************
 void Smearceptance_Tester::ResetAll() {
   //********************************************************************
   if (OutputSummaryTree) {
     eventVariables->Reset();
   }
   return;
 }
 
 //********************************************************************
 float Smearceptance_Tester::GetChi2() {
   //********************************************************************
   // No Likelihood to test, purely MC
   return 0.0;
 }
diff --git a/src/MINERvA/CMakeLists.txt b/src/MINERvA/CMakeLists.txt
index d8a5008..6e89fe5 100644
--- a/src/MINERvA/CMakeLists.txt
+++ b/src/MINERvA/CMakeLists.txt
@@ -1,167 +1,174 @@
 # Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret
 
 ################################################################################
 #    This file is part of NUISANCE.
 #
 #    NUISANCE is free software: you can redistribute it and/or modify
 #    it under the terms of the GNU General Public License as published by
 #    the Free Software Foundation, either version 3 of the License, or
 #    (at your option) any later version.
 #
 #    NUISANCE is distributed in the hope that it will be useful,
 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 #    GNU General Public License for more details.
 #
 #    You should have received a copy of the GNU General Public License
 #    along with NUISANCE.  If not, see <http://www.gnu.org/licenses/>.
 ################################################################################
 set(IMPLFILES
 MINERvA_CCQE_XSec_1DQ2_antinu.cxx
 MINERvA_CCQE_XSec_1DQ2_joint.cxx
 MINERvA_CCQE_XSec_1DQ2_nu.cxx
 
 MINERvA_CC0pi_XSec_1DEe_nue.cxx
 MINERvA_CC0pi_XSec_1DQ2_nue.cxx
 MINERvA_CC0pi_XSec_1DQ2_nu_proton.cxx
 MINERvA_CC0pi_XSec_1DThetae_nue.cxx
 
 MINERvA_CC1pi0_XSec_1DEnu_antinu.cxx
 MINERvA_CC1pi0_XSec_1DQ2_antinu.cxx
 MINERvA_CC1pi0_XSec_1Dpmu_antinu.cxx
 MINERvA_CC1pi0_XSec_1Dppi0_antinu.cxx
 MINERvA_CC1pi0_XSec_1DTpi0_antinu.cxx
 MINERvA_CC1pi0_XSec_1Dth_antinu.cxx
 MINERvA_CC1pi0_XSec_1Dthmu_antinu.cxx
 
 MINERvA_CC1pi0_XSec_1D_nu.cxx
 
 
 
 MINERvA_CC1pip_XSec_1DTpi_20deg_nu.cxx
 MINERvA_CC1pip_XSec_1DTpi_nu.cxx
 MINERvA_CC1pip_XSec_1Dth_20deg_nu.cxx
 MINERvA_CC1pip_XSec_1Dth_nu.cxx
 MINERvA_CC1pip_XSec_1D_2017Update.cxx
 
 MINERvA_CCNpip_XSec_1DEnu_nu.cxx
 MINERvA_CCNpip_XSec_1DQ2_nu.cxx
 MINERvA_CCNpip_XSec_1DTpi_nu.cxx
 MINERvA_CCNpip_XSec_1Dpmu_nu.cxx
 MINERvA_CCNpip_XSec_1Dth_nu.cxx
 MINERvA_CCNpip_XSec_1Dthmu_nu.cxx
 
 MINERvA_CCinc_XSec_2DEavq3_nu.cxx
 MINERvA_CCinc_XSec_1Dx_ratio.cxx
 MINERvA_CCinc_XSec_1DEnu_ratio.cxx
 MINERvA_CCinc_XSec_1Dx_nu.cxx
 MINERvA_CCinc_XSec_1DEnu_nu.cxx
 
 MINERvA_CCDIS_XSec_1Dx_ratio.cxx
 MINERvA_CCDIS_XSec_1DEnu_ratio.cxx
 MINERvA_CCDIS_XSec_1Dx_nu.cxx
 MINERvA_CCDIS_XSec_1DEnu_nu.cxx
 
 MINERvA_CC0pi_XSec_1DQ2_Tgt_nu.cxx
 MINERvA_CC0pi_XSec_1DQ2_TgtRatio_nu.cxx
 
 MINERvA_CC0pi_XSec_2Dptpx_nu.cxx
 MINERvA_CC0pi_XSec_2Dptpx_antinu.cxx
 
 MINERvA_CCCOHPI_XSec_1DEnu_nu.cxx
 MINERvA_CCCOHPI_XSec_1DEpi_nu.cxx
 MINERvA_CCCOHPI_XSec_1Dth_nu.cxx
 MINERvA_CCCOHPI_XSec_1DQ2_nu.cxx
 
 MINERvA_CCCOHPI_XSec_1DEnu_antinu.cxx
 MINERvA_CCCOHPI_XSec_1DEpi_antinu.cxx
 MINERvA_CCCOHPI_XSec_1Dth_antinu.cxx
 MINERvA_CCCOHPI_XSec_1DQ2_antinu.cxx
 
+MINERvA_CCCOHPI_XSec_joint.cxx
+
 MINERvAUtils.cxx
 MINERvA_SignalDef.cxx
 )
 
 set(HEADERFILES
 MINERvA_CCQE_XSec_1DQ2_antinu.h
 MINERvA_CCQE_XSec_1DQ2_joint.h
 MINERvA_CCQE_XSec_1DQ2_nu.h
 
 MINERvA_CC0pi_XSec_1DEe_nue.h
 MINERvA_CC0pi_XSec_1DQ2_nue.h
 MINERvA_CC0pi_XSec_1DQ2_nu_proton.h
 MINERvA_CC0pi_XSec_1DThetae_nue.h
 
 MINERvA_CC1pi0_XSec_1DEnu_antinu.h
 MINERvA_CC1pi0_XSec_1DQ2_antinu.h
 MINERvA_CC1pi0_XSec_1Dpmu_antinu.h
 MINERvA_CC1pi0_XSec_1Dppi0_antinu.h
 MINERvA_CC1pi0_XSec_1DTpi0_antinu.h
 MINERvA_CC1pi0_XSec_1Dth_antinu.h
 MINERvA_CC1pi0_XSec_1Dthmu_antinu.h
 
 MINERvA_CC1pip_XSec_1DTpi_20deg_nu.h
 MINERvA_CC1pip_XSec_1DTpi_nu.h
 MINERvA_CC1pip_XSec_1Dth_20deg_nu.h
 MINERvA_CC1pip_XSec_1Dth_nu.h
 
 MINERvA_CCNpip_XSec_1DEnu_nu.h
 MINERvA_CCNpip_XSec_1DQ2_nu.h
 MINERvA_CCNpip_XSec_1DTpi_nu.h
 MINERvA_CCNpip_XSec_1Dpmu_nu.h
 MINERvA_CCNpip_XSec_1Dth_nu.h
 MINERvA_CCNpip_XSec_1Dthmu_nu.h
 
 MINERvA_CCinc_XSec_2DEavq3_nu.h
 MINERvA_CCinc_XSec_1Dx_ratio.h
 MINERvA_CCinc_XSec_1DEnu_ratio.h
 MINERvA_CCinc_XSec_1Dx_nu.h
 MINERvA_CCinc_XSec_1DEnu_nu.h
 
 MINERvA_CCDIS_XSec_1Dx_ratio.h
 MINERvA_CCDIS_XSec_1DEnu_ratio.h
 MINERvA_CCDIS_XSec_1Dx_nu.h
 MINERvA_CCDIS_XSec_1DEnu_nu.h
 
 MINERvA_CC0pi_XSec_1DQ2_Tgt_nu.h
 MINERvA_CC0pi_XSec_1DQ2_TgtRatio_nu.h
 
 MINERvA_CC0pi_XSec_2Dptpx_nu.h
 MINERvA_CC0pi_XSec_2Dptpx_antinu.h
 
 MINERvA_CC1pip_XSec_1D_2017Update.h
 
 MINERvA_CCCOHPI_XSec_1DEnu_nu.h
 MINERvA_CCCOHPI_XSec_1DEpi_nu.h
 MINERvA_CCCOHPI_XSec_1Dth_nu.h
+MINERvA_CCCOHPI_XSec_1DQ2_nu.h
+
 MINERvA_CCCOHPI_XSec_1DEnu_antinu.h
 MINERvA_CCCOHPI_XSec_1DEpi_antinu.h
 MINERvA_CCCOHPI_XSec_1Dth_antinu.h
+MINERvA_CCCOHPI_XSec_1DQ2_antinu.h
+
+MINERvA_CCCOHPI_XSec_joint.h
 
 MINERvAUtils.h
 MINERvA_SignalDef.h
 MINERvAVariableBoxes.h
 )
 
 set(LIBNAME expMINERvA)
 
 if(CMAKE_BUILD_TYPE MATCHES DEBUG)
   add_library(${LIBNAME} STATIC ${IMPLFILES})
 else(CMAKE_BUILD_TYPE MATCHES RELEASE)
   add_library(${LIBNAME} SHARED ${IMPLFILES})
 endif()
 
 include_directories(${MINIMUM_INCLUDE_DIRECTORIES})
 
 set_target_properties(${LIBNAME} PROPERTIES VERSION
   "${NUISANCE_VERSION_MAJOR}.${NUISANCE_VERSION_MINOR}.${NUISANCE_VERSION_REVISION}")
 #set_target_properties(${LIBNAME} PROPERTIES LINK_FLAGS ${ROOT_LD_FLAGS})
 if(DEFINED PROJECTWIDE_EXTRA_DEPENDENCIES)
   add_dependencies(${LIBNAME} ${PROJECTWIDE_EXTRA_DEPENDENCIES})
 endif()
 
 install(TARGETS ${LIBNAME} DESTINATION lib)
 #Can uncomment this to install the headers... but is it really neccessary?
 #install(FILES ${HEADERFILES} DESTINATION include)
 
 set(MODULETargets ${MODULETargets} ${LIBNAME} PARENT_SCOPE)
diff --git a/src/MINERvA/MINERvAUtils.cxx b/src/MINERvA/MINERvAUtils.cxx
index 1770ea3..c9d20e2 100644
--- a/src/MINERvA/MINERvAUtils.cxx
+++ b/src/MINERvA/MINERvAUtils.cxx
@@ -1,312 +1,312 @@
 // Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret
 
 /*******************************************************************************
 *    This file is part of NUISANCE.
 *
 *    NUISANCE is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    NUISANCE is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with NUISANCE.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
 
 #include "MINERvAUtils.h"
-#include "FitParameters.h"
+
 #include "FitUtils.h"
 
 namespace MINERvAPar{
   double MINERvADensity    = FitPar::Config().GetParD("MINERvADensity");
   double MINERvARecoDist   = FitPar::Config().GetParD("MINERvARecoDist");
   double PenetratingMuonE = FitPar::Config().GetParD("PenetratingMuonEnergy");
   double NumRangeSteps    = FitPar::Config().GetParI("NumRangeSteps");
 }
 
 double MINERvAUtils::StoppedEfficiency(TH2D *effHist, FitParticle *nu, FitParticle *muon){
 
   double eff = 0.;
 
   if (!effHist) return eff;
   eff = effHist->GetBinContent(effHist->FindBin(FitUtils::p(muon), FitUtils::th(nu, muon)/TMath::Pi()*180.));
 
   return eff;
 }
 
 double MINERvAUtils::PenetratedEfficiency(FitParticle *nu, FitParticle *muon){
 
   double eff = 0.;
 
   if (FitUtils::th(nu, muon)/TMath::Pi()*180. > 50) eff = 0.;
   if (FitUtils::p(muon) < 1.4) eff = 0.;
 
   return eff;
 }
 
 double MINERvAUtils::BetheBlochCH(double E, double mass){
 
   double beta2 = 1 - mass*mass/E/E;
   double gamma = 1./sqrt(1-beta2);
   double mass_ratio = PhysConst::mass_electron*1000./mass;
   // Argh, have to remember to convert to MeV or you'll hate yourself!
   double I2 = 68.7e-6*68.7e-6; // mean excitation potential I
 
   
   double w_max = 2*PhysConst::mass_electron*1000.*beta2*gamma*gamma;
   w_max /= 1 + 2*gamma*mass_ratio + mass_ratio*mass_ratio;
 
 
   // Values taken from the PDG for K = 0.307075 MeV mol-1 cm2, mean ionization energy I = 68.7 eV (Polystyrene)
   // <Z/A> = 0.53768 (pdg.lbl.gov/AtomicNuclearProperties)
   double log_term = log(2*PhysConst::mass_electron*1000.*beta2*gamma*gamma*w_max/I2);
   double dedx = 0.307075*0.53768/beta2*(0.5*log_term - beta2);
 
   return dedx;
 }
 
 
 // This function returns an estimate of the range of the particle in scintillator.
 // It uses crude integration and Bethe-Bloch to approximate the range.
 double MINERvAUtils::RangeInScintillator(FitParticle* particle, int nsteps){
 
   // The particle energy
   double E  = particle->fP.E();
   double M  = particle->fP.M();
   double Ek = E - M;
 
   double step_size = Ek/float(nsteps+1);
   double range = 0;
 
   // Add an offset to make the integral a touch more accurate
   Ek -= step_size/2.;
   for (int i = 0; i < nsteps; ++i){
     
     double dEdx = MINERvAUtils::BetheBlochCH(Ek+M, M);
     
     Ek -= step_size;
     // dEdx is -ve
     range -= step_size/dEdx;
   }
 
   // Account for density of polystyrene
   range /= MINERvAPar::MINERvADensity;
 
   // Range estimate is in cm
   return fabs(range);
 }
 
 double MINERvAUtils::GetEDepositOutsideRangeInScintillator(FitParticle* particle, double rangelimit){
 
   // The particle energy
   double E  = particle->fP.E();
   double M  = particle->fP.M();
   double Ek = E - M;
 
   int nsteps = MINERvAPar::NumRangeSteps;
   double step_size = Ek/float(nsteps+1);
   double range = 0;
   double Ekinside = 0.0;
   double Ekstart = Ek;
 
   // Add an offset to make the integral a touch more accurate
   Ek -= step_size/2.;
   for (int i = 0; i < nsteps; ++i){
     
     double dEdx = MINERvAUtils::BetheBlochCH(Ek+M, M);
     
     Ek -= step_size;
     // dEdx is -ve
     range -= step_size/dEdx;
     if (fabs(range) / MINERvAPar::MINERvADensity < rangelimit){
       Ekinside = Ek;
     }
   }
 
   // Range estimate is in cm
   return Ekstart - Ekinside;
 } 
 
 double MINERvAUtils::GetEDepositInsideRangeInScintillator(FitParticle* particle, double rangelimit){
   // The particle energy
   double E  = particle->fP.E();
   double M  = particle->fP.M();
   double Ek = E - M;
 
   return Ek - GetEDepositOutsideRangeInScintillator(particle, rangelimit);
 }
 
 
 
 // Function to calculate the distance the particle travels in scintillator
 bool MINERvAUtils::PassesDistanceCut(FitParticle* beam, FitParticle* particle){
 
   double dist  = MINERvAUtils::RangeInScintillator(particle, MINERvAPar::NumRangeSteps);
   double zdist = dist*cos(FitUtils::th(beam, particle));
 
   if (abs(zdist) < MINERvAPar::MINERvARecoDist) return false;
   return true;
 }
 
 
 // Function to return the MainTrk
 int MINERvAUtils::GetMainTrack(FitEvent *event, TH2D *effHist, FitParticle*& mainTrk, double& weight, bool penetrated){
 
   FitParticle *nu   = event->GetNeutrinoIn();
   double highestMom = 0;
   int index = 0;
   mainTrk = NULL;
 
   // Loop over particles
   for (uint j = 2; j < event->Npart(); ++j){
 
     // Final state only!
     if (!(event->PartInfo(j))->fIsAlive) continue;
     if (event->PartInfo(j)->fNEUTStatusCode != 0) continue;
 
     int PID = event->PartInfo(j)->fPID;
 
     // Only consider pions, muons for now
     if (abs(PID) != 211 && abs(PID) != 13) continue;
 
     // Ignore if higher momentum tracks available
     if (FitUtils::p(event->PartInfo(j)) < highestMom) continue;
 
     // Okay, now this is highest momentum
     highestMom = FitUtils::p(event->PartInfo(j));
     weight  *= MINERvAUtils::StoppedEfficiency(effHist, nu, event->PartInfo(j));
     index   = j;
     mainTrk = event->PartInfo(j);
   } // end loop over particle stack
   
   return index;
 }
 
 
 void MINERvAUtils::GetOtherTrackInfo(FitEvent *event, int mainIndex, int& nProtons, int& nPiMus, int& nVertex, FitParticle*& secondTrk){
 
   // Reset everything
   nPiMus      = 0;
   nProtons    = 0;
   nVertex     = 0;
   secondTrk   = NULL;
 
   double highestMom  = 0.;
 
   // Loop over particles
   for (uint j = 2; j < event->Npart(); ++j){
 
     // Don't re-count the main track
     if (j == (uint)mainIndex) continue;
 
     // Final state only!
     if (!(event->PartInfo(j))->fIsAlive) continue;
     if (event->PartInfo(j)->fNEUTStatusCode != 0) continue;
 
     int PID = event->PartInfo(j)->fPID;
 
     // Only consider pions, muons, protons
     if (abs(PID) != 211 && PID != 2212 && abs(PID) != 13) continue;
 
     // Must be reconstructed as a track in SciBooNE
     if (MINERvAUtils::PassesDistanceCut(event->PartInfo(0), event->PartInfo(j))){
 
       // Keep track of the second highest momentum track
       if (FitUtils::p(event->PartInfo(j)) > highestMom){
 	highestMom = FitUtils::p(event->PartInfo(j));
 	secondTrk  = event->PartInfo(j);
       }
 
       if (PID == 2212) nProtons += 1;
       else nPiMus += 1;
     } else nVertex += 1;
 
   } // end loop over particle stack
 
   return;
 }
 
 
 // NOTE: need to adapt this to allow for penetrating events...
 // Simpler, but gives the same results as in Hirade-san's thesis
 double MINERvAUtils::CalcThetaPr(FitEvent *event, FitParticle *main, FitParticle *second, bool penetrated){
   
   FitParticle *nu   = event->GetNeutrinoIn();
 
   if (!main || !nu || !second) return -999;
 
   // Construct the vector p_pr = (-p_mux, -p_muy, Enurec - pmucosthetamu)
   // where p_mux, p_muy are the projections of the candidate muon momentum onto the x and y dimension respectively
   double pmu   = main->fP.Vect().Mag();
   double pmu_x = main->fP.Vect().X();
   double pmu_y = main->fP.Vect().Y();
 
   if (penetrated){
     pmu = 1400.;
     double ratio = 1.4/main->fP.Vect().Mag();
     TVector3 mod_mu = main->fP.Vect()*ratio;
     pmu_x = mod_mu.X();
     pmu_y = mod_mu.Y();
   }
 
   double Enuqe = FitUtils::EnuQErec(pmu/1000.,cos(FitUtils::th(nu, main)), 27., true)*1000.;
   double p_pr_z = Enuqe - pmu*cos(FitUtils::th(nu, main));
 
   TVector3 p_pr  = TVector3(-pmu_x, -pmu_y, p_pr_z);
   double thetapr = p_pr.Angle(second->fP.Vect())/TMath::Pi()*180.;
 
   return thetapr;
 }
 
 double MINERvAUtils::CalcThetaPi(FitEvent *event, FitParticle *second){
 
   FitParticle *nu   = event->GetNeutrinoIn();
 
   if (!second || !nu) return -999;
 
   double thetapi = FitUtils::th(nu, second)/TMath::Pi()*180.;
   return thetapi;
 }
 
 /// Functions to deal with the SB mode stacks
 MINERvAUtils::ModeStack::ModeStack(std::string name, std::string title, TH1* hist) {
   fName = name;
   fTitle = title;
 
   AddMode(0, "Other",   "Other", kGreen+2, 2, 3244);
   AddMode(1, "CCDIS",   "#nu_{#mu} CC DIS", kRed,     2, 3304);
   AddMode(2, "CCRES",   "#nu_{#mu} CC Resonant",  kGray+2,  2, 1001);
   AddMode(3, "CCQE",    "#nu_{#mu} CC QE",  kMagenta, 2, 1001);
   AddMode(4, "CC2P2H",  "#nu_{#mu} CC 2p2h", kAzure+1, 2, 1001);
 
   StackBase::SetupStack(hist);
 };
 
 int MINERvAUtils::ModeStack::ConvertModeToIndex(int mode){
   switch (abs(mode)){
   case 1: return 3;
   case 2: return 4;
   case 11:
   case 12:
   case 13: return 2;
   case 26: return 1;
   default: return 0;
   }
 };
 
 
 void MINERvAUtils::ModeStack::Fill(int mode, double x, double y, double z, double weight) {
   StackBase::FillStack(MINERvAUtils::ModeStack::ConvertModeToIndex(mode), x, y, z, weight);
 };
 
 void MINERvAUtils::ModeStack::Fill(FitEvent* evt, double x, double y, double z, double weight) {
   StackBase::FillStack(MINERvAUtils::ModeStack::ConvertModeToIndex(evt->Mode), x, y, z, weight);
 };
 
 void MINERvAUtils::ModeStack::Fill(BaseFitEvt* evt, double x, double y, double z, double weight) {
   StackBase::FillStack(MINERvAUtils::ModeStack::ConvertModeToIndex(evt->Mode), x, y, z, weight);
 };
diff --git a/src/MINERvA/MINERvA_CC0pi_XSec_1DQ2_TgtRatio_nu.cxx b/src/MINERvA/MINERvA_CC0pi_XSec_1DQ2_TgtRatio_nu.cxx
index 3494bc7..d524079 100644
--- a/src/MINERvA/MINERvA_CC0pi_XSec_1DQ2_TgtRatio_nu.cxx
+++ b/src/MINERvA/MINERvA_CC0pi_XSec_1DQ2_TgtRatio_nu.cxx
@@ -1,138 +1,138 @@
 // Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret
 
 /*******************************************************************************
 *    This file is part of NUISANCE.
 *
 *    NUISANCE is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    NUISANCE is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with NUISANCE.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
 
 #include "MINERvA_SignalDef.h"
 #include "MINERvA_CC0pi_XSec_1DQ2_TgtRatio_nu.h"
 
 
 //********************************************************************
 MINERvA_CC0pi_XSec_1DQ2_TgtRatio_nu::MINERvA_CC0pi_XSec_1DQ2_TgtRatio_nu(nuiskey samplekey) {
 //********************************************************************
 
   // Sample overview ---------------------------------------------------
   std::string descrip = "MINERvA_CC0pi_XSec_1DQ2_TgtRatio_nu sample. \n" \
                         "Target: Target;CH (2 INPUTS)\n" \
                         "Flux: MINERvA Forward Horn Current Numu \n" \
     "Signal: Any event with 1 muon, 1 proton p>450, no pions";
 
   // Setup common settings
   fSettings = LoadSampleSettings(samplekey);
   fSettings.SetDescription(descrip);
   fSettings.SetXTitle("Q^{2}_{QE} (GeV^{2})");
   fSettings.SetYTitle(" d#sigma/dQ^{2}_{QE} (cm^{2}/GeV^{2}/nucleon)");
   fSettings.SetAllowedTypes("FIX/DIAG,FULL/MASK", "FIX/FULL");
   fSettings.SetEnuRange(0.0, 100.0);
 
   // CCQELike plot information
   fSettings.SetTitle("MINERvA_CC0pi_XSec_1DQ2_TgtRatio_nu");
   
   fIsRatio = true;
   nBins = 5;
 
   target  = "";
   if (fSettings.Found("name", "TgtRatioFe")) target =   "Fe";
   else if (fSettings.Found("name", "TgtRatioPb")) target =   "Pb";
   else if      (fSettings.Found("name", "TgtRatioC")) target =   "C";
   else {
     ERR(FTL) << "target " << target << " was not found!" << std::endl;
     exit(-1);
   }
 
   std::string basedir = FitPar::GetDataBase() + "/MINERvA/CC0pi/";
   fSettings.SetDataInput(  basedir + "Q2_TgtRatio_" + target + "_data.txt");
   fSettings.SetCovarInput( basedir + "Q2_TgtRatio_" + target + "_covar.txt");
   FinaliseSampleSettings();
 
   // Get parsed input files
   if (fSubInFiles.size() != 2) ERR(FTL) << "MINERvA CC0pi ratio requires input files in format: NUMERATOR;DENOMINATOR" << std::endl;
   std::string inFileNUM = fSubInFiles.at(0);
   std::string inFileDEN = fSubInFiles.at(1);
 
   // Scaling Setup ---------------------------------------------------
   // Ratio of sub classes so non needed
 
   // Plot Setup -------------------------------------------------------
   SetDataFromTextFile( fSettings.GetDataInput() );
   SetCorrelationFromTextFile(fSettings.GetCovarInput());
 
 
   // Setup Experiments  -------------------------------------------------------
   std::string type = samplekey.GetS("type");
 
-  nuiskey samplekey_num = Config::CreateKey("sample");
-  samplekey_num.AddS("name", "MINERvA_CC0pi_XSec_1DQ2_Tgt" + target + "_nu");
-  samplekey_num.AddS("input", inFileNUM);
-  samplekey_num.AddS("type", type);
-
-  nuiskey samplekey_den = Config::CreateKey("sample");
-  samplekey_den.AddS("name", "MINERvA_CC0pi_XSec_1DQ2_TgtCH_nu");
-  samplekey_den.AddS("input", inFileDEN);
-  samplekey_den.AddS("type", type);
+  nuiskey samplekey_num = nuiskey("sample");
+  samplekey_num.Set("name", "MINERvA_CC0pi_XSec_1DQ2_Tgt" + target + "_nu");
+  samplekey_num.Set("input", inFileNUM);
+  samplekey_num.Set("type", type);
+
+  nuiskey samplekey_den = nuiskey("sample");
+  samplekey_den.Set("name", "MINERvA_CC0pi_XSec_1DQ2_TgtCH_nu");
+  samplekey_den.Set("input", inFileDEN);
+  samplekey_den.Set("type", type);
 
   NUM  = new MINERvA_CC0pi_XSec_1DQ2_Tgt_nu(samplekey_num);
   DEN  = new MINERvA_CC0pi_XSec_1DQ2_Tgt_nu(samplekey_den);
   NUM  ->SetNoData();
   DEN  ->SetNoData();
 
   // Add to chain for processing
   this->fSubChain.clear();
   this->fSubChain.push_back(NUM);
   this->fSubChain.push_back(DEN);
 
   // Final setup  ---------------------------------------------------
   FinaliseMeasurement();
 
 };
 
 //********************************************************************
 void MINERvA_CC0pi_XSec_1DQ2_TgtRatio_nu::MakePlots() {
 //********************************************************************
 
   UInt_t sample = 0;
   for (std::vector<MeasurementBase*>::const_iterator expIter = this->fSubChain.begin(); expIter != this->fSubChain.end(); expIter++) {
     MeasurementBase* exp = static_cast<MeasurementBase*>(*expIter);
 
     if      (sample == 0) this->NUM = static_cast<MINERvA_CC0pi_XSec_1DQ2_Tgt_nu*>(exp);
     else if (sample == 1) this->DEN = static_cast<MINERvA_CC0pi_XSec_1DQ2_Tgt_nu*>(exp);
     else break;
     sample++;
   }
 
   // Now make the ratio histogram
   TH1D* NUM_MC = (TH1D*)this->NUM->GetMCList().at(0)->Clone();
   TH1D* DEN_MC = (TH1D*)this->DEN->GetMCList().at(0)->Clone();
 
   for (int i = 0; i < nBins; ++i) {
     double binVal = 0;
     double binErr = 0;
 
     if (DEN_MC->GetBinContent(i + 1) && NUM_MC->GetBinContent(i + 1)) {
       binVal = NUM_MC->GetBinContent(i + 1) / DEN_MC->GetBinContent(i + 1);
       double fractErrNUM = NUM_MC->GetBinError(i + 1) / NUM_MC->GetBinContent(i + 1);
       double fractErrDEN = DEN_MC->GetBinError(i + 1) / DEN_MC->GetBinContent(i + 1);
       binErr = binVal * sqrt(fractErrNUM * fractErrNUM + fractErrDEN * fractErrDEN);
     }
 
     this->fMCHist->SetBinContent(i + 1, binVal);
     this->fMCHist->SetBinError(i + 1, binErr);
   }
 
   return;
 }
 
diff --git a/src/MINERvA/MINERvA_CC0pi_XSec_2Dptpx_nu.cxx b/src/MINERvA/MINERvA_CC0pi_XSec_2Dptpx_nu.cxx
index 0d88e2c..ac88a09 100755
--- a/src/MINERvA/MINERvA_CC0pi_XSec_2Dptpx_nu.cxx
+++ b/src/MINERvA/MINERvA_CC0pi_XSec_2Dptpx_nu.cxx
@@ -1,110 +1,110 @@
 //Adrian Orea
 //I used the file MINERvA_CCinc_XSec_2DEavq3_nu.cxx as a template
 //Also, I am fully aware of the naming typo (should be ptpz), but Everything is already named the same way so...
 
 //Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret
 
 /*******************************************************************************
 *    This file is part of NUISANCE.
 *
 *    NUISANCE is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    NUISANCE is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with NUISANCE.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
 
 /*
   Author : Adrian Orea
  */
 
 
 #include "MINERvA_SignalDef.h"
 #include "MINERvA_CC0pi_XSec_2Dptpx_nu.h"
 
 //********************************************************************
 MINERvA_CC0pi_XSec_2Dptpx_nu::MINERvA_CC0pi_XSec_2Dptpx_nu(nuiskey samplekey) {
 //********************************************************************
 
   // Sample overview ---------------------------------------------------
   std::string descrip = "MINERvA_CC0pi_XSec_2Dptpx_nu sample. \n" \
                         "Target: CH \n" \
                         "Flux: MINERvA Medium Energy FHC numu  \n" \
                         "Signal: CC-0pi \n";
 
   // Setup common settings
   fSettings = LoadSampleSettings(samplekey);
   fSettings.SetDescription(descrip);
-  fSettings.SetXTitle("p_{z} (GeV)");
-  fSettings.SetYTitle("p_{t} (GeV)");
+  fSettings.SetYTitle("p_{z} (GeV)");
+  fSettings.SetZTitle("p_{t} (GeV)");
   fSettings.SetZTitle("d^{2}#sigma/dP_{t}dP_{z} (cm^{2}/GeV^{2}/nucleon)");
   fSettings.SetAllowedTypes("FIX,FREE,SHAPE/FULL,DIAG/MASK", "FIX/FULL");
   fSettings.SetEnuRange(0.0, 100.0);
   fSettings.DefineAllowedTargets("C,H");
 
   // CCQELike plot information
   fSettings.SetTitle("MINERvA_CC0pi_XSec_2Dptpx_nu");
 
-  fSettings.SetDataInput(  FitPar::GetDataBase() + "MINERvA/CC0pi/CCQE_Neutrino_CV_Result.txt" );
-  fSettings.SetCovarInput( FitPar::GetDataBase() + "MINERvA/CC0pi/covar_2D.txt" );
-  fSettings.SetMapInput( FitPar::GetDataBase() + "MINERvA/CC0pi/map_2D.txt" );
+  fSettings.SetDataInput(  FitPar::GetDataBase() + "MINERvA/CC0pi_ptpz_nu/data2D.txt");
+  fSettings.SetCovarInput( FitPar::GetDataBase() + "MINERvA/CC0pi_ptpz_nu/covar.txt");
+  fSettings.SetMapInput( FitPar::GetDataBase() + "MINERvA/CC0pi_ptpz_nu/map2D.txt" );
   fSettings.DefineAllowedSpecies("numu");
   FinaliseSampleSettings();
 
   // Scaling Setup ---------------------------------------------------
   // ScaleFactor automatically setup for DiffXSec/cm2/Nucleon
-  fScaleFactor = (GetEventHistogram()->Integral("width") * 1E-37 / (fNEvents + 0.)) / this->TotalIntegratedFlux();
+  //  fScaleFactor = (GetEventHistogram()->Integral("width") * 1E-37 / (fNEvents + 0.)) / this->TotalIntegratedFlux();
+  fScaleFactor = (GetEventHistogram()->Integral("width") * 1E-38 / (fNEvents + 0.)) / this->TotalIntegratedFlux();
 
   // Plot Setup -------------------------------------------------------
   Double_t P_t[14] = {0,0.075,0.15,0.25,0.325,0.4,0.475,0.55,0.7,0.85,1.0,1.25,1.5,2.5};
   Double_t P_z[13] = {1.5,2.0,2.5,3.0,3.5,4.0,4.5,5.0,6.0,8.0,10.0,15.0,20.0};
-  CreateDataHistogram(13, P_z, 14, P_t);
+  CreateDataHistogram(14, P_t, 13, P_z);
+  
   SetDataValuesFromTextFile( fSettings.GetDataInput() );
-  ScaleData(1E-41);
+  //  fDataHist->Scale(1.0, "width");
 
   SetMapValuesFromText( fSettings.GetMapInput() );
-
-  SetCholDecompFromTextFile( fSettings.GetCovarInput() );
-  ScaleCovar(1E-16);
-
+  SetCovarFromTextFile( fSettings.GetCovarInput(), FitPar::Config().GetParI("CC0piNBINS") );
+  
   StatUtils::SetDataErrorFromCov(fDataHist, fFullCovar, fMapHist, 1E-38);
 
   // Final setup  ---------------------------------------------------
   FinaliseMeasurement();
 
 };
 
 //********************************************************************
 void MINERvA_CC0pi_XSec_2Dptpx_nu::FillEventVariables(FitEvent *event) {
 //********************************************************************
 
 // Checking to see if there is a Muon
   if (event->NumFSParticle(13) == 0) 
 	return;
 
   TLorentzVector Pmu  = event->GetHMFSParticle(13)->fP; //I Added this part
   Double_t px = Pmu.X()/1000;
   Double_t py = Pmu.Y()/1000;
   Double_t pz = Pmu.Z()/1000;
   Double_t pt = sqrt(px*px+py*py);
 
-// Set Hist Variables
-  fYVar = pt;
-  fXVar = pz;
+  // Set Hist Variables
+  fYVar = pz;
+  fXVar = pt;
 
   return;
 };
 
 //********************************************************************
 bool MINERvA_CC0pi_XSec_2Dptpx_nu::isSignal(FitEvent *event) {
 //********************************************************************
   return SignalDef::isCC0pi_MINERvAPTPZ(event, 14, EnuMin, EnuMax);
   
 };
diff --git a/src/MINERvA/MINERvA_CC1pi0_XSec_1D_nu.cxx b/src/MINERvA/MINERvA_CC1pi0_XSec_1D_nu.cxx
new file mode 100644
index 0000000..594a2c9
--- /dev/null
+++ b/src/MINERvA/MINERvA_CC1pi0_XSec_1D_nu.cxx
@@ -0,0 +1,320 @@
+// Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret
+
+/*******************************************************************************
+*    This file is part of NUISANCE.
+*
+*    NUISANCE is free software: you can redistribute it and/or modify
+*    it under the terms of the GNU General Public License as published by
+*    the Free Software Foundation, either version 3 of the License, or
+*    (at your option) any later version.
+*
+*    NUISANCE is distributed in the hope that it will be useful,
+*    but WITHOUT ANY WARRANTY; without even the implied warranty of
+*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*    GNU General Public License for more details.
+*
+*    You should have received a copy of the GNU General Public License
+*    along with NUISANCE.  If not, see <http://www.gnu.org/licenses/>.
+*******************************************************************************/
+#include "MINERvA_SignalDef.h"
+#include "MINERvA_CC1pi0_XSec_1D_nu.h"
+
+// Implementation of 2017 MINERvA numu CC1pi0
+// arxiv:1708.03723v1 hep-ex
+// c.wret14@imperial.ac.uk
+
+//********************************************************************
+void MINERvA_CC1pi0_XSec_1D_nu::SetupDataSettings(){
+//********************************************************************
+
+  // Set Distribution
+  // See header file for enum and some descriptions
+  std::string name = fSettings.GetS("name");
+  if      (!name.compare("MINERvA_CC1pi0_XSec_1DTpi_nu"))  fDist = kTpi;
+  else if (!name.compare("MINERvA_CC1pi0_XSec_1Dth_nu"))   fDist= kth;
+  else if (!name.compare("MINERvA_CC1pi0_XSec_1Dpmu_nu"))  fDist= kpmu;
+  else if (!name.compare("MINERvA_CC1pi0_XSec_1Dthmu_nu")) fDist= kthmu;
+  else if (!name.compare("MINERvA_CC1pi0_XSec_1DQ2_nu"))   fDist= kQ2;
+  else if (!name.compare("MINERvA_CC1pi0_XSec_1DEnu_nu"))  fDist= kEnu;
+  else if (!name.compare("MINERvA_CC1pi0_XSec_1DWexp_nu")) fDist= kWexp;
+  else if (!name.compare("MINERvA_CC1pi0_XSec_1DPPi0Mass_nu")) fDist= kPPi0Mass;
+  else if (!name.compare("MINERvA_CC1pi0_XSec_1DPPi0MassDelta_nu")) fDist= kPPi0MassDelta;
+  else if (!name.compare("MINERvA_CC1pi0_XSec_1DCosAdler_nu")) fDist= kCosAdler;
+  else if (!name.compare("MINERvA_CC1pi0_XSec_1DPhiAdler_nu")) fDist= kPhiAdler;
+
+  // Define what files to use from the dist
+  std::string datafile = "";
+  std::string corrfile = "";
+  std::string titles = "";
+  std::string distdescript = "";
+  // Set the default to essentially not be a cut on proton kinetic energy
+  // The Adler angles and reconstructed p,pi0 invariant mass have cuts on these
+  ProtonCut = 100;
+  // W exp is 1.8 GeV or lower (dealt with below)
+  WexpCut = 1.8;
+
+  // Load up the data
+  switch (fDist) {
+
+    case (kTpi):
+      datafile  = "data/XSec_Table_pi0_KE_xsec.csv";
+      corrfile = "corr/Correlation_Table_pi0_KE_xsec.csv";
+      titles    = "CC1#pi^{0};T_{#pi} (GeV);d#sigma/dT_{#pi} (cm^{2}/nucleon/GeV)";
+      break;
+
+    case (kth):
+      datafile  = "data/XSec_Table_pi0_theta_xsec.csv";
+      corrfile = "corr/Correlation_Table_pi0_theta_xsec.csv";
+      titles    = "CC1#pi^{0};#theta_{#pi} (degrees); d#sigma/d#theta_{#pi} (cm^{2}/nucleon/degree)";
+      break;
+
+    case (kpmu):
+      datafile  = "data/XSec_Table_muon_P_xsec.csv";
+      corrfile = "corr/Correlation_Table_muon_P_xsec.csv";
+      titles    = "CC1#pi^{0};p_{#mu} (GeV);d#sigma/dp_{#mu} (cm^{2}/nucleon/GeV)";
+      break;
+
+    case (kthmu):
+      datafile  = "data/XSec_Table_muon_theta_xsec.csv";
+      corrfile = "corr/Correlation_Table_muon_theta_xsec.csv";
+      titles    = "CC1#pi^{0};#theta_{#mu} (degrees);d#sigma/d#theta_{#mu} (cm^{2}/nucleon/degree)";
+      break;
+
+    case (kQ2):
+      datafile  = "data/XSec_Table_QSq_xsec.csv";
+      corrfile = "corr/Correlation_Table_QSq_xsec.csv";
+      titles    = "CC1#pi^{0};Q^{2} (GeV^{2});d#sigma/dQ^{2} (cm^{2}/nucleon/GeV^{2})";
+      break;
+
+    case (kEnu):
+      datafile  = "data/XSec_Table_Enu_xsec.csv";
+      corrfile = "corr/Correlation_Table_Enu_xsec.csv";
+      titles    = "CC1#pi^{0};E_{#nu} (GeV);#sigma(E_#nu) (cm^{2}/nucleon)";
+      break;
+
+    case (kWexp):
+      datafile  = "data/XSec_Table_W_xsec.csv";
+      corrfile = "corr/Correlation_Table_W_xsec.csv";
+      titles    = "CC1#pi^{0};W_{exp} (GeV);d#sigma/dW_{exp} (cm^{2}/nucleon/GeV)";
+      break;
+
+    case (kPPi0Mass):
+      datafile  = "data/XSec_Table_deltaInvMass_xsec.csv";
+      corrfile = "corr/Correlation_Table_deltaInvMass_xsec.csv";
+      titles    = "CC1#pi^{0}; M_{p#pi^{0}} (GeV); d#sigma/dM_{p#pi^{0}} (cm^{2}/nucleon/GeV)";
+      break;
+
+    case (kPPi0MassDelta):
+      datafile  = "data/XSec_Table_deltaInvMass_xsec_DeltaRich.csv";
+      corrfile = "corr/Correlation_Table_deltaInvMass_xsec_DeltaRich.csv";
+      titles    = "CC1#pi^{0}; M_{p#pi^{0}} W_{exp} < 1.4 (GeV); d#sigma/dM_{p#pi^{0}} (cm^{2}/nucleon/GeV)";
+      break;
+
+    case (kCosAdler):
+      datafile  = "data/XSec_Table_Delta_pi_theta_xsec.csv";
+      corrfile = "corr/Correlation_Table_Delta_pi_theta_xsec.csv";
+      titles    = "CC1#pi^{0}; cos#theta_{Adler}; d#sigma/dcos#thtea_{Adler} (cm^{2}/nucleon/0.1)";
+      break;
+
+    case (kPhiAdler):
+      datafile  = "data/XSec_Table_Delta_pi_phi_xsec.csv";
+      corrfile = "corr/Correlation_Table_Delta_pi_phi_xsec.csv";
+      titles    = "CC1#pi^{0}; #phi_{Adler} (degrees); d#sigma/d#phi_{Adler} (cm^{2}/nucleon/degree)";
+      break;
+
+    default:
+      THROW("Unknown Analysis Distribution : " << fDist);
+  }
+
+  // Set the Wexp and proton kinetic energy cuts depending on sample
+  // for Ppi0Mass distributions and Adler angles we require a proton of at least 100 MeV kinetic energy
+  if (fDist >= kPPi0Mass) {
+    ProtonCut = 0.1;
+    // 0.1 GeV proton kinetic energy cut
+    // Some distributions have a Wexp cut at 1.4 GeV which attempts to isolate delta production
+    if (fDist >= kPPi0MassDelta) {
+      WexpCut = 1.4;
+    }
+  }
+
+  // Only have xsec covariance (not shape only)
+
+  // Now setup each data distribution and description.
+  std::string descrip =  distdescript + \
+                         "Target: CH \n"				       \
+                         "Flux: MINERvA Forward Horn Current numu ONLY \n"  \
+                         "Signal: Any event with 1 muon, and 1pi0 in FS, no mesons, any nucleon(s). W < 1.8" \
+                         "Alt Signal: Add in requirement of 1 proton with 100 MeV and sometimes W < 1.4";
+
+  fSettings.SetDescription(descrip);
+  // Specify the data
+  fSettings.SetDataInput( GeneralUtils::GetTopLevelDir()+"/data/MINERvA/CC1pi0/2017_nu/" + datafile);
+  // And the correlations
+  fSettings.SetCovarInput(GeneralUtils::GetTopLevelDir()+"/data/MINERvA/CC1pi0/2017_nu/" + corrfile);
+  fSettings.SetTitle(  GeneralUtils::ParseToStr(titles,";")[0] );
+  fSettings.SetXTitle( GeneralUtils::ParseToStr(titles,";")[1] );
+  fSettings.SetYTitle( GeneralUtils::ParseToStr(titles,";")[2] );
+
+  return;
+}
+
+//********************************************************************
+MINERvA_CC1pi0_XSec_1D_nu::MINERvA_CC1pi0_XSec_1D_nu(nuiskey samplekey) {
+  //********************************************************************
+
+  // Define Sample Settings common to all data distributions
+  fSettings = LoadSampleSettings(samplekey);
+  fSettings.SetAllowedTypes("FIX,FREE,SHAPE/DIAG,FULL/NORM/MASK", "FIX/FULL");
+  // From 1.5 to 20 GeV Enu
+  fSettings.SetEnuRange(1.5, 20.0);
+  fSettings.DefineAllowedTargets("C,H");
+  fSettings.DefineAllowedSpecies("numu");
+  SetupDataSettings();
+  FinaliseSampleSettings();
+
+  // Scaling Setup ---------------------------------------------------
+  // If Enu setup scale factor for Enu Unfolded, otherwise use differential
+  if (fDist == kEnu) fScaleFactor = GetEventHistogram()->Integral("width") * double(1E-38) / double(fNEvents);
+  else fScaleFactor = GetEventHistogram()->Integral("width") * double(1E-38) / double(fNEvents) / TotalIntegratedFlux("width");
+
+  // Plot Setup -------------------------------------------------------
+  SetDataFromTextFile( fSettings.GetDataInput() );
+  // The errors come as a percent of the cross-section for this measurement so need rescaling
+  // Have set the fDataHist above so just loop over and set new errors
+  for (int i = 0; i < fDataHist->GetNbinsX(); ++i) {
+    fDataHist->SetBinError(i+1, (fDataHist->GetBinError(i+1)/100.0)*fDataHist->GetBinContent(i+1));
+  }
+  // And finally all the numbers are in units of 1E-40 so scale the histograms as such
+  fDataHist->Scale(1.0E-40);
+  // This measurement gives us a correlation matrix, so should set it up as such
+  SetCorrelationFromTextFile( fSettings.GetCovarInput() );
+
+  // Final setup  ---------------------------------------------------
+  FinaliseMeasurement();
+};
+
+//********************************************************************
+void MINERvA_CC1pi0_XSec_1D_nu::FillEventVariables(FitEvent *event) {
+  //********************************************************************
+
+  fXVar = -999.9;
+  // Need a neutral pion and a muon
+  if (event->NumFSParticle(111) == 0 || event->NumFSParticle(13) == 0) {
+    return;
+  }
+
+  // Get the TLorentzVectors from the event
+  TLorentzVector Pnu  = event->GetNeutrinoIn()->fP;
+  TLorentzVector Ppi0 = event->GetHMFSParticle(111)->fP;
+  TLorentzVector Pmu  = event->GetHMFSParticle(13)->fP;
+
+  // Pion kinetic energy
+  double Tpi     = (Ppi0.E() - Ppi0.Mag())/1.E3;
+  // Pion-neutrino angle
+  double th      = (180./M_PI)*FitUtils::th(Pnu, Ppi0);
+  // Muon momentum
+  double pmu     = Pmu.Vect().Mag()/1.E3;
+  // Muon-neutrino angle
+  double thmu    = (180.0/M_PI)*FitUtils::th(Pnu, Pmu);
+  // True Q2
+  double Q2      = fabs((Pmu - Pnu).Mag2()) / 1.E6;
+  // True Enu
+  double Enu     = Pnu.E() / 1.E3;
+  // Wexp (derived from "kinematic quantities" but uses EnuTrue)
+  double Wexp    = FitUtils::Wrec(Pnu, Pmu)/1.E3;
+
+  // Wexp cut of 1.8 GeV in signal definition
+  // N.B. the Adler angles and PPi0 mass requires this to be 1400
+  if (Wexp > WexpCut) return;
+
+  // Some distributions require the final state proton: check that it exists
+  if (fDist >= kPPi0Mass && event->NumFSParticle(2212) == 0) return;
+
+  // Fill the variables depending on the enums
+  switch (fDist) {
+    case kTpi:
+      fXVar = Tpi;
+      break;
+    case kth:
+      fXVar = th;
+      break;
+    case kpmu:
+      // Pmu has a theta_mu < 25degree cut
+      if (thmu > 25) return;
+      else fXVar = pmu;
+      break;
+    case kthmu:
+      // thmu has a theta_mu < 25degree cut
+      if (thmu > 25) return;
+      else fXVar = pmu;
+      fXVar = thmu;
+      break;
+    case kQ2:
+      fXVar = Q2;
+      break;
+    case kEnu:
+      fXVar = Enu;
+      break;
+    case kWexp:
+      fXVar = Wexp;
+      break;
+    // p, pi0 invariant mass with Wexp < 1.8 or Wexp < 1.4: already checked these above
+    case kPPi0Mass:
+    case kPPi0MassDelta:
+      {
+      // Get the proton
+      TLorentzVector Pprot = event->GetHMFSParticle(2212)->fP;
+      double Ppi0Mass = (Ppi0+Pprot).Mag()/1.E3;
+      fXVar = Ppi0Mass;
+      break;
+      }
+    // Cos theta Adler angle
+    case kCosAdler:
+      {
+      TLorentzVector Pprot = event->GetHMFSParticle(2212)->fP;
+      double CosThAdler = FitUtils::CosThAdler(Pnu, Pmu, Ppi0, Pprot);
+      fXVar = CosThAdler;
+      break;
+      }
+    // Phi Adler angle
+    case kPhiAdler:
+      {
+      TLorentzVector Pprot = event->GetHMFSParticle(2212)->fP;
+      double PhiAdler = FitUtils::PhiAdler(Pnu, Pmu, Ppi0, Pprot);
+      fXVar = PhiAdler;
+      break;
+      }
+    default:
+      THROW("DIST NOT FOUND : " << fDist);
+      break;
+  }
+
+};
+
+//********************************************************************
+bool MINERvA_CC1pi0_XSec_1D_nu::isSignal(FitEvent *event) {
+  //********************************************************************
+  // Some of the distributions require a proton with at least 100 MeV KE
+  if (fDist >= kPPi0Mass) {
+    // First of needs a proton in the final state
+    if (event->NumFSParticle(2212) == 0) return false;
+
+    // Needs to pass CC1pi0 signal definition
+    bool pass_cc1pi0 = SignalDef::isCC1pi0_MINERvA_nu(event, EnuMin, EnuMax);
+    if (!pass_cc1pi0) return false;
+
+    // And the proton needs at least 100 MeV kinetic energy
+    TLorentzVector Pprot = event->GetHMFSParticle(2212)->fP;
+    double ke = (Pprot.E() - Pprot.Mag())/1.E3;
+    if (pass_cc1pi0 && ke > ProtonCut) {
+      return true;
+    } else {
+      return false;
+    }
+  // The other distributions ahve a more generic "1mu, 1pi0, no mesons, any nucleon(s)"
+  // The W cut is instead made in FillEventVariables
+  } else {
+    return SignalDef::isCC1pi0_MINERvA_nu(event, EnuMin, EnuMax);
+  }
+}
+
diff --git a/src/MINERvA/MINERvA_CC1pi0_XSec_1D_nu.h b/src/MINERvA/MINERvA_CC1pi0_XSec_1D_nu.h
new file mode 100644
index 0000000..5247d84
--- /dev/null
+++ b/src/MINERvA/MINERvA_CC1pi0_XSec_1D_nu.h
@@ -0,0 +1,74 @@
+// Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret
+
+/*******************************************************************************
+*    This file is part of NUISANCE.
+*
+*    NUISANCE is free software: you can redistribute it and/or modify
+*    it under the terms of the GNU General Public License as published by
+*    the Free Software Foundation, either version 3 of the License, or
+*    (at your option) any later version.
+*
+*    NUISANCE is distributed in the hope that it will be useful,
+*    but WITHOUT ANY WARRANTY; without even the implied warranty of
+*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*    GNU General Public License for more details.
+*
+*    You should have received a copy of the GNU General Public License
+*    along with NUISANCE.  If not, see <http://www.gnu.org/licenses/>.
+*******************************************************************************/
+
+#ifndef MINERVA_CC1PI0_XSEC_1D_NU_H_SEEN
+#define MINERVA_CC1PI0_XSEC_1D_NU_H_SEEN
+
+#include "Measurement1D.h"
+
+// Implementation of 2017 MINERvA numu CC1pi0
+// arxiv:1708.03723v1 hep-ex
+// c.wret14@imperial.ac.uk
+
+class MINERvA_CC1pi0_XSec_1D_nu : public Measurement1D {
+public:
+  MINERvA_CC1pi0_XSec_1D_nu(nuiskey samplekey);
+  virtual ~MINERvA_CC1pi0_XSec_1D_nu() {};
+
+  void SetupDataSettings();
+  void FillEventVariables(FitEvent *event);
+  bool isSignal(FitEvent *event);
+  
+  private:
+  int fDist;
+
+  double WexpCut;
+  double ProtonCut;
+  
+  // The enums for the different distributions
+  // P.S. the order __IS__ important: after Wexp we require a proton and impose other cuts
+  enum DataDistribution {
+    // Pion kinetic energy
+    kTpi,
+    // Pion-neutrino angle
+    kth,
+    // Muon momentum
+    kpmu,
+    // Muon-neutrino angle
+    kthmu,
+    // True Q2
+    kQ2,
+    // True Enu
+    kEnu,
+    // And the interesting distributions ^_^
+    // Wexperimental
+    kWexp,
+    // p, pi0 invariant mass with Wexp < 1.8
+    kPPi0Mass,
+    // p, pi0 invariant mass with Wexp < 1.4
+    kPPi0MassDelta,
+    // Cos theta Adler angle
+    kCosAdler,
+    // Phi Adler angle
+    kPhiAdler
+  } CC1pi0_DataDistributions;
+
+};
+
+#endif
diff --git a/src/Reweight/CMakeLists.txt b/src/Reweight/CMakeLists.txt
index 685133c..55b9fef 100644
--- a/src/Reweight/CMakeLists.txt
+++ b/src/Reweight/CMakeLists.txt
@@ -1,81 +1,83 @@
 # Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret
 
 ################################################################################
 #    This file is part of NUISANCE.
 #
 #    NUISANCE is free software: you can redistribute it and/or modify
 #    it under the terms of the GNU General Public License as published by
 #    the Free Software Foundation, either version 3 of the License, or
 #    (at your option) any later version.
 #
 #    NUISANCE is distributed in the hope that it will be useful,
 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 #    GNU General Public License for more details.
 #
 #    You should have received a copy of the GNU General Public License
 #    along with NUISANCE.  If not, see <http://www.gnu.org/licenses/>.
 ################################################################################
 set(IMPLFILES
 GlobalDialList.cxx
 FitWeight.cxx
 WeightEngineBase.cxx
 NEUTWeightEngine.cxx
 NuWroWeightEngine.cxx
 GENIEWeightEngine.cxx
 WeightUtils.cxx
 SampleNormEngine.cxx
 LikelihoodWeightEngine.cxx
 SplineWeightEngine.cxx
 NUISANCESyst.cxx
 T2KWeightEngine.cxx
 NUISANCEWeightEngine.cxx
 NUISANCEWeightCalcs.cxx
 NIWGWeightEngine.cxx
 OscWeightEngine.cxx
 MINERvAWeightCalcs.cxx
+weightRPA.h
 )
 
 set(HEADERFILES
 GlobalDialList.h
 FitWeight.h
 WeightEngineBase.h
 NEUTWeightEngine.h
 NuWroWeightEngine.h
 GENIEWeightEngine.h
 WeightUtils.h
 SampleNormEngine.h
 LikelihoodWeightEngine.h
 SplineWeightEngine.h
 NUISANCESyst.h
 T2KWeightEngine.h
 NUISANCEWeightEngine.h
 NUISANCEWeightCalcs.h
 NIWGWeightEngine.h
 OscWeightEngine.h
 MINERvAWeightCalcs.h
+weightRPA.h
 )
 
 set(LIBNAME Reweight)
 
 if(CMAKE_BUILD_TYPE MATCHES DEBUG)
   add_library(${LIBNAME} STATIC ${IMPLFILES})
 else(CMAKE_BUILD_TYPE MATCHES RELEASE)
   add_library(${LIBNAME} SHARED ${IMPLFILES})
 endif()
 
 include_directories(${MINIMUM_INCLUDE_DIRECTORIES})
 
 set_target_properties(${LIBNAME} PROPERTIES VERSION
   "${ExtFit_VERSION_MAJOR}.${ExtFit_VERSION_MINOR}.${ExtFit_VERSION_REVISION}")
 #set_target_properties(${LIBNAME} PROPERTIES LINK_FLAGS ${ROOT_LD_FLAGS})
 
 if(DEFINED PROJECTWIDE_EXTRA_DEPENDENCIES)
   add_dependencies(${LIBNAME} ${PROJECTWIDE_EXTRA_DEPENDENCIES})
 endif()
 
 install(TARGETS ${LIBNAME} DESTINATION lib)
 #Can uncomment this to install the headers... but is it really neccessary?
 install(FILES ${HEADERFILES} DESTINATION include)
 
 set(MODULETargets ${MODULETargets} ${LIBNAME} PARENT_SCOPE)
diff --git a/src/Reweight/GENIEWeightEngine.cxx b/src/Reweight/GENIEWeightEngine.cxx
index 4b4ceb1..8e0aab6 100644
--- a/src/Reweight/GENIEWeightEngine.cxx
+++ b/src/Reweight/GENIEWeightEngine.cxx
@@ -1,231 +1,244 @@
 #include "GENIEWeightEngine.h"
 
 GENIEWeightEngine::GENIEWeightEngine(std::string name) {
 #ifdef __GENIE_ENABLED__
 
 	// Setup the NEUT Reweight engien
 	fCalcName = name;
 	LOG(FIT) << "Setting up GENIE RW : " << fCalcName << std::endl;
 
 	// Create RW Engine suppressing cout
 	StopTalking();
 	fGenieRW = new genie::rew::GReWeight();
 
 	// Get List of Vetos (Just for debugging)
 	std::string rw_engine_list = FitPar::Config().GetParS("FitWeight.fGenieRW_veto");
 	bool xsec_ncel = rw_engine_list.find("xsec_ncel") == std::string::npos;
 	bool xsec_ccqe = rw_engine_list.find("xsec_ccqe") == std::string::npos;
 	bool xsec_coh = rw_engine_list.find("xsec_coh") == std::string::npos;
 	bool xsec_nnres = rw_engine_list.find("xsec_nonresbkg") == std::string::npos;
 	bool xsec_nudis = rw_engine_list.find("nuclear_dis") == std::string::npos;
 	bool xsec_resdec = rw_engine_list.find("hadro_res_decay") == std::string::npos;
 	bool xsec_fzone = rw_engine_list.find("hadro_intranuke") == std::string::npos;
 	bool xsec_intra = rw_engine_list.find("hadro_fzone") == std::string::npos;
 	bool xsec_agky = rw_engine_list.find("hadro_agky") == std::string::npos;
 	bool xsec_qevec = rw_engine_list.find("xsec_ccqe_vec") == std::string::npos;
 	bool xsec_dis = rw_engine_list.find("xsec_dis") == std::string::npos;
 	bool xsec_nc = rw_engine_list.find("xsec_nc") == std::string::npos;
 	bool xsec_ccres = rw_engine_list.find("xsec_ccres") == std::string::npos;
 	bool xsec_ncres = rw_engine_list.find("xsec_ncres") == std::string::npos;
 	bool xsec_nucqe = rw_engine_list.find("nuclear_qe") == std::string::npos;
 	bool xsec_qeaxial = rw_engine_list.find("xsec_ccqe_axial") == std::string::npos;
 
 	// Now actually add the RW Calcs
 	if (xsec_ncel)
 		fGenieRW->AdoptWghtCalc("xsec_ncel", new genie::rew::GReWeightNuXSecNCEL);
-	if (xsec_ccqe)
-		fGenieRW->AdoptWghtCalc("xsec_ccqe", new genie::rew::GReWeightNuXSecCCQE);
-	if (xsec_coh)
-		fGenieRW->AdoptWghtCalc("xsec_coh", new genie::rew::GReWeightNuXSecCOH);
+	if (xsec_ccqe){
+	  fGenieRW->AdoptWghtCalc("xsec_ccqe", new genie::rew::GReWeightNuXSecCCQE);
+	  //	  (dynamic_cast<GReWeightNuXSecCCQE*> (fGenieRW->WghtCalc("xsec_ccqe")))
+	  //	    ->SetXSecModel( FitPar::Config().GetParS("GENIEXSecModelCCQE") );
+	}
+	if (xsec_coh){
+	  fGenieRW->AdoptWghtCalc("xsec_coh", new genie::rew::GReWeightNuXSecCOH());
+	  //	  (dynamic_cast<GReWeightNuXSecCOH*> (fGenieRW->WghtCalc("xsec_coh")))
+	  //	    ->SetXSecModel( FitPar::Config().GetParS("GENIEXSecModelCOH") );
+	}
+
 	if (xsec_nnres)
 		fGenieRW->AdoptWghtCalc("xsec_nonresbkg",
 		                        new genie::rew::GReWeightNonResonanceBkg);
 	if (xsec_nudis)
 		fGenieRW->AdoptWghtCalc("nuclear_dis", new genie::rew::GReWeightDISNuclMod);
 	if (xsec_resdec)
 		fGenieRW->AdoptWghtCalc("hadro_res_decay",
 		                        new genie::rew::GReWeightResonanceDecay);
 	if (xsec_fzone)
 		fGenieRW->AdoptWghtCalc("hadro_fzone", new genie::rew::GReWeightFZone);
 	if (xsec_intra)
 		fGenieRW->AdoptWghtCalc("hadro_intranuke", new genie::rew::GReWeightINuke);
 	if (xsec_agky)
 		fGenieRW->AdoptWghtCalc("hadro_agky", new genie::rew::GReWeightAGKY);
 	if (xsec_qevec)
 		fGenieRW->AdoptWghtCalc("xsec_ccqe_vec",
 		                        new genie::rew::GReWeightNuXSecCCQEvec);
 #if __GENIE_VERSION__ >= 212
 	if (xsec_qeaxial)
 		fGenieRW->AdoptWghtCalc("xsec_ccqe_axial",
 		                        new genie::rew::GReWeightNuXSecCCQEaxial);
 #endif
 
 	if (xsec_dis)
 		fGenieRW->AdoptWghtCalc("xsec_dis", new genie::rew::GReWeightNuXSecDIS);
 	if (xsec_nc)
 		fGenieRW->AdoptWghtCalc("xsec_nc", new genie::rew::GReWeightNuXSecNC);
-	if (xsec_ccres)
+	if (xsec_ccres){
+#if __GENIE_VERSION__ < 213
 		fGenieRW->AdoptWghtCalc("xsec_ccres", new genie::rew::GReWeightNuXSecCCRES);
+#else
+		fGenieRW->AdoptWghtCalc("xsec_ccres", new genie::rew::GReWeightNuXSecCCRES( FitPar::Config().GetParS("GENIEXSecModelCCRES"), "Default"));
+#endif
+	}
+
 	if (xsec_ncres)
 		fGenieRW->AdoptWghtCalc("xsec_ncres", new genie::rew::GReWeightNuXSecNCRES);
 	if (xsec_nucqe)
 		fGenieRW->AdoptWghtCalc("nuclear_qe", new genie::rew::GReWeightFGM);
 
 	GReWeightNuXSecCCQE * rwccqe =
 	    dynamic_cast<GReWeightNuXSecCCQE *> (fGenieRW->WghtCalc("xsec_ccqe"));
 	rwccqe->SetMode(GReWeightNuXSecCCQE::kModeMa);
 
 	// Default to include shape and normalization changes for CCRES (can be changed downstream if desired)
 	GReWeightNuXSecCCRES * rwccres =
 	    dynamic_cast<GReWeightNuXSecCCRES *> (fGenieRW->WghtCalc("xsec_ccres"));
 	std::string marestype = FitPar::Config().GetParS("GENIEWeightEngine_CCRESMode");
 	if (!marestype.compare("kModeNormAndMaMvShape")){ rwccres->SetMode(GReWeightNuXSecCCRES::kModeNormAndMaMvShape); }
 	else if (!marestype.compare("kModeMaMv")){ rwccres->SetMode(GReWeightNuXSecCCRES::kModeMaMv); }
 	else {
 	  THROW("Unkown MARES Mode in GENIE Weight Engine : " << marestype );
 	}
 
 	// Default to include shape and normalization changes for NCRES (can be changed downstream if desired)
 	GReWeightNuXSecNCRES * rwncres =
 	    dynamic_cast<GReWeightNuXSecNCRES *> (fGenieRW->WghtCalc("xsec_ncres"));
 	rwncres->SetMode(GReWeightNuXSecNCRES::kModeMaMv);
 
 	// Default to include shape and normalization changes for DIS (can be changed downstream if desired)
 	GReWeightNuXSecDIS * rwdis =
 	    dynamic_cast<GReWeightNuXSecDIS *> (fGenieRW->WghtCalc("xsec_dis"));
 	rwdis->SetMode(GReWeightNuXSecDIS::kModeABCV12u);
 
 	// Set Abs Twk Config
 	fIsAbsTwk = (FitPar::Config().GetParB("setabstwk"));
 
 	// allow cout again
 	StartTalking();
 
 #else
 	ERR(FTL) << "GENIE RW NOT ENABLED" << std::endl;
 #endif
 };
 
 
 void GENIEWeightEngine::IncludeDial(std::string name, double startval) {
 #ifdef __GENIE_ENABLED__
 
 	// Get First enum
 	int nuisenum = Reweight::ConvDial(name, kGENIE);
 
 	// Setup Maps
 	fEnumIndex[nuisenum];// = std::vector<size_t>(0);
 	fNameIndex[name]; // = std::vector<size_t>(0);
 
 	// Split by commas
 	std::vector<std::string> allnames = GeneralUtils::ParseToStr(name, ",");
 	for (uint i = 0; i < allnames.size(); i++) {
 		std::string singlename = allnames[i];
 
 		// Get RW
 		genie::rew::GSyst_t rwsyst = GSyst::FromString(singlename);
 
 		// Fill Maps
 		int index = fValues.size();
 		fValues.push_back(0.0);
 		fGENIESysts.push_back(rwsyst);
 
 		// Initialize dial
 		std::cout << "Registering " << singlename << " from " << name << std::endl;
 		fGenieRW->Systematics().Init( fGENIESysts[index] );
 
 		// If Absolute
 		if (fIsAbsTwk) {
 			GSystUncertainty::Instance()->SetUncertainty( rwsyst, 1.0, 1.0 );
 		}
 
 		// Setup index
 		fEnumIndex[nuisenum].push_back(index);
 		fNameIndex[name].push_back(index);
 
 	}
 
 	// Set Value if given
 	if (startval != -999.9) {
 		SetDialValue(nuisenum, startval);
 	}
 #endif
 };
 
 
 void GENIEWeightEngine::SetDialValue(int nuisenum, double val) {
 #ifdef __GENIE_ENABLED__
 	std::vector<size_t> indices = fEnumIndex[nuisenum];
 	for (uint i = 0; i < indices.size(); i++) {
 		fValues[indices[i]] = val;
 		fGenieRW->Systematics().Set( fGENIESysts[indices[i]], val);
 	}
 #endif
 }
 
 void GENIEWeightEngine::SetDialValue(std::string name, double val) {
 #ifdef __GENIE_ENABLED__
 	std::vector<size_t> indices = fNameIndex[name];
 	for (uint i = 0; i < indices.size(); i++) {
 		fValues[indices[i]] = val;
 		fGenieRW->Systematics().Set(fGENIESysts[indices[i]], val);
 	}
 #endif
 }
 
 void GENIEWeightEngine::Reconfigure(bool silent) {
 #ifdef __GENIE_ENABLED__
 	// Hush now...
 	if (silent) StopTalking();
 
 	// Reconf
 	fGenieRW->Reconfigure();
 	fGenieRW->Print();
 	
 	// Shout again
 	if (silent) StartTalking();
 #endif
 }
 
 
 double GENIEWeightEngine::CalcWeight(BaseFitEvt* evt) {
 	double rw_weight = 1.0;
 
 #ifdef __GENIE_ENABLED__
 	// Skip Non GENIE
 	if (evt->fType != kGENIE) return 1.0;
 
 	// Make nom weight
 	if (!evt) {
 		THROW("evt not found : " << evt);
 	}
 
 	if (!(evt->genie_event)) {
 		THROW("evt->genie_event not found!" << evt->genie_event);
 	}
 
 	if (!(evt->genie_event->event)) {
 		THROW("evt->genie_event->event GHepRecord not found!" << (evt->genie_event->event));
 	}
 
 	if (!fGenieRW) {
 		THROW("GENIE RW Not Found!" << fGenieRW);
 	}
 
 	rw_weight = fGenieRW->CalcWeight(*(evt->genie_event->event));
 	//	std::cout << "Returning GENIE Weight for electron scattering = " << rw_weight << std::endl;
 #endif
 
 	// Return rw_weight
 	return rw_weight;
 }
 
 
 
 
 
 
 
 
 
 
diff --git a/src/Reweight/MINERvAWeightCalcs.cxx b/src/Reweight/MINERvAWeightCalcs.cxx
index ebd453a..00953a4 100644
--- a/src/Reweight/MINERvAWeightCalcs.cxx
+++ b/src/Reweight/MINERvAWeightCalcs.cxx
@@ -1,469 +1,554 @@
 #ifdef __MINERVA_RW_ENABLED__
 #ifdef __GENIE_ENABLED__
 
 #include "MINERvAWeightCalcs.h"
 #include "BaseFitEvt.h"
 
 namespace nuisance {
 namespace reweight {
 
 
 //*******************************************************
 MINERvAReWeight_QE::MINERvAReWeight_QE() {
   //*******************************************************
   fTwk_NormCCQE = 0.0;
   fDef_NormCCQE = 1.0;
   fCur_NormCCQE = fDef_NormCCQE;
 }
 
 MINERvAReWeight_QE::~MINERvAReWeight_QE(){};
 
 double MINERvAReWeight_QE::CalcWeight(BaseFitEvt* evt) {
   // Check GENIE
   if (evt->fType != kGENIE) return 1.0;
 
   // Extract the GENIE Record
   GHepRecord* ghep = static_cast<GHepRecord*>(evt->genie_event->event);
   const Interaction* interaction = ghep->Summary();
   const InitialState& init_state = interaction->InitState();
   const ProcessInfo& proc_info = interaction->ProcInfo();
   const Target& tgt = init_state.Tgt();
 
   // If the event is not QE this Calc doesn't handle it
   if (!proc_info.IsQuasiElastic()) return 1.0;
 
   // WEIGHT CALCULATIONS -------------
   double w = 1.0;
 
   // CCQE Dial
   if (!proc_info.IsWeakCC()) w *= fCur_NormCCQE;
 
   // Return Combined Weight
   return w;
 }
 
 void MINERvAReWeight_QE::SetDialValue(std::string name, double val) {
   SetDialValue(Reweight::ConvDial(name, kCUSTOM), val);
 }
 
 void MINERvAReWeight_QE::SetDialValue(int rwenum, double val) {
   // Check Handled
   int curenum = rwenum % 1000;
   if (!IsHandled(curenum)) return;
 
   // Set Values
   if (curenum == kMINERvARW_NormCCQE) {
     fTwk_NormCCQE = val;
     fCur_NormCCQE = fDef_NormCCQE + fTwk_NormCCQE;
   }
 
   // Define Tweaked
   fTweaked = ((fTwk_NormCCQE != 0.0));
 }
 
 bool MINERvAReWeight_QE::IsHandled(int rwenum) {
   int curenum = rwenum % 1000;
 
   switch (curenum) {
     case kMINERvARW_NormCCQE:
       return true;
     default:
       return false;
   }
 }
 
 
 //*******************************************************
 MINERvAReWeight_MEC::MINERvAReWeight_MEC() {
   //*******************************************************
   fTwk_NormCCMEC = 0.0;
   fDef_NormCCMEC = 1.0;
   fCur_NormCCMEC = fDef_NormCCMEC;
 }
 
 MINERvAReWeight_MEC::~MINERvAReWeight_MEC(){};
 
 double MINERvAReWeight_MEC::CalcWeight(BaseFitEvt* evt) {
   // Check GENIE
   if (evt->fType != kGENIE) return 1.0;
 
   // Extract the GENIE Record
   GHepRecord* ghep = static_cast<GHepRecord*>(evt->genie_event->event);
   const Interaction* interaction = ghep->Summary();
   const InitialState& init_state = interaction->InitState();
   const ProcessInfo& proc_info = interaction->ProcInfo();
   const Target& tgt = init_state.Tgt();
 
   // If the event is not MEC this Calc doesn't handle it
   if (!proc_info.IsMEC()) return 1.0;
 
   // WEIGHT CALCULATIONS -------------
   double w = 1.0;
 
   // CCMEC Dial
   if (!proc_info.IsWeakCC()) w *= fCur_NormCCMEC;
 
   // Return Combined Weight
   return w;
 }
 
 void MINERvAReWeight_MEC::SetDialValue(std::string name, double val) {
   SetDialValue(Reweight::ConvDial(name, kCUSTOM), val);
 }
 
 void MINERvAReWeight_MEC::SetDialValue(int rwenum, double val) {
   // Check Handled
   int curenum = rwenum % 1000;
   if (!IsHandled(curenum)) return;
 
   // Set Values
   if (curenum == kMINERvARW_NormCCMEC) {
     fTwk_NormCCMEC = val;
     fCur_NormCCMEC = fDef_NormCCMEC + fTwk_NormCCMEC;
   }
 
   // Define Tweaked
   fTweaked = ((fTwk_NormCCMEC != 0.0));
 }
 
 bool MINERvAReWeight_MEC::IsHandled(int rwenum) {
   int curenum = rwenum % 1000;
 
   switch (curenum) {
     case kMINERvARW_NormCCMEC:
       return true;
     default:
       return false;
   }
 }
 
 //*******************************************************
 MINERvAReWeight_RES::MINERvAReWeight_RES() {
   //*******************************************************
   fTwk_NormCCRES = 0.0;
   fDef_NormCCRES = 1.0;
   fCur_NormCCRES = fDef_NormCCRES;
 }
 
 MINERvAReWeight_RES::~MINERvAReWeight_RES(){};
 
 double MINERvAReWeight_RES::CalcWeight(BaseFitEvt* evt) {
 
   // std::cout << "Caculating RES" << std::endl;
   // Check GENIE
   if (evt->fType != kGENIE) return 1.0;
 
   // Extract the GENIE Record
   GHepRecord* ghep = static_cast<GHepRecord*>(evt->genie_event->event);
   const Interaction* interaction = ghep->Summary();
   const InitialState& init_state = interaction->InitState();
   const ProcessInfo& proc_info = interaction->ProcInfo();
   const Target& tgt = init_state.Tgt();
 
   // If the event is not RES this Calc doesn't handle it
   if (!proc_info.IsResonant()) return 1.0;
 
   // WEIGHT CALCULATIONS -------------
   double w = 1.0;
 
   // CCRES Dial
   if (proc_info.IsWeakCC()) w *= fCur_NormCCRES;
 
   // Return Combined Weight
   return w;
 }
 
 void MINERvAReWeight_RES::SetDialValue(std::string name, double val) {
   SetDialValue(Reweight::ConvDial(name, kCUSTOM), val);
 }
 
 void MINERvAReWeight_RES::SetDialValue(int rwenum, double val) {
   // Check Handled
   int curenum = rwenum % 1000;
   if (!IsHandled(curenum)) return;
 
   // Set Values
   if (curenum == kMINERvARW_NormCCRES) {
     fTwk_NormCCRES = val;
     fCur_NormCCRES = fDef_NormCCRES + fTwk_NormCCRES;
   }
 
   // Define Tweaked
   fTweaked = ((fTwk_NormCCRES != 0.0));
 }
 
 bool MINERvAReWeight_RES::IsHandled(int rwenum) {
   int curenum = rwenum % 1000;
 
   switch (curenum) {
     case kMINERvARW_NormCCRES:
       return true;
     default:
       return false;
   }
 }
 
 //*******************************************************
 RikRPA::RikRPA() {
   //*******************************************************
 
   // - Syst : kMINERvA_RikRPA_ApplyRPA
   // - Type : Binary
   // - Limits : 0.0 (false) -> 1.0 (true)
   // - Default : 0.0
   fApplyDial_RPACorrection = false;
 
   // - Syst : kMINERvA_RikRPA_LowQ2
   // - Type : Absolute
   // - Limits : 1.0 -> 1.0
   // - Default : 0.0
   // - Frac Error : 100%
   fDefDial_RPALowQ2 = 0.0;
   fCurDial_RPALowQ2 = fDefDial_RPALowQ2;
   fErrDial_RPALowQ2 = 0.0;
 
   // - Syst : kMINERvA_RikRPA_HighQ2
   // - Type : Absolute
   // - Limits : 1.0 -> 1.0
   // - Default : 0.0
   // - Frac Error : 100%
   fDefDial_RPAHighQ2 = 0.0;
   fCurDial_RPAHighQ2 = fDefDial_RPAHighQ2;
   fErrDial_RPAHighQ2 = 1.0;
 
-  fEventWeights = new double[5];
+  
+
+  // - Syst : kMINERvA_RikRESRPA_ApplyRPA
+  // - Type : Binary
+  // - Limits : 0.0 (false) -> 1.0 (true)
+  // - Default : 0.0
+  fApplyDial_RESRPACorrection = false;
+
+  // - Syst : kMINERvA_RikRESRPA_LowQ2
+  // - Type : Absolute
+  // - Limits : 1.0 -> 1.0
+  // - Default : 0.0
+  // - Frac Error : 100%
+  fDefDial_RESRPALowQ2 = 0.0;
+  fCurDial_RESRPALowQ2 = fDefDial_RESRPALowQ2;
+  fErrDial_RESRPALowQ2 = 0.0;
 
+  // - Syst : kMINERvA_RikRESRPA_HighQ2
+  // - Type : Absolute
+  // - Limits : 1.0 -> 1.0
+  // - Default : 0.0
+  // - Frac Error : 100%
+  fDefDial_RESRPAHighQ2 = 0.0;
+  fCurDial_RESRPAHighQ2 = fDefDial_RESRPAHighQ2;
+  fErrDial_RESRPAHighQ2 = 1.0;
+
+
+  // Setup Calculators
+  fEventWeights = new double[5];
   for (size_t i = 0; i < kMaxCalculators; i++) {
-    // fRPACalculators[i] = NULL;
+    fRPACalculators[i] = NULL;
   }
 
   fTweaked = false;
 }
 
 RikRPA::~RikRPA() {
-  delete fEventWeights;
+  //  delete fEventWeights;
 
-  for (size_t i = 0; i < kMaxCalculators; i++) {
-    // if (fRPACalculators[i]) delete fRPACalculators[i];
-    // fRPACalculators[i] = NULL;
-  }
+  //  for (size_t i = 0; i < kMaxCalculators; i++) {
+  //    if (fRPACalculators[i]) delete fRPACalculators[i];
+  //    fRPACalculators[i] = NULL;
+  //  }
 }
 
 double RikRPA::CalcWeight(BaseFitEvt* evt) {
   // LOG(FIT) << "Calculating RikRPA" << std::endl;
   // Return 1.0 if not tweaked
   if (!fTweaked) return 1.0;
 
   double w = 1.0;
 
   // Extract the GENIE Record
   GHepRecord* ghep = static_cast<GHepRecord*>(evt->genie_event->event);
   const Interaction* interaction = ghep->Summary();
   const InitialState& init_state = interaction->InitState();
   const ProcessInfo& proc_info = interaction->ProcInfo();
   // const Kinematics &   kine       = interaction->Kine();
   // const XclsTag &      xcls       = interaction->ExclTag();
   const Target& tgt = init_state.Tgt();
 
   // If not QE return 1.0
   // LOG(FIT) << "RikRPA : Event QE = " << proc_info.IsQuasiElastic() <<
   // std::endl;
   if (!tgt.IsNucleus()) return 1.0;
-  if (!proc_info.IsQuasiElastic()) return 1.0;
+  if (!proc_info.IsQuasiElastic() && !proc_info.IsResonant()) return 1.0;
 
   // Extract Beam and Target PDG
   GHepParticle* neutrino = ghep->Probe();
   int bpdg = neutrino->Pdg();
 
   GHepParticle* target = ghep->Particle(1);
   assert(target);
   int tpdg = target->Pdg();
 
   // Find the enum we need
   int calcenum = GetRPACalcEnum(bpdg, tpdg);
   if (calcenum == -1) return 1.0;
 
   // Check we have the RPA Calc setup for this enum
   // if not, set it up at that point
-  // if (!fRPACalculators[calcenum]) SetupRPACalculator(calcenum);
-  // weightRPA* rpacalc = fRPACalculators[calcenum];
-  // if (!rpacalc) {
-  // THROW("Failed to grab the RPA Calculator : " << calcenum);
-  // }
+  if (!fRPACalculators[calcenum]) SetupRPACalculator(calcenum);
+  weightRPA* rpacalc = fRPACalculators[calcenum];
+  if (!rpacalc) {
+    THROW("Failed to grab the RPA Calculator : " << calcenum);
+  }
 
   // Extract Q0-Q3
   GHepParticle* fsl = ghep->FinalStatePrimaryLepton();
   const TLorentzVector& k1 = *(neutrino->P4());
   const TLorentzVector& k2 = *(fsl->P4());
   double q0 = fabs((k1 - k2).E());
   double q3 = fabs((k1 - k2).Vect().Mag());
+  double Q2 = fabs((k1 - k2).Mag2());
 
-  // Now use q0-q3 and RPA Calculator to fill fWeights
-  // LOG(FIT) << "Getting Weights = " << q0 << " " << q3 << std::endl;
-  // rpacalc->getWeight(q0, q3, fEventWeights);
+  // Quasielastic
+  if (proc_info.IsQuasiElastic()){
 
-  // Apply Interpolation (for the time being simple linear)
+    // Now use q0-q3 and RPA Calculator to fill fWeights
+    rpacalc->getWeight(q0, q3, fEventWeights);
 
-  // Syst Application : kMINERvA_RikRPA_ApplyRPA
-  if (fApplyDial_RPACorrection) {
-    w *= fEventWeights[0];  // CV
-  }
+    if (fApplyDial_RPACorrection) {
+      w *= fEventWeights[0];  // CV
+    }
 
-  LOG(FIT) << " fCurDial_RPALowQ2  = " << fCurDial_RPALowQ2
-           << " fCurDial_RPAHighQ2 = " << fCurDial_RPAHighQ2 << " Weights "
-           << fEventWeights[0] << " " << fEventWeights[1] << " "
-           << fEventWeights[2] << " " << fEventWeights[3] << " "
-           << fEventWeights[4] << std::endl;
-
-  // Syst Application : kMINERvA_RikRPA_LowQ2
-  if (fabs(fCurDial_RPALowQ2) > 0.0) {
-    double interpw = fEventWeights[0];
-
-    if (fCurDial_RPALowQ2 > 0.0) {
-      interpw = fEventWeights[0] - (fEventWeights[0] - fEventWeights[1]) *
-                                       fCurDial_RPALowQ2;  // WLow+    } else if
-    } else if (fCurDial_RPALowQ2 < 0.0) {
-      interpw = fEventWeights[0] - (fEventWeights[2] - fEventWeights[0]) *
-                                       fCurDial_RPALowQ2;  // WLow-
+    // Syst Application : kMINERvA_RikRPA_LowQ2
+    if (fabs(fCurDial_RPALowQ2) > 0.0) {
+      double interpw = fEventWeights[0];
+      
+      if (fCurDial_RPALowQ2 > 0.0 && Q2 < 2.0) {
+	interpw = fEventWeights[0] - (fEventWeights[0] - fEventWeights[1]) *
+	  fCurDial_RPALowQ2;  // WLow+    } else if
+      } else if (fCurDial_RPALowQ2 < 0.0 && Q2 < 2.0) {
+	interpw = fEventWeights[0] - (fEventWeights[2] - fEventWeights[0]) *
+	  fCurDial_RPALowQ2;  // WLow-
+      }
+      w *= interpw / fEventWeights[0];  // Div by CV again
+    }
+    
+    // Syst Application : kMINERvA_RikRPA_HighQ2
+    if (fabs(fCurDial_RPAHighQ2) > 0.0) {
+      double interpw = fEventWeights[0];
+      
+      if (fCurDial_RPAHighQ2 > 0.0) {
+	interpw = fEventWeights[0] - (fEventWeights[0] - fEventWeights[3]) *
+	  fCurDial_RPAHighQ2;  // WHigh+   
+	
+      } else if (fCurDial_RPAHighQ2 < 0.0) {
+        interpw = fEventWeights[0] - (fEventWeights[4] - fEventWeights[0]) *
+	  fCurDial_RPAHighQ2;  // WHigh-
+      }
+      w *= interpw / fEventWeights[0];  // Div by CV again
     }
-    w *= interpw / fEventWeights[0];  // Div by CV again
   }
 
-  // Syst Application : kMINERvA_RikRPA_HighQ2
-  if (fabs(fCurDial_RPAHighQ2) > 0.0) {
-    double interpw = fEventWeights[0];
-    if (fCurDial_RPAHighQ2 > 0.0) {
-      interpw = fEventWeights[0] - (fEventWeights[0] - fEventWeights[3]) *
-                                       fCurDial_RPAHighQ2;  // WHigh+    } else
-      if (fCurDial_RPAHighQ2 < 0.0) {
+  // Resonant Events
+  if (proc_info.IsResonant()){
+
+    // Now use Q2 and RESRPA Calculator to fill fWeights
+    double CV = rpacalc->getWeight(Q2);
+
+    if (fApplyDial_RESRPACorrection) {
+      w *= CV; //fEventWeights[0];  // CVa
+    }
+
+    /*
+    // Syst Application : kMINERvA_RikRESRPA_LowQ2
+    if (fabs(fCurDial_RESRPAHighQ2) > 0.0) {
+      double interpw = fEventWeights[0];
+      
+      if (fCurDial_RESRPAHighQ2 > 0.0) {
+	interpw = fEventWeights[0] - (fEventWeights[0] - fEventWeights[3]) *
+	  fCurDial_RESRPAHighQ2;  // WHigh+
+	
+      } else if (fCurDial_RESRPAHighQ2 < 0.0) {
+	interpw = fEventWeights[0] - (fEventWeights[4] - fEventWeights[0]) *
+	  fCurDial_RESRPAHighQ2;  // WHigh-
+      }
+      w *= interpw / fEventWeights[0];  // Div by CV again
+    }
+
+    // Syst Application : kMINERvA_RikRESRPA_HighQ2
+    if (fabs(fCurDial_RESRPAHighQ2) > 0.0) {
+      double interpw = fEventWeights[0];
+
+      if (fCurDial_RESRPAHighQ2 > 0.0) {
+        interpw = fEventWeights[0] - (fEventWeights[0] - fEventWeights[3]) *
+          fCurDial_RESRPAHighQ2;  // WHigh+
+
+      } else if (fCurDial_RESRPAHighQ2 < 0.0) {
         interpw = fEventWeights[0] - (fEventWeights[4] - fEventWeights[0]) *
-                                         fCurDial_RPAHighQ2;  // WHigh-
+          fCurDial_RESRPAHighQ2;  // WHigh-
       }
       w *= interpw / fEventWeights[0];  // Div by CV again
     }
+    */
   }
 
   // LOG(FIT) << "RPA Weight = " << w << std::endl;
   return w;
 }  // namespace reweight
 
 void RikRPA::SetDialValue(std::string name, double val) {
   SetDialValue(Reweight::ConvDial(name, kCUSTOM), val);
 }
 
 void RikRPA::SetDialValue(int rwenum, double val) {
   int curenum = rwenum % 1000;
 
   // Check Handled
   if (!IsHandled(curenum)) return;
-  if (curenum == kMINERvARW_RikRPA_ApplyRPA)
-    fApplyDial_RPACorrection = (val > 0.5);
-  if (curenum == kMINERvARW_RikRPA_LowQ2) fCurDial_RPALowQ2 = val;
-  if (curenum == kMINERvARW_RikRPA_HighQ2) fCurDial_RPAHighQ2 = val;
+  if (curenum == kMINERvARW_RikRPA_ApplyRPA) fApplyDial_RPACorrection = (val > 0.5);
+  if (curenum == kMINERvARW_RikRPA_LowQ2)    fCurDial_RPALowQ2 = val;
+  if (curenum == kMINERvARW_RikRPA_HighQ2)   fCurDial_RPAHighQ2 = val;
+  if (curenum == kMINERvARW_RikRESRPA_ApplyRPA) fApplyDial_RESRPACorrection = (val > 0.5);
+  if (curenum == kMINERvARW_RikRESRPA_LowQ2)    fCurDial_RESRPALowQ2 = val;
+  if (curenum == kMINERvARW_RikRESRPA_HighQ2)   fCurDial_RESRPAHighQ2 = val;
+  
 
   // Assign flag to say stuff has changed
   fTweaked = (fApplyDial_RPACorrection ||
               fabs(fCurDial_RPAHighQ2 - fDefDial_RPAHighQ2) > 0.0 ||
-              fabs(fCurDial_RPALowQ2 - fDefDial_RPALowQ2) > 0.0);
+              fabs(fCurDial_RPALowQ2 - fDefDial_RPALowQ2) > 0.0 ||
+	      fApplyDial_RESRPACorrection ||
+	      fabs(fCurDial_RESRPAHighQ2 - fDefDial_RESRPAHighQ2) > 0.0 ||
+	      fabs(fCurDial_RESRPALowQ2 - fDefDial_RESRPALowQ2) > 0.0);
+  
 }
 
 bool RikRPA::IsHandled(int rwenum) {
   int curenum = rwenum % 1000;
   switch (curenum) {
-    case kMINERvARW_RikRPA_ApplyRPA:
-      return true;
-    case kMINERvARW_RikRPA_LowQ2:
-      return true;
-    case kMINERvARW_RikRPA_HighQ2:
-      return true;
-    default:
-      return false;
+  case kMINERvARW_RikRESRPA_ApplyRPA:
+    return true;
+  case kMINERvARW_RikRESRPA_LowQ2:
+    return true;
+  case kMINERvARW_RikRESRPA_HighQ2:
+    return true;
+  case kMINERvARW_RikRPA_ApplyRPA:
+    return true;
+  case kMINERvARW_RikRPA_LowQ2:
+    return true;
+  case kMINERvARW_RikRPA_HighQ2:
+    return true;
+  default:
+    return false;
   }
 }
 
 void RikRPA::SetupRPACalculator(int calcenum) {
   std::string rwdir = FitPar::GetDataBase() + "/reweight/MINERvA/RikRPA/";
   std::string fidir = "";
   switch (calcenum) {
     case kNuMuC12:
       fidir = "outNievesRPAratio-nu12C-20GeV-20170202.root";
       break;
 
     case kNuMuO16:
       fidir = "outNievesRPAratio-nu16O-20GeV-20170202.root";
       break;
 
     case kNuMuAr40:
       fidir = "outNievesRPAratio-nu40Ar-20GeV-20170202.root";
       break;
 
     case kNuMuCa40:
       fidir = "outNievesRPAratio-nu40Ca-20GeV-20170202.root";
       break;
 
     case kNuMuFe56:
       fidir = "outNievesRPAratio-nu56Fe-20GeV-20170202.root";
       break;
 
     case kNuMuBarC12:
       fidir = "outNievesRPAratio-anu12C-20GeV-20170202.root";
       break;
 
     case kNuMuBarO16:
       fidir = "outNievesRPAratio-anu16O-20GeV-20170202.root";
       break;
 
     case kNuMuBarAr40:
       fidir = "outNievesRPAratio-anu40Ar-20GeV-20170202.root";
       break;
 
     case kNuMuBarCa40:
       fidir = "outNievesRPAratio-anu40Ca-20GeV-20170202.root";
       break;
 
     case kNuMuBarFe56:
       fidir = "outNievesRPAratio-anu56Fe-20GeV-20170202.root";
       break;
   }
 
   LOG(FIT) << "Loading RPA CALC : " << fidir << std::endl;
   TDirectory* olddir = gDirectory;
 
-  // fRPACalculators[calcenum] = new weightRPA(rwdir + "/" + fidir);
+  std::cout << "***********************************************" << std::endl;
+  std::cout << "Loading a new weightRPA calculator" << std::endl;
+  std::cout << "Authors:  Rik Gran, Heidi Schellman" << std::endl;
+  std::cout << "Citation: arXiv:1705.02932 [hep-ex]" << std::endl;
+  std::cout << "***********************************************" << std::endl;
+
+  fRPACalculators[calcenum] = new weightRPA(rwdir + "/" + fidir);
   olddir->cd();
   return;
 }
 
 int RikRPA::GetRPACalcEnum(int bpdg, int tpdg) {
   if (bpdg == 14 && tpdg == 1000060120)
     return kNuMuC12;
   else if (bpdg == 14 && tpdg == 1000080160)
     return kNuMuO16;
   else if (bpdg == 14 && tpdg == 1000180400)
     return kNuMuAr40;
   else if (bpdg == 14 && tpdg == 1000200400)
     return kNuMuCa40;
   else if (bpdg == 14 && tpdg == 1000280560)
     return kNuMuFe56;
   else if (bpdg == -14 && tpdg == 1000060120)
     return kNuMuBarC12;
   else if (bpdg == -14 && tpdg == 1000080160)
     return kNuMuBarO16;
   else if (bpdg == -14 && tpdg == 1000180400)
     return kNuMuBarAr40;
   else if (bpdg == -14 && tpdg == 1000200400)
     return kNuMuBarCa40;
   else if (bpdg == -14 && tpdg == 1000280560)
     return kNuMuBarFe56;
   else {
     ERROR(WRN, "Unknown beam and target combination for RPA Calcs! "
                    << bpdg << " " << tpdg);
   }
 
   return -1;
 }
 
 }  // namespace reweight
 }  // namespace nuisance
 #endif
 #endif
diff --git a/src/Reweight/MINERvAWeightCalcs.h b/src/Reweight/MINERvAWeightCalcs.h
index d3ec9a1..629b6ec 100644
--- a/src/Reweight/MINERvAWeightCalcs.h
+++ b/src/Reweight/MINERvAWeightCalcs.h
@@ -1,136 +1,148 @@
 #ifndef MINERVA_WEIGHT_CALCS
 #define MINERVA_WEIGHT_CALCS
 
 #include <string>
 
 #ifdef __MINERVA_RW_ENABLED__
 #ifdef __GENIE_ENABLED__
 #include "Conventions/Units.h"
 #include "EVGCore/EventRecord.h"
 #include "FitEvent.h"
-#include "FitParameters.h"
+
 #include "GHEP/GHepParticle.h"
 #include "GHEP/GHepRecord.h"
 #include "GHEP/GHepUtils.h"
 #include "GeneralUtils.h"
 #include "NUISANCESyst.h"
 #include "NUISANCEWeightCalcs.h"
 #include "Ntuple/NtpMCEventRecord.h"
 #include "PDG/PDGUtils.h"
 #include "WeightUtils.h"
-// #include "weightRPA.h"
+#include "weightRPA.h"
 using namespace genie;
 class BaseFitEvt;
 
 
 namespace nuisance {
 namespace reweight {
 
 // MEC Dials
 class MINERvAReWeight_QE : public NUISANCEWeightCalc {
  public:
   MINERvAReWeight_QE();
   virtual ~MINERvAReWeight_QE();
 
   double CalcWeight(BaseFitEvt* evt);
   void SetDialValue(std::string name, double val);
   void SetDialValue(int rwenum, double val);
   bool IsHandled(int rwenum);
 
   double fTwk_NormCCQE;
   double fCur_NormCCQE;
   double fDef_NormCCQE;
     bool fTweaked;
 
 };
 
 
 // MEC Dials
 class MINERvAReWeight_MEC : public NUISANCEWeightCalc {
  public:
   MINERvAReWeight_MEC();
   virtual ~MINERvAReWeight_MEC();
 
   double CalcWeight(BaseFitEvt* evt);
   void SetDialValue(std::string name, double val);
   void SetDialValue(int rwenum, double val);
   bool IsHandled(int rwenum);
 
   double fTwk_NormCCMEC;
   double fCur_NormCCMEC;
   double fDef_NormCCMEC;
     bool fTweaked;
 
 };
 
 // RES Dials
 class MINERvAReWeight_RES : public NUISANCEWeightCalc {
  public:
    MINERvAReWeight_RES();
    virtual ~MINERvAReWeight_RES();
 
    double CalcWeight(BaseFitEvt* evt);
    void SetDialValue(std::string name, double val);
    void SetDialValue(int rwenum, double val);
    bool IsHandled(int rwenum);
 
    double fTwk_NormCCRES;
    double fCur_NormCCRES;
    double fDef_NormCCRES;
     bool fTweaked;
 
  };
 
 /// RPA Weight Calculator that applies RPA systematics
 /// to GENIE events. GENIE EVENTS ONLY!
 class RikRPA : public NUISANCEWeightCalc {
 public:
 	RikRPA();
 	~RikRPA();
 
 	double CalcWeight(BaseFitEvt* evt);
 	void SetDialValue(std::string name, double val);
 	void SetDialValue(int rwenum, double val);
 	bool IsHandled(int rwenum);
 
 	void SetupRPACalculator(int calcenum);
 	int GetRPACalcEnum(int bpdg, int tpdg);
 
 	bool   fApplyDial_RPACorrection;
 
 	double fTwkDial_RPALowQ2;
 	double fDefDial_RPALowQ2;
 	double fCurDial_RPALowQ2;
 	double fErrDial_RPALowQ2;
 
 	double fTwkDial_RPAHighQ2;
 	double fDefDial_RPAHighQ2;
 	double fCurDial_RPAHighQ2;
 	double fErrDial_RPAHighQ2;
+	
+	bool   fApplyDial_RESRPACorrection;
+
+        double fTwkDial_RESRPALowQ2;
+        double fDefDial_RESRPALowQ2;
+        double fCurDial_RESRPALowQ2;
+        double fErrDial_RESRPALowQ2;
+
+        double fTwkDial_RESRPAHighQ2;
+        double fDefDial_RESRPAHighQ2;
+        double fCurDial_RESRPAHighQ2;
+        double fErrDial_RESRPAHighQ2;
 
 	double* fEventWeights;
 	bool fTweaked;
 
 	const static int kMaxCalculators = 10;
 	enum rpacalcenums {
 		kNuMuC12,
 		kNuMuO16,
 		kNuMuAr40,
 		kNuMuCa40,
 		kNuMuFe56,
 		kNuMuBarC12,
 		kNuMuBarO16,
 		kNuMuBarAr40,
 		kNuMuBarCa40,
 		kNuMuBarFe56
 	};
-	// weightRPA* fRPACalculators[kMaxCalculators];
+	weightRPA* fRPACalculators[kMaxCalculators];
 };
 
 };  // namespace reweight
 };  // namespace nuisance
 
 #endif // __GENIE_ENABLED__
 #endif //__MINERVA_RW_ENABLED__
 
 #endif
diff --git a/src/Reweight/NUISANCESyst.h b/src/Reweight/NUISANCESyst.h
index 3fec5a7..dfc84e2 100644
--- a/src/Reweight/NUISANCESyst.h
+++ b/src/Reweight/NUISANCESyst.h
@@ -1,58 +1,62 @@
 #ifndef NUISANCESyst_H
 #define NUISANCESyst_H
 #include "GeneralUtils.h"
 
 namespace Reweight {
 
 enum NUISANCESyst {
 	kUnkownNUISANCEDial = 0,
 	kGaussianCorr_CCQE_norm,
 	kGaussianCorr_CCQE_tilt,
 	kGaussianCorr_CCQE_Pq0,
 	kGaussianCorr_CCQE_Wq0,
 	kGaussianCorr_CCQE_Pq3,
 	kGaussianCorr_CCQE_Wq3,
 	kGaussianCorr_2p2h_norm,
 	kGaussianCorr_2p2h_tilt,
 	kGaussianCorr_2p2h_Pq0,
 	kGaussianCorr_2p2h_Wq0,
 	kGaussianCorr_2p2h_Pq3,
 	kGaussianCorr_2p2h_Wq3,
 	kGaussianCorr_2p2h_PPandNN_norm,
 	kGaussianCorr_2p2h_PPandNN_tilt,
 	kGaussianCorr_2p2h_PPandNN_Pq0,
 	kGaussianCorr_2p2h_PPandNN_Wq0,
 	kGaussianCorr_2p2h_PPandNN_Pq3,
 	kGaussianCorr_2p2h_PPandNN_Wq3,
 	kGaussianCorr_2p2h_NP_norm,
 	kGaussianCorr_2p2h_NP_tilt,
 	kGaussianCorr_2p2h_NP_Pq0,
 	kGaussianCorr_2p2h_NP_Wq0,
 	kGaussianCorr_2p2h_NP_Pq3,
 	kGaussianCorr_2p2h_NP_Wq3,
 	kGaussianCorr_CC1pi_norm,
 	kGaussianCorr_CC1pi_tilt,
 	kGaussianCorr_CC1pi_Pq0,
 	kGaussianCorr_CC1pi_Wq0,
 	kGaussianCorr_CC1pi_Pq3,
 	kGaussianCorr_CC1pi_Wq3,
 	kGaussianCorr_AllowSuppression,
 
 	kModeNorm_NormRES,
 
 	kMINERvARW_NormCCQE,
 	kMINERvARW_NormCCMEC,
 	kMINERvARW_NormCCRES,
 
 	kMINERvARW_RikRPA_ApplyRPA,
-    kMINERvARW_RikRPA_LowQ2,
-    kMINERvARW_RikRPA_HighQ2,
+	kMINERvARW_RikRPA_LowQ2,
+	kMINERvARW_RikRPA_HighQ2,
+
+	kMINERvARW_RikRESRPA_ApplyRPA,
+        kMINERvARW_RikRESRPA_LowQ2,
+	kMINERvARW_RikRESRPA_HighQ2,
 
 	kNUISANCEDial_LAST
 };
 
 int ConvertNUISANCEDial(std::string type);
 std::string ConvNUISANCEDial(int type);
 
 };
 #endif
diff --git a/src/Reweight/NUISANCEWeightCalcs.h b/src/Reweight/NUISANCEWeightCalcs.h
index 95fa64b..3814d67 100644
--- a/src/Reweight/NUISANCEWeightCalcs.h
+++ b/src/Reweight/NUISANCEWeightCalcs.h
@@ -1,100 +1,100 @@
 #ifndef NUISANCE_WEIGHT_CALCS
 #define NUISANCE_WEIGHT_CALCS
 
 #include "FitEvent.h"
 #include "GeneralUtils.h"
 #include "BaseFitEvt.h"
 #include "WeightUtils.h"
 #include "NUISANCESyst.h"
-#include "FitParameters.h"
+
 
 using namespace Reweight;
 
 
  class NUISANCEWeightCalc {
 public:
 	NUISANCEWeightCalc() {};
 	virtual ~NUISANCEWeightCalc() {};
 
 	virtual double CalcWeight(BaseFitEvt* evt){return 1.0;};
 	virtual void SetDialValue(std::string name, double val){};
 	virtual void SetDialValue(int rwenum, double val){};
 	virtual bool IsHandled(int rwenum){return false;};
 
 	virtual void Print(){};
 
 	std::map<std::string, int> fDialNameIndex;
 	std::map<int, int> fDialEnumIndex;
 	std::vector<double> fDialValues;
 
 	std::string fName;
 };
 
 class ModeNormCalc : public NUISANCEWeightCalc {
  public:
   ModeNormCalc();
   ~ModeNormCalc(){};
 
   double CalcWeight(BaseFitEvt* evt);
   void SetDialValue(std::string name, double val);
   void SetDialValue(int rwenum, double val);
   bool IsHandled(int rwenum);
 
   double fNormRES;
  };
 
 
 
 class GaussianModeCorr : public NUISANCEWeightCalc {
 public:
 
 	GaussianModeCorr();
 	~GaussianModeCorr(){};
 
 	double CalcWeight(BaseFitEvt* evt);
 	void SetDialValue(std::string name, double val);
 	void SetDialValue(int rwenum, double val);
 	bool IsHandled(int rwenum);
 	double GetGausWeight(double q0, double q3, double vals[]);
 
 	// 5 pars describe the Gaussain
 	// 0 norm.
 	// 1 q0 pos
 	// 2 q0 width
 	// 3 q3 pos
 	// 4 q3 width
 	static const int kPosNorm = 0;
 	static const int kPosTilt = 1;
 	static const int kPosPq0  = 2;
 	static const int kPosWq0  = 3;
 	static const int kPosPq3  = 4;
 	static const int kPosWq3  = 5;
 
 	bool fApply_CCQE;
 	double fGausVal_CCQE[6];
 
 	bool fApply_2p2h;
 	double fGausVal_2p2h[6];
 
 	bool fApply_2p2h_PPandNN;
 	double fGausVal_2p2h_PPandNN[6];
 
 	bool fApply_2p2h_NP;
 	double fGausVal_2p2h_NP[6];
 
 	bool fApply_CC1pi;
 	double fGausVal_CC1pi[6];
 
 	bool fAllowSuppression;
 
 	bool fDebugStatements;
 
 
 
 
 
 
 };
 
 
 #endif
diff --git a/src/Reweight/WeightUtils.h b/src/Reweight/WeightUtils.h
index c2e35ef..52cf634 100644
--- a/src/Reweight/WeightUtils.h
+++ b/src/Reweight/WeightUtils.h
@@ -1,144 +1,144 @@
 #ifndef WEIGHTUTILS_H
 #define WEIGHTUTILS_H
 
 #include "FitEvent.h"
 #include "FitLogger.h"
-#include "FitParameters.h"
+
 #include "TF1.h"
 
 #ifdef __T2KREW_ENABLED__
 #include "T2KGenieReWeight.h"
 #include "T2KNIWGReWeight.h"
 #include "T2KNIWGUtils.h"
 #include "T2KNeutReWeight.h"
 #include "T2KNeutUtils.h"
 #include "T2KReWeight.h"
 using namespace t2krew;
 #endif
 
 #ifdef __NIWG_ENABLED__
 #include "NIWGReWeight.h"
 #include "NIWGReWeight1piAngle.h"
 #include "NIWGReWeight2010a.h"
 #include "NIWGReWeight2012a.h"
 #include "NIWGReWeight2014a.h"
 #include "NIWGReWeightDeltaMass.h"
 #include "NIWGReWeightEffectiveRPA.h"
 #include "NIWGReWeightHadronMultSwitch.h"
 #include "NIWGReWeightMEC.h"
 #include "NIWGReWeightPiMult.h"
 #include "NIWGReWeightProtonFSIbug.h"
 #include "NIWGReWeightRPA.h"
 #include "NIWGReWeightSpectralFunc.h"
 #include "NIWGReWeightSplineEnu.h"
 #include "NIWGSyst.h"
 #include "NIWGSystUncertainty.h"
 #endif
 
 #ifdef __NEUT_ENABLED__
 #include "NReWeight.h"
 #include "NReWeightCasc.h"
 #include "NReWeightNuXSecCCQE.h"
 #include "NReWeightNuXSecCCRES.h"
 #include "NReWeightNuXSecCOH.h"
 #include "NReWeightNuXSecDIS.h"
 #include "NReWeightNuXSecNC.h"
 #include "NReWeightNuXSecNCEL.h"
 #include "NReWeightNuXSecNCRES.h"
 #include "NReWeightNuXSecRES.h"
 #include "NReWeightNuclPiless.h"
 #include "NSyst.h"
 #include "NSystUncertainty.h"
 #include "neutpart.h"
 #include "neutvect.h"
 #endif
 
 #ifdef __NUWRO_ENABLED__
 #include "event1.h"
 #endif
 
 #ifdef __NUWRO_REWEIGHT_ENABLED__
 #include "NuwroReWeight.h"
 #include "NuwroReWeight_FlagNorm.h"
 #include "NuwroReWeight_QEL.h"
 #include "NuwroReWeight_SPP.h"
 #include "NuwroSyst.h"
 #include "NuwroSystUncertainty.h"
 #endif
 
 #ifdef __GENIE_ENABLED__
 #include "EVGCore/EventRecord.h"
 #include "EVGCore/EventRecord.h"
 #include "GHEP/GHepRecord.h"
 #include "GSyst.h"
 #include "GSystUncertainty.h"
 #include "Ntuple/NtpMCEventRecord.h"
 #include "ReWeight/GReWeight.h"
 #include "ReWeight/GReWeightAGKY.h"
 #include "ReWeight/GReWeightDISNuclMod.h"
 #include "ReWeight/GReWeightFGM.h"
 #include "ReWeight/GReWeightFZone.h"
 #include "ReWeight/GReWeightINuke.h"
 #include "ReWeight/GReWeightNonResonanceBkg.h"
 #include "ReWeight/GReWeightNuXSecCCQE.h"
 #include "ReWeight/GReWeightNuXSecCCQEvec.h"
 #include "ReWeight/GReWeightNuXSecCCRES.h"
 #include "ReWeight/GReWeightNuXSecCOH.h"
 #include "ReWeight/GReWeightNuXSecDIS.h"
 #include "ReWeight/GReWeightNuXSecNC.h"
 #include "ReWeight/GReWeightNuXSecNCEL.h"
 #include "ReWeight/GReWeightNuXSecNCRES.h"
 #include "ReWeight/GReWeightResonanceDecay.h"
 using namespace genie;
 using namespace genie::rew;
 #endif
 
 #include "GlobalDialList.h"
 #include "NUISANCESyst.h"
 
 enum extra_reweight_types { kOSCILLATION = kLast_generator_event_type };
 
 namespace FitBase {
 
 TF1 GetRWConvFunction(std::string type, std::string name);
 std::string GetRWUnits(std::string type, std::string name);
 
 double RWSigmaToFrac(std::string type, std::string name, double val);
 double RWSigmaToAbs(std::string type, std::string name, double val);
 double RWAbsToSigma(std::string type, std::string name, double val);
 double RWFracToSigma(std::string type, std::string name, double val);
 
 int ConvDialType(std::string type);
 std::string ConvDialType(int type);
 int GetDialEnum(std::string type, std::string name);
 int GetDialEnum(int type, std::string name);
 static std::map<std::string, int> gNormEnums;
 static std::map<std::string, int> gLikeWeightEnums;
 static std::map<std::string, int> gSplineParameterEnums;
 }
 
 namespace Reweight {
 
 int ConvDial(std::string name, std::string type, bool exceptions = false);
 int ConvDial(std::string name, int type, bool exceptions = false);
 std::string ConvDial(int nuisenum);
 
 int ConvDialType(std::string type);
 std::string ConvDialType(int type);
 
 int NEUTEnumFromName(std::string name);
 int NIWGEnumFromName(std::string name);
 int NUWROEnumFromName(std::string name);
 int T2KEnumFromName(std::string name);
 int GENIEEnumFromName(std::string name);
 int CustomEnumFromName(std::string name);
 
 int NUISANCEEnumFromName(std::string name, int type);
 int OscillationEnumFromName(std::string name);
 
 static const int kNoDialFound = -1;
 static const int kNoTypeFound = -2;
 static const int kGeneratorNotBuilt = -3;
 }
 
 #endif
diff --git a/src/Reweight/weightRPA.h b/src/Reweight/weightRPA.h
new file mode 100644
index 0000000..6f969fd
--- /dev/null
+++ b/src/Reweight/weightRPA.h
@@ -0,0 +1,414 @@
+#ifndef weightRPA_h
+#define weightRPA_h
+
+#include <fstream>  //ifstream
+#include <iostream> //cout
+
+#include <TString.h>
+#include <TH2D.h>
+#include <TH1D.h>
+#include <TFile.h>
+#include "math.h"
+#include "assert.h"
+//For Compatibility with ROOT compiler
+//uncomment the following:
+//#define ROOT
+
+/*!
+ *  Code example to extract the RPA effect central weight
+ *  and its uncertainties from the prepared files.
+ *  Heidi Schellman (Oregon State) and Rik Gran (Minnesota Duluth)
+ *  for use in MINERvA experiment analysis
+ *  must compile with the ROOT libraries
+ *  g++ `root-config --glibs --cflags` -O3 weightRPAtest.cxx -o weightRPA
+ 
+
+ *    The underlying model is from the IFIC Valencia group
+ *    see (public) minerva docdb:12688 for the full physics discussion
+
+ */
+
+
+// NOTE UNITS ARE GEV in the calculation
+// make sure you convert MeV to GeV before calling these functions
+
+
+// Class for getting  RPA paramaters inputs from a given file
+// Includes methods that return all five RPA weights at once
+//   (is the most cpu efficient way to get them)
+// Or return just the central value
+//   (skipping the uncertainties code completely if only cv wanted)
+// Or return each CV and uncertainty one at a time
+//   (is the least cpu efficient, repeats some calculations 5 times)
+
+class weightRPA {
+public:
+  //Constructor: Read in params from a filename
+  weightRPA(const TString  f) { read(f); }    //Read in params from file
+  
+  TString  filename;
+  TFile* fRPAratio;
+  TH2D *hRPArelratio;
+  TH2D *hRPAnonrelratio;
+  TH1D *hQ2relratio;
+  TH1D *hQ2nonrelratio;
+  TArrayD *TADrpapolyrel;
+  Double_t *rpapolyrel ;
+  TArrayD *TADrpapolynonrel;
+  Double_t *rpapolynonrel;
+  static const int CENTRAL=0;
+  static const int LOWQ2 = 1;
+  static const int HIGHQ2 = 2;
+
+  // true to take from histogram, false use parameterization
+  static const bool Q2histORparam = true;  
+
+  // MINERvA holds kinematics in MeV, but all these functions require GeV
+  // So make sure you pass them in GeV.
+  inline double getWeight(const double mc_q0, const double mc_q3, double * weights);  //in GeV
+  inline double getWeight(const double mc_q0, const double mc_q3); //in GeV
+  inline double getWeight(const double mc_q0, const double mc_q3, int type, int sign); //in GeV
+  inline double getWeight(const double Q2); //in GeV^2
+  inline double getWeightLowQ2(const double mc_q0, const double mc_q3, const int sign);
+  inline double getWeightHighQ2(const double mc_q0, const double mc_q3, const int sign);
+  inline double getWeightQ2(const double mc_Q2, const bool relORnonrel=true);
+  //Initializer
+  inline void read(const TString  f);
+  
+  // q0 and q3 in GeV, type = 1 for low Q2, 2 for high Q2, 0 for central
+  //double getWeightInternal(const double mc_q0, const double mc_q3,int type, int sign);
+
+  private:
+  inline double getWeightInternal(const double mc_Q2);
+  
+  inline double getWeightInternal(const double mc_q0, const double mc_q3, const int type, const int sign);
+  inline double getWeightInternal(const double mc_q0, const double mc_q3, double *weights=0);
+  inline double getWeightQ2parameterization(const double mc_Q2, const bool relORnonrel);
+  inline double getWeightQ2fromhistogram(const double mc_Q2, const bool relORnonrel);
+  
+  
+};
+
+void weightRPA::read(const TString  f)
+//Read in the params doubles from a file
+//argument: valid filename
+{
+  fRPAratio = TFile::Open(f,"READONLY");
+  if (fRPAratio){
+    hRPArelratio = (TH2D*)fRPAratio->Get("hrelratio");
+    hRPAnonrelratio = (TH2D*)fRPAratio->Get("hnonrelratio");
+    hQ2relratio = (TH1D*)fRPAratio->Get("hQ2relratio");
+    hQ2nonrelratio = (TH1D*)fRPAratio->Get("hQ2nonrelratio");
+    TADrpapolyrel = (TArrayD*)fRPAratio->Get("rpapolyrel");
+    rpapolyrel = TADrpapolyrel->GetArray();
+    TADrpapolynonrel = (TArrayD*)fRPAratio->Get("rpapolynonrel");
+    rpapolynonrel = TADrpapolynonrel->GetArray();
+    hRPArelratio->Print();
+    std::cout << "have read in ratios from file " << f <<std::endl;
+    
+  }
+  else{
+    //File could not be read
+    std::cout << "File could not be read" << std::endl;
+    
+  }
+}
+
+
+ 
+
+ 
+double weightRPA::getWeightInternal(const double mc_q0, const double mc_q3,  double *weights){
+  assert(hRPArelratio);
+  
+  if (weights != 0){
+    for (int i = 0; i < 5; i++){
+      weights[i] = 1.0;
+    }
+  }
+  
+  // the construction here is that the histogram bins
+  // line up in mev-sized steps e.g. from 0.018 to 0.019
+  // and the value stored is the value at bin-center.
+  
+  // double gevmev = 0.001 ;
+  const Double_t gevlimit = 3.; // upper limit for 2d
+  Int_t rpamevlimit = gevlimit*1000.;
+  //Double_t Q2gev = mc_Q2*gevmev*gevmev;
+  Double_t Q2gev = mc_q3*mc_q3-mc_q0*mc_q0;
+  Int_t q3bin = Int_t(mc_q3*1000.);
+  Int_t q0bin = Int_t(mc_q0*1000.);
+  if(mc_q0 >= gevlimit) q0bin = rpamevlimit - 1;
+  if(mc_q3 >= gevlimit) q3bin = rpamevlimit - 1;
+  
+  // Nieves does not calculate anything below binding energy.
+  // I don't know what GENIE does, but lets be soft about this.
+  // Two things lurking here at once.
+  // One, we are taking out a 10 MeV offset between GENIE and Valencia.
+  // Second, we are protecting against being asked for a weight that is too low in q0.
+  // It actually shouldn't happen for real GENIE events,
+  // but this protection does something that doesn't suck, just in case.
+  // you would see the artifact in a plot for sure, but better than writing 1.0.
+  Int_t q0offsetValenciaGENIE = 10;
+  if(mc_q0 < 0.018) q0bin = 18+q0offsetValenciaGENIE;
+  Double_t thisrwtemp = hRPArelratio->GetBinContent(q3bin,q0bin-q0offsetValenciaGENIE);
+  
+  // now trap bogus entries.  Not sure why they happen, but set to 1.0 not 0.0
+  if(thisrwtemp <= 0.001)thisrwtemp = 1.0;
+  
+  // events in genie but not in valencia should get a weight
+  // related to a similar q0 from the bulk distribution.
+  if(mc_q0 < 0.15 && thisrwtemp > 0.9){
+    thisrwtemp = hRPArelratio->GetBinContent(q3bin+150, q0bin-q0offsetValenciaGENIE);
+  }
+  
+
+  
+  //Double_t *mypoly;
+  //mypoly = rpapoly;
+  
+  if(Q2gev >= 9.0){
+    thisrwtemp = 1.0;
+  }
+  else if(Q2gev > 3.0) {
+    // hiding option, use the Q2 parameterization everywhere
+    // } else if(Q2gev > 3.0 || rwRPAQ2) {
+    // turn rwRPAQ2 all the way on to override the 2D histogram
+    // illustrates the old-style Q2 suppression many folks still use.
+
+    thisrwtemp = getWeightQ2(Q2gev,true);
+    
+    //    double powerQ2 = 1.0;
+    //thisrwtemp = 0.0;
+    //for(int ii=0; ii<10; ii++){
+    //  thisrwtemp += rpapoly[ii]*powerQ2;
+    //  powerQ2 *= Q2gev;
+    //}
+    //std::cout << "test temp " << thisrwtemp << " " << rpamypoly[2] << std::endl;
+  }
+  
+  if(!(thisrwtemp >= 0.001 && thisrwtemp <= 2.0))thisrwtemp = 1.0;
+  
+  // hiding option, turn off the enhancement.
+  //if(rwoffSRC && thisrwtemp > 1.0)thisrwtemp = 1.0;
+
+  if (0 == weights) return thisrwtemp;
+  // if this was called without passing an array,
+  // the user didn't want us to calculate the +/- 1-sigma bounds
+  // so the above line returned before even trying.
+
+  weights[0] = thisrwtemp;
+  
+  //if (type == 0) return thisrwtemp;
+  
+  //if (type == 1) {
+    // Construct the error bands on the low Q2 suppression.
+  // Double_t thisrwSupP1 = 1.0;
+  // Double_t thisrwSupM1 = 1.0;
+  
+  if( thisrwtemp < 1.0){
+    // make the suppression stronger or weaker to muon capture uncertainty
+    // rwRPAonesig is either +1 or -1, which is 0.25 (25%).
+    // possible to be re-written to produce 2 and 3 sigma.
+    
+    weights[1] = thisrwtemp + 1.0 * (0.25)*(1.0 - thisrwtemp);
+    weights[2] = thisrwtemp - 1.0 * (0.25)*(1.0 - thisrwtemp);
+    
+   
+    
+  }
+  else{
+    weights[1] = thisrwtemp;
+    weights[2] = thisrwtemp;
+  }
+
+  //std::cout << "check " << thisrwtemp << " " << weights[1] << " " << weights[2] << std::endl;
+
+  
+    
+    
+  // Construct the rest of the error bands on the low Q2 suppression.
+  // this involves getting the weight from the non-relativistic ratio
+  
+  //if (type == 2){
+    
+  Double_t thisrwEnhP1 = 1.0;
+  Double_t thisrwEnhM1 = 1.0;
+  
+  // make enhancement stronger or weaker to Federico Sanchez uncertainty
+  // this does NOT mean two sigma, its overloading the option.
+  Double_t thisrwextreme = hRPAnonrelratio->GetBinContent(q3bin,q0bin-q0offsetValenciaGENIE);
+  // now trap bogus entries.  Not sure why they happen, but set to 1.0 not 0.0
+  if(thisrwextreme <= 0.001)thisrwextreme = 1.0;
+  
+  if(mc_q0 < 0.15 && thisrwextreme > 0.9){
+    thisrwextreme = hRPAnonrelratio->GetBinContent(q3bin+150, q0bin-q0offsetValenciaGENIE);
+  }
+  
+  //std::cout << "ext " << thisrwextreme << " " << thisrwtemp << std::endl;
+
+  // get the same for the Q2 dependent thing,
+  // but from the nonrelativistic polynomial
+  
+  if(Q2gev >= 9.0){
+    thisrwextreme = 1.0;
+  }
+  else if(Q2gev > 3.0 ) {
+    thisrwextreme = getWeightQ2(Q2gev,false);
+    //double powerQ2 = 1.0;
+    //thisrwextreme = 0.0;
+    //for(int ii=0; ii<10; ii++){
+    //  thisrwextreme += rpapolynonrel[ii]*powerQ2;
+    //  powerQ2 *= Q2gev;
+    //}
+    //std::cout << "test extreme " << thisrwextreme << " " << mypolynonrel[2] << std::endl;
+  }
+
+  if(!(thisrwextreme >= 0.001 && thisrwextreme <= 2.0))thisrwextreme = 1.0;
+
+  //std::cout << "test extreme " << Q2gev << " " << thisrwextreme << " " << thisrwtemp << std::endl;
+  
+  Double_t RelToNonRel = 0.6;
+  
+  // based on some distance between central value and extreme
+  thisrwEnhP1 = thisrwtemp + RelToNonRel * (thisrwextreme-thisrwtemp);
+  Double_t thisrwEnhP1max = thisrwextreme;
+  
+  if(Q2gev < 0.9)thisrwEnhP1 += 1.5*(0.9 - Q2gev)*(thisrwEnhP1max - thisrwEnhP1);
+  // sanity check, don't let the upper error bound go above the nonrel limit.
+  if(thisrwEnhP1 > thisrwEnhP1max)thisrwEnhP1 = thisrwEnhP1max;
+  // don't let positive error bound be closer than 3% above the central value
+  // will happen at very high Q2 and very close to Q2 = 0
+  if(thisrwEnhP1 < thisrwtemp + 0.03)thisrwEnhP1 = thisrwtemp + 0.03;
+  
+  thisrwEnhM1 = thisrwtemp - RelToNonRel * (thisrwextreme-thisrwtemp);
+  // don't let negative error bound be closer than 3% below the central value
+  if(thisrwEnhM1 > thisrwtemp - 0.03)thisrwEnhM1 = thisrwtemp - 0.03;
+  // even still, don't let the lower error bound go below 1.0 at high-ish Q2
+  if(Q2gev > 1.0 && thisrwEnhM1 < 1.0)thisrwEnhM1 = 1.0;
+  
+  // whew.  so now return the main weight
+  // and return the array of all five weights in some array
+  // thisrwtemp, thisrwSupP1, thisrwSupM1, thisrwEnhP1, thisrwEnhM1
+  
+  //if (sign == 1) return thisrwEnhP1;
+  //if (sign == -1) return thisrwEnhM1;
+    
+  weights[3] = thisrwEnhP1;
+  weights[4] = thisrwEnhM1;
+
+  // still return the central value
+  return thisrwtemp;
+  
+}
+
+
+double weightRPA::getWeight(const double mc_q0, const double mc_q3){
+
+  return getWeightInternal(mc_q0, mc_q3);
+
+}
+
+double weightRPA::getWeight(const double mc_q0, const double mc_q3, double *weights){
+
+  return getWeightInternal(mc_q0, mc_q3, weights);
+
+}
+
+double weightRPA::getWeight(const double mc_q0, const double mc_q3, int type, int sign){
+
+  return getWeightInternal(mc_q0, mc_q3, type, sign);
+
+}
+
+double weightRPA::getWeight(const double mc_Q2){
+
+  return getWeightQ2(mc_Q2);
+  
+}
+
+double weightRPA::getWeightInternal(const double mc_q0, const double mc_q3, int type, int sign){
+
+   double weights[5] = {1., 1., 1., 1., 1.};
+   double cv = getWeightInternal(mc_q0, mc_q3, weights);
+
+   if(type==0)return cv;
+   else if(type==weightRPA::LOWQ2 && sign == 1)return weights[1];
+   else if(type==weightRPA::LOWQ2 && sign == -1)return weights[2];
+   else if(type==weightRPA::HIGHQ2 && sign == 1)return weights[3];
+   else if(type==weightRPA::HIGHQ2 && sign == -1)return weights[4];
+   //else {
+   //  // should never happen?  Bork ?
+   //  return cv;  //?
+   //}
+   
+   return cv;
+}
+
+double weightRPA::getWeightQ2(const double mc_Q2, const bool relORnonrel){
+
+  if(mc_Q2 < 0.0)return 1.0;  // this is Q2 actually, not sure hw
+  if(mc_Q2 > 9.0)return 1.0;
+
+  // this function needs to know two options.
+  // does user want rel (cv) or nonrel
+  // does user want to use the histogram or parameterization
+
+  if(Q2histORparam)return getWeightQ2fromhistogram(mc_Q2, relORnonrel);
+  else return getWeightQ2parameterization(mc_Q2, relORnonrel);
+    
+}
+
+double weightRPA::getWeightQ2parameterization(const double mc_Q2, const bool relORnonrel){
+
+  if(mc_Q2 < 0.0)return 1.0;
+  if(mc_Q2 > 9.0)return 1.0;
+  
+    // this one returns just the polynomial Q2 version
+  // for special tests.  Poor answer for baseline MINERvA QE events.
+  // No uncertainty assigned to this usecase at this time.
+  //double gevmev = 0.001;  // minerva sends in MeV.
+  double Q2gev = mc_Q2;
+  double powerQ2 = 1.0;
+  double thisrwtemp = 0.0;
+  thisrwtemp = 0.0;
+  for(int ii=0; ii<10; ii++){
+    if(relORnonrel)thisrwtemp += rpapolyrel[ii]*powerQ2;
+    else thisrwtemp += rpapolynonrel[ii]*powerQ2;
+    powerQ2 *= Q2gev;
+  }
+  return thisrwtemp;
+
+  
+}
+
+double weightRPA::getWeightQ2fromhistogram(const double mc_Q2, const bool relORnonrel){
+
+  if(mc_Q2 < 0.0)return 1.0;
+  if(mc_Q2 > 9.0) return 1.0;
+
+  if(relORnonrel)return hQ2relratio->GetBinContent( hQ2relratio->FindBin(mc_Q2) );
+  else return hQ2nonrelratio->GetBinContent( hQ2nonrelratio->FindBin(mc_Q2) );
+
+  // interpolation might be overkill for such a finely binned histogram, 0.01%
+  // but the extra cpu cycles maybe small.
+  // save it here for some future use.
+  //if(relORnonrel)return  hQ2relratio->Interpolate(mc_Q2);
+  //else return  hQ2nonrelratio->Interpolate(mc_Q2);
+  
+}
+
+
+double weightRPA::getWeightLowQ2(const double mc_q0, const double mc_q3, int sign){
+  return getWeightInternal(mc_q0,mc_q3,weightRPA::LOWQ2,sign);
+}
+
+double weightRPA::getWeightHighQ2(const double mc_q0, const double mc_q3, int sign){
+  return getWeightInternal(mc_q0,mc_q3,weightRPA::HIGHQ2,sign);
+}
+
+
+#endif
+
+
+
diff --git a/src/Routines/ComparisonRoutines.cxx b/src/Routines/BayesianRoutines.cxx
similarity index 53%
copy from src/Routines/ComparisonRoutines.cxx
copy to src/Routines/BayesianRoutines.cxx
index c5463c0..5d1b69c 100755
--- a/src/Routines/ComparisonRoutines.cxx
+++ b/src/Routines/BayesianRoutines.cxx
@@ -1,537 +1,521 @@
 // Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret
 
 /*******************************************************************************
 *    This file is part of NUISANCE.
 *
 *    NUISANCE is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    NUISANCE is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with NUISANCE.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
-#include "ComparisonRoutines.h"
+#include "BayesianRoutines.h"
 
-/*
-  Constructor/Destructor
-*/
-//************************
-void ComparisonRoutines::Init() {
-//************************
+void BayesianRoutines::Init() {
+
+  fInputFile = "";
+  fInputRootFile = NULL;
 
   fOutputFile = "";
   fOutputRootFile = NULL;
 
-  fStrategy = "Compare";
-
+  fStrategy = "BayesianThrows";
   fRoutines.clear();
+  fRoutines.push_back("BayesianThrows");
 
   fCardFile = "";
 
   fFakeDataInput = "";
 
-  fSampleFCN = NULL;
+  fSampleFCN    = NULL;
 
-  fAllowedRoutines = ("Compare");
-  
-};
+  fAllowedRoutines = ("f");
 
-//*************************************
-ComparisonRoutines::~ComparisonRoutines() {
-//*************************************
 };
 
+BayesianRoutines::~BayesianRoutines() {
+};
 
-
-/*
-  Input Functions
-*/
-//*************************************
-ComparisonRoutines::ComparisonRoutines(int argc, char* argv[]) {
-//*************************************
+BayesianRoutines::BayesianRoutines(int argc, char* argv[]) {
 
   // Initialise Defaults
   Init();
   nuisconfig configuration = Config::Get();
 
   // Default containers
   std::string cardfile = "";
   std::string maxevents = "-1";
   int errorcount = 0;
   int verbocount = 0;
   std::vector<std::string> xmlcmds;
   std::vector<std::string> configargs;
-
+  fNThrows = 250;
+  fStartThrows = 0;
+  fThrowString = "";
   // Make easier to handle arguments.
   std::vector<std::string> args = GeneralUtils::LoadCharToVectStr(argc, argv);
   ParserUtils::ParseArgument(args, "-c", fCardFile, true);
   ParserUtils::ParseArgument(args, "-o", fOutputFile, false, false);
   ParserUtils::ParseArgument(args, "-n", maxevents, false, false);
   ParserUtils::ParseArgument(args, "-f", fStrategy, false, false);
-  ParserUtils::ParseArgument(args, "-d", fFakeDataInput, false, false);
+  ParserUtils::ParseArgument(args, "-t", fNThrows, false, false);
   ParserUtils::ParseArgument(args, "-i", xmlcmds);
   ParserUtils::ParseArgument(args, "-q", configargs);
   ParserUtils::ParseCounter(args, "e", errorcount);
   ParserUtils::ParseCounter(args, "v", verbocount);
   ParserUtils::CheckBadArguments(args);
 
   // Add extra defaults if none given
   if (fCardFile.empty() and xmlcmds.empty()) {
     ERR(FTL) << "No input supplied!" << std::endl;
     throw;
   }
 
   if (fOutputFile.empty() and !fCardFile.empty()) {
     fOutputFile = fCardFile + ".root";
     ERR(WRN) << "No output supplied so saving it to: " << fOutputFile << std::endl;
 
   } else if (fOutputFile.empty()) {
     ERR(FTL) << "No output file or cardfile supplied!" << std::endl;
     throw;
   }
 
   // Configuration Setup =============================
 
   // Check no comp key is available
-  nuiskey fCompKey;
   if (Config::Get().GetNodes("nuiscomp").empty()) {
     fCompKey = Config::Get().CreateNode("nuiscomp");
   } else {
     fCompKey = Config::Get().GetNodes("nuiscomp")[0];
   }
 
-  if (!fCardFile.empty())   fCompKey.AddS("cardfile", fCardFile);
-  if (!fOutputFile.empty()) fCompKey.AddS("outputfile", fOutputFile);
-  if (!fStrategy.empty())   fCompKey.AddS("strategy", fStrategy);
+  if (!fCardFile.empty())   fCompKey.Set("cardfile", fCardFile);
+  if (!fOutputFile.empty()) fCompKey.Set("outputfile", fOutputFile);
+  if (!fStrategy.empty())   fCompKey.Set("strategy", fStrategy);
 
   // Load XML Cardfile
-  configuration.LoadConfig( fCompKey.GetS("cardfile"), "");
-
-  // Add CMD XML Structs
-  for (size_t i = 0; i < xmlcmds.size(); i++) {
-    configuration.AddXMLLine(xmlcmds[i]);
-  }
+  configuration.LoadSettings( fCompKey.GetS("cardfile"), "");
 
   // Add Config Args
   for (size_t i = 0; i < configargs.size(); i++) {
     configuration.OverrideConfig(configargs[i]);
   }
-  if (maxevents.compare("-1")){
+  if (maxevents.compare("-1")) {
     configuration.OverrideConfig("MAXEVENTS=" + maxevents);
   }
 
   // Finish configuration XML
-  configuration.FinaliseConfig(fCompKey.GetS("outputfile") + ".xml");
+  configuration.FinaliseSettings(fCompKey.GetS("outputfile") + ".xml");
 
   // Add Error Verbo Lines
-  verbocount += Config::Get().GetParI("VERBOSITY");
-  errorcount += Config::Get().GetParI("ERROR");
-  bool trace = Config::Get().GetParB("TRACE");
+  verbocount += Config::GetParI("VERBOSITY");
+  errorcount += Config::GetParI("ERROR");
   std::cout << "[ NUISANCE ]: Setting VERBOSITY=" << verbocount << std::endl;
   std::cout << "[ NUISANCE ]: Setting ERROR=" << errorcount << std::endl;
   SETVERBOSITY(verbocount);
-  SETTRACE(trace);
-
-  // Comparison Setup ========================================
 
   // Proper Setup
-  fOutputRootFile = new TFile(fCompKey.GetS("outputfile").c_str(), "RECREATE");
-  SetupComparisonsFromXML();
+  if (fStrategy.find("ErrorBands") != std::string::npos ||
+      fStrategy.find("MergeErrors") != std::string::npos) {
+    fOutputRootFile = new TFile(fCompKey.GetS("outputfile").c_str(), "RECREATE");
+  }
+
+  //  fOutputRootFile = new TFile(fCompKey.GetS("outputfile").c_str(), "RECREATE");
+  SetupSystematicsFromXML();
 
   SetupRWEngine();
   SetupFCN();
 
   return;
 };
 
-//*************************************
-void ComparisonRoutines::SetupComparisonsFromXML() {
-//*************************************
+void BayesianRoutines::SetupSystematicsFromXML() {
 
-  LOG(FIT) << "Setting up nuiscomp" << std::endl;
+  LOG(FIT) << "Setting up nuismin" << std::endl;
 
   // Setup Parameters ------------------------------------------
   std::vector<nuiskey> parkeys = Config::QueryKeys("parameter");
   if (!parkeys.empty()) {
     LOG(FIT) << "Number of parameters :  " << parkeys.size() << std::endl;
   }
 
   for (size_t i = 0; i < parkeys.size(); i++) {
     nuiskey key = parkeys.at(i);
 
     // Check for type,name,nom
     if (!key.Has("type")) {
       ERR(FTL) << "No type given for parameter " << i << std::endl;
-      ERR(FTL) << "type='PARAMETER_TYPE'" << std::endl;
       throw;
     } else if (!key.Has("name")) {
       ERR(FTL) << "No name given for parameter " << i << std::endl;
-      ERR(FTL) << "name='SAMPLE_NAME'" << std::endl;
       throw;
     } else if (!key.Has("nominal")) {
       ERR(FTL) << "No nominal given for parameter " << i << std::endl;
-      ERR(FTL) << "nominal='NOMINAL_VALUE'" << std::endl;
       throw;
     }
 
     // Get Inputs
     std::string partype = key.GetS("type");
     std::string parname = key.GetS("name");
     double parnom  = key.GetD("nominal");
     double parlow  = parnom - 1;
     double parhigh = parnom + 1;
     double parstep = 1;
 
-    // override if state not given
-    if (!key.Has("state")){
-      key.SetS("state","FIX");
+
+    // Override if state not given
+    if (!key.Has("state")) {
+      key.SetS("state", "FIX");
     }
 
     std::string parstate = key.GetS("state");
 
-    // Check for incomplete limtis
-    int limdef = ((int)key.Has("low")  +
-                  (int)key.Has("high") +
-                  (int)key.Has("step"));
-
-    if (limdef > 0 and limdef < 3){
-      ERR(FTL) << "Incomplete limit set given for parameter : " << parname << std::endl;
-      ERR(FTL) << "Requires: low='LOWER_LIMIT' high='UPPER_LIMIT' step='STEP_SIZE' " << std::endl;
-      throw;
-    }
-
     // Extra limits
     if (key.Has("low")) {
-
       parlow  = key.GetD("low");
       parhigh = key.GetD("high");
       parstep = key.GetD("step");
 
       LOG(FIT) << "Read " << partype << " : "
                << parname << " = "
                << parnom << " : "
                << parlow << " < p < " << parhigh
                << " : " << parstate << std::endl;
     } else {
       LOG(FIT) << "Read " << partype << " : "
                << parname << " = "
                << parnom << " : "
                << parstate << std::endl;
     }
 
-    // Convert if required
+    // Run Parameter Conversion if needed
     if (parstate.find("ABS") != std::string::npos) {
       parnom  = FitBase::RWAbsToSigma( partype, parname, parnom  );
       parlow  = FitBase::RWAbsToSigma( partype, parname, parlow  );
       parhigh = FitBase::RWAbsToSigma( partype, parname, parhigh );
       parstep = FitBase::RWAbsToSigma( partype, parname, parstep );
     } else if (parstate.find("FRAC") != std::string::npos) {
       parnom  = FitBase::RWFracToSigma( partype, parname, parnom  );
       parlow  = FitBase::RWFracToSigma( partype, parname, parlow  );
       parhigh = FitBase::RWFracToSigma( partype, parname, parhigh );
       parstep = FitBase::RWFracToSigma( partype, parname, parstep );
     }
 
     // Push into vectors
     fParams.push_back(parname);
 
     fTypeVals[parname]  = FitBase::ConvDialType(partype);;
+    fStartVals[parname] = parnom;
     fCurVals[parname]   = parnom;
-    fStateVals[parname] = parstate;
+
+    fErrorVals[parname] = 0.0;
+
+    fStateVals[parname]    = parstate;
+    bool fixstate = parstate.find("FIX") != std::string::npos;
+    fFixVals[parname]      = fixstate;
+    fStartFixVals[parname] = fFixVals[parname];
+
+    fMinVals[parname]  = parlow;
+    fMaxVals[parname]  = parhigh;
+    fStepVals[parname] = parstep;
 
   }
 
   // Setup Samples ----------------------------------------------
   std::vector<nuiskey> samplekeys =  Config::QueryKeys("sample");
   if (!samplekeys.empty()) {
     LOG(FIT) << "Number of samples : " << samplekeys.size() << std::endl;
+  } else {
+    ERR(WRN) <<  "NO SAMPLES LOADED" << std::endl;
   }
 
   for (size_t i = 0; i < samplekeys.size(); i++) {
     nuiskey key = samplekeys.at(i);
 
     // Get Sample Options
     std::string samplename = key.GetS("name");
     std::string samplefile = key.GetS("input");
 
     std::string sampletype =
       key.Has("type") ? key.GetS("type") : "DEFAULT";
 
     double samplenorm =
       key.Has("norm") ? key.GetD("norm") : 1.0;
 
     // Print out
-    LOG(FIT) << "Read Sample " << i << ". : "
-             << samplename << " (" << sampletype << ") [Norm=" << samplenorm<<"]"<< std::endl
-             << "                                -> input='" << samplefile  << "'" << std::endl;
+    LOG(FIT) << "Read sample info " << i << " : "
+             << samplename << std::endl
+             << "\t\t input -> " << samplefile  << std::endl
+             << "\t\t state -> " << sampletype << std::endl
+             << "\t\t norm  -> " << samplenorm << std::endl;
 
     // If FREE add to parameters otherwise continue
     if (sampletype.find("FREE") == std::string::npos) {
       continue;
     }
 
     // Form norm dial from samplename + sampletype + "_norm";
     std::string normname = samplename + "_norm";
 
     // Check normname not already present
-    if (fTypeVals.find("normname") != fTypeVals.end()) {
+    if (fTypeVals.find(normname) != fTypeVals.end()) {
       continue;
     }
 
     // Add new norm dial to list if its passed above checks
     fParams.push_back(normname);
 
     fTypeVals[normname] = kNORM;
     fStateVals[normname] = sampletype;
     fCurVals[normname] = samplenorm;
 
+    fErrorVals[normname] = 0.0;
+
+    fMinVals[normname]  = 0.1;
+    fMaxVals[normname]  = 10.0;
+    fStepVals[normname] = 0.5;
+
+    bool state = sampletype.find("FREE") == std::string::npos;
+    fFixVals[normname]      = state;
+    fStartFixVals[normname] = state;
   }
 
   // Setup Fake Parameters -----------------------------
   std::vector<nuiskey> fakekeys = Config::QueryKeys("fakeparameter");
   if (!fakekeys.empty()) {
     LOG(FIT) << "Number of fake parameters : " << fakekeys.size() << std::endl;
   }
 
   for (size_t i = 0; i < fakekeys.size(); i++) {
     nuiskey key = fakekeys.at(i);
 
     // Check for type,name,nom
     if (!key.Has("name")) {
       ERR(FTL) << "No name given for fakeparameter " << i << std::endl;
       throw;
-    } else if (!key.Has("nominal")) {
+    } else if (!key.Has("nom")) {
       ERR(FTL) << "No nominal given for fakeparameter " << i << std::endl;
       throw;
     }
 
     // Get Inputs
     std::string parname = key.GetS("name");
-    double parnom  = key.GetD("nominal");
+    double parnom  = key.GetD("nom");
 
     // Push into vectors
     fFakeVals[parname] = parnom;
   }
 }
 
+/*
+  Setup Functions
+*/
 //*************************************
-void ComparisonRoutines::SetupRWEngine() {
+void BayesianRoutines::SetupRWEngine() {
 //*************************************
 
-  LOG(FIT) << "Setting up FitWeight Engine" << std::endl;
   for (UInt_t i = 0; i < fParams.size(); i++) {
     std::string name = fParams[i];
-    FitBase::GetRW()->IncludeDial(name, fTypeVals.at(name));
+    FitBase::GetRW() -> IncludeDial(name, fTypeVals.at(name) );
   }
+  UpdateRWEngine(fStartVals);
 
   return;
 }
 
 //*************************************
-void ComparisonRoutines::SetupFCN() {
-  //*************************************
+void BayesianRoutines::SetupFCN() {
+//*************************************
 
-  LOG(FIT) << "Building the SampleFCN" << std::endl;
+  LOG(FIT) << "Making the jointFCN" << std::endl;
   if (fSampleFCN) delete fSampleFCN;
-  FitPar::Config().out = fOutputRootFile;
-  fOutputRootFile->cd();
   fSampleFCN = new JointFCN(fOutputRootFile);
-  SetFakeData();
-
-  return;
-}
-
-//*************************************
-void ComparisonRoutines::SetFakeData() {
-//*************************************
-
-  if (fFakeDataInput.empty()) return;
-
-  if (fFakeDataInput.compare("MC") == 0) {
-    LOG(FIT) << "Setting fake data from MC starting prediction." << std::endl;
-    UpdateRWEngine(fFakeVals);
-
-    FitBase::GetRW()->Reconfigure();
-    fSampleFCN->ReconfigureAllEvents();
-    fSampleFCN->SetFakeData("MC");
-
-    UpdateRWEngine(fCurVals);
 
-    LOG(FIT) << "Set all data to fake MC predictions." << std::endl;
-  } else {
-    LOG(FIT) << "Setting fake data from: " << fFakeDataInput << std::endl;
-    fSampleFCN->SetFakeData(fFakeDataInput);
-  }
+  fInputThrows = fSampleFCN->GetPullList();
 
   return;
 }
 
 /*
   Fitting Functions
 */
 //*************************************
-void ComparisonRoutines::UpdateRWEngine(
-  std::map<std::string, double>& updateVals) {
-  //*************************************
+void BayesianRoutines::UpdateRWEngine(std::map<std::string, double>& updateVals) {
+//*************************************
 
   for (UInt_t i = 0; i < fParams.size(); i++) {
     std::string name = fParams[i];
 
     if (updateVals.find(name) == updateVals.end()) continue;
     FitBase::GetRW()->SetDialValue(name, updateVals.at(name));
   }
 
   FitBase::GetRW()->Reconfigure();
   return;
 }
 
 //*************************************
-void ComparisonRoutines::Run() {
+void BayesianRoutines::ThrowParameters() {
 //*************************************
 
-  LOG(FIT) << "Running ComparisonRoutines : " << fStrategy << std::endl;
-
-  if (FitPar::Config().GetParB("save_nominal")) {
-    SaveNominal();
+  // Set fThrownVals to all values in currentVals
+  for (UInt_t i = 0; i < fParams.size(); i++) {
+    std::string name = fParams.at(i);
+    fThrownVals[name] = fCurVals[name];
   }
 
-  // Parse given routines
-  fRoutines = GeneralUtils::ParseToStr(fStrategy, ",");
-  if (fRoutines.empty()) {
-    ERR(FTL) << "Trying to run ComparisonRoutines with no routines given!" << std::endl;
-    throw;
-  }
+  for (PullListConstIter iter = fInputThrows.begin();
+       iter != fInputThrows.end(); iter++) {
+    ParamPull* pull = *iter;
 
-  for (UInt_t i = 0; i < fRoutines.size(); i++) {
-    std::string routine = fRoutines.at(i);
+    pull->ThrowCovariance();
+    TH1D dialhist = pull->GetDataHist();
 
-    LOG(FIT) << "Routine: " << routine << std::endl;
-    if (!routine.compare("Compare")) {
-      UpdateRWEngine(fCurVals);
-      GenerateComparison();
-      PrintState();
-      SaveCurrentState();
+    for (int i = 0; i < dialhist.GetNbinsX(); i++) {
+      std::string name = std::string(dialhist.GetXaxis()->GetBinLabel(i + 1));
+      if (fCurVals.find(name) != fCurVals.end()) {
+        fThrownVals[name] = dialhist.GetBinContent(i + 1);
+      }
     }
+
+    // Reset throw incase pulls are calculated.
+    pull->ResetToy();
+
   }
 
+  // Now update Parameters
+  UpdateRWEngine(fThrownVals);
 
+  // Update Pulls
+  for (PullListConstIter iter = fInputThrows.begin();
+       iter != fInputThrows.end(); iter++) {
+    ParamPull* pull = *iter;
+    pull->Reconfigure();
+  }
 
   return;
-}
+};
 
 //*************************************
-void ComparisonRoutines::GenerateComparison() {
-  //*************************************
-  LOG(FIT) << "Generating Comparison." << std::endl;
-  // Main Event Loop from event Manager
-  fSampleFCN->ReconfigureAllEvents();
-  return;
-
-}
-
+void BayesianRoutines::Run() {
 //*************************************
-void ComparisonRoutines::PrintState() {
-  //*************************************
-  LOG(FIT) << "------------" << std::endl;
-
-  // Count max size
-  int maxcount = 0;
-  for (UInt_t i = 0; i < fParams.size(); i++) {
-    maxcount = max(int(fParams[i].size()), maxcount);
-  }
-
-  // Header
-  LOG(FIT) << " #    " << left << setw(maxcount) << "Parameter "
-           << " = " << setw(10) << "Value"
-           << " +- " << setw(10) << "Error"
-           << " " << setw(8) << "(Units)"
-           << " " << setw(10) << "Conv. Val"
-           << " +- " << setw(10) << "Conv. Err"
-           << " " << setw(8) << "(Units)" << std::endl;
-
-  // Parameters
-  for (UInt_t i = 0; i < fParams.size(); i++) {
-    std::string syst = fParams.at(i);
-
-    std::string typestr = FitBase::ConvDialType(fTypeVals[syst]);
-    std::string curunits = "(sig.)";
-    double curval = fCurVals[syst];
-    double curerr = 0.0;
-
-    if (fStateVals[syst].find("ABS") != std::string::npos) {
-      curval = FitBase::RWSigmaToAbs(typestr, syst, curval);
-      curerr = (FitBase::RWSigmaToAbs(typestr, syst, curerr) -
-                FitBase::RWSigmaToAbs(typestr, syst, 0.0));
-      curunits = "(Abs.)";
-    } else if (fStateVals[syst].find("FRAC") != std::string::npos) {
-      curval = FitBase::RWSigmaToFrac(typestr, syst, curval);
-      curerr = (FitBase::RWSigmaToFrac(typestr, syst, curerr) -
-                FitBase::RWSigmaToFrac(typestr, syst, 0.0));
-      curunits = "(Frac)";
-    }
 
-    std::string convunits = "(" + FitBase::GetRWUnits(typestr, syst) + ")";
-    double convval = FitBase::RWSigmaToAbs(typestr, syst, curval);
-    double converr = (FitBase::RWSigmaToAbs(typestr, syst, curerr) -
-                      FitBase::RWSigmaToAbs(typestr, syst, 0.0));
+  std::cout << "Running routines " << std::endl;
+  fRoutines = GeneralUtils::ParseToStr(fStrategy, ",");
 
-    std::ostringstream curparstring;
+  for (UInt_t i = 0; i < fRoutines.size(); i++) {
 
-    curparstring << " " << setw(3) << left << i << ". " << setw(maxcount)
-                 << syst << " = " << setw(10) << curval << " +- " << setw(10)
-                 << curerr << " " << setw(8) << curunits << " " << setw(10)
-                 << convval << " +- " << setw(10) << converr << " " << setw(8)
-                 << convunits;
+    std::string routine = fRoutines.at(i);
+    LOG(FIT) << "Running Routine: " << routine << std::endl;
 
-    LOG(FIT) << curparstring.str() << std::endl;
+    if (!routine.compare("BayesianThrows")) GenerateThrows();
+    else THROW("UNKNOWN ROUTINE " << routine);
   }
 
-  LOG(FIT) << "------------" << std::endl;
-  double like = fSampleFCN->GetLikelihood();
-  LOG(FIT) << std::left << std::setw(46) << "Likelihood for JointFCN: " << like << std::endl;
-  LOG(FIT) << "------------" << std::endl;
+  return;
 }
 
-/*
-  Write Functions
-*/
 //*************************************
-void ComparisonRoutines::SaveCurrentState(std::string subdir) {
+void BayesianRoutines::GenerateThrows() {
 //*************************************
 
-  LOG(FIT) << "Saving current full FCN predictions" << std::endl;
+  // Create a new output file
+  TFile* outfile = new TFile((fOutputFile + ".throws.root").c_str(), "RECREATE");
+  outfile->cd();
+
+  int nthrows = fNThrows;
+
+  // Setting Seed
+  // Matteo Mazzanti's Fix
+  struct timeval mytime;
+  gettimeofday(&mytime, NULL);
+  Double_t seed = time(NULL) + int(getpid()) + (mytime.tv_sec * 1000.) + (mytime.tv_usec / 1000.);
+  gRandom->SetSeed(seed);
+  LOG(FIT) << "Using Seed : " << seed << std::endl;
+  LOG(FIT) << "nthrows = " << nthrows << std::endl;
+
+  // Run the Initial Reconfigure
+  LOG(FIT) << "Making nominal prediction " << std::endl;
+  TDirectory* nominal = (TDirectory*) outfile->mkdir("nominal");
+  nominal->cd();
+  UpdateRWEngine(fStartVals);
+  fSampleFCN->ReconfigureUsingManager();
+  fSampleFCN->Write();
 
-  // Setup DIRS
-  TDirectory* curdir = gDirectory;
-  if (!subdir.empty()) {
-    TDirectory* newdir = (TDirectory*)gDirectory->mkdir(subdir.c_str());
-    newdir->cd();
+  // Create an iteration tree inside SampleFCN
+  fSampleFCN->CreateIterationTree("error_iterations", FitBase::GetRW());
+
+  // Create a new iteration TTree
+  TTree* LIKETREE = new TTree("likelihood", "likelihood");
+  std::vector<std::string> likenames = fSampleFCN->GetAllNames();
+  std::vector<double>      likevals  = fSampleFCN->GetAllLikelihoods();
+  std::vector<int>         likendof  = fSampleFCN->GetAllNDOF();
+  double* LIKEVALS = new double[likevals.size()];
+  int* LIKENDOF = new int[likendof.size()];
+
+  for (size_t i = 0; i < likendof.size(); i++) {
+    LIKETREE->Branch( (likenames[i] + "_likelihood"  ).c_str(), &LIKEVALS[i], 
+                      (likenames[i] + "_likelihood/D").c_str() );
+    LIKETREE->Branch( (likenames[i] + "_ndof"  ).c_str(),       &LIKENDOF[i], 
+                      (likenames[i] + "_ndof/I").c_str()       );
+    LIKENDOF[i] = likendof[i];
   }
 
-  fSampleFCN->Write();
+  likenames .clear();
+  likevals  .clear();
+  likendof  .clear();
 
-  // Change back to current DIR
-  curdir->cd();
+  double* PARAMVALS = new double[fParams.size()];
+  for (size_t i = 0; i < fParams.size(); i++){
+    LIKETREE->Branch( fParams[i].c_str(), &PARAMVALS[i], (fParams[i] + "/D").c_str() );
+  }
 
-  return;
-}
+  // Run Throws and save
+  for (Int_t i = 0; i < nthrows; i++) {
 
-//*************************************
-void ComparisonRoutines::SaveNominal() {
-  //*************************************
+    // Skip the start throw
+    if (i == 0) continue;
+    LOG(FIT) << "Throw " << i << " ================================" << std::endl;
 
-  fOutputRootFile->cd();
+    // Throw Parameters
+    ThrowParameters();
+    FitBase::GetRW()->Print();
 
-  LOG(FIT) << "Saving Nominal Predictions (be cautious with this)" << std::endl;
-  FitBase::GetRW()->Reconfigure();
-  GenerateComparison();
-  SaveCurrentState("nominal");
-};
+    // Get Parameter Values
+    for (size_t i = 0; i < fParams.size(); i++){
+      PARAMVALS[i] = fThrownVals[fParams[i]];
+    }
+
+    // Run Sample Prediction
+    fSampleFCN->ReconfigureFastUsingManager();
 
+    // Get vector of likelihoods/ndof
+    std::vector<double> likevals = fSampleFCN->GetAllLikelihoods();
+    for (size_t i = 0; i < likevals.size(); i++) {
+      LIKEVALS[i] = likevals[i];
+    }
+
+    // Save to TTree
+    LIKETREE->Fill();
+
+    // Save the FCN
+    // if (fSavePredictions){ SaveSamplePredictions(); }
+    LOG(FIT) << "END OF THROW ================================" << std::endl;
 
+  }
+
+  // Finish up
+  outfile->cd();
+  LIKETREE->Write();
+  outfile->Close();
+  delete LIKEVALS;
+  delete LIKENDOF;
+  delete PARAMVALS;
+}
diff --git a/src/Routines/SplineRoutines.h b/src/Routines/BayesianRoutines.h
similarity index 60%
copy from src/Routines/SplineRoutines.h
copy to src/Routines/BayesianRoutines.h
index a56f692..777e716 100755
--- a/src/Routines/SplineRoutines.h
+++ b/src/Routines/BayesianRoutines.h
@@ -1,197 +1,183 @@
 // Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret
 
 /*******************************************************************************
 *    This file is part of NUISANCE.
 *
 *    NUISANCE is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    NUISANCE is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with NUISANCE.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
 
-#ifndef SPLINE_ROUTINES_H
-#define SPLINE_ROUTINES_H
+#ifndef BAYESIAN_ROUTINES_H
+#define BAYESIAN_ROUTINES_H
 
 /*!
  *  \addtogroup Minimizer
  *  @{
  */
 
 #include "TH1.h"
 #include "TF1.h"
 #include "TMatrixD.h"
 #include "TVectorD.h"
 #include "TSystem.h"
 #include "TFile.h"
 #include "TProfile.h"
 
-
+#include <sys/time.h>
 #include <vector>
 #include <string>
 #include <iostream>
 #include <sstream>
 #include <cstring>
 
 #include "FitEvent.h"
 #include "JointFCN.h"
-#include "FitParameters.h"
-#include "FitLogger.h"
-#include "BaseFitEvt.h"
-#include "NuisConfig.h"
-#include "NuisKey.h"
-#include "SplineReader.h"
-#include "SplineWriter.h"
-#include "SplineMerger.h"
+
 #include "ParserUtils.h"
-#include "OpenMPWrapper.h"
+
 enum minstate {
   kErrorStatus = -1,
   kGoodStatus,
   kFitError,
   kNoChange,
   kFitFinished,
   kFitUnfinished,
   kStateChange,
 };
 
 //*************************************
 //! Collects all possible fit routines into a single class to avoid repeated code
-class SplineRoutines{
+class BayesianRoutines{
 //*************************************
 
 public:
 
   /*
     Constructor/Destructor
   */
 
   //! Constructor reads in arguments given at the command line for the fit here.
-  SplineRoutines(int argc, char* argv[]);
+  BayesianRoutines(int argc, char* argv[]);
     
   //! Default destructor
-  ~SplineRoutines();
+  ~BayesianRoutines();
 
   //! Reset everything to default/NULL
   void Init();
   
   /*
     Input Functions
   */
 
   //! Splits the arguments ready for initial setup
   void ParseArgs(int argc, char* argv[]);
-  
+
+  //! Sorts out configuration and verbosity right at the very start.
+  //! Calls readCard to set everything else up.
+  void InitialSetup();
+
   /*
     Setup Functions
   */
-
-  //! Setup the configuration given the arguments passed at the commandline and card file
-  void SetupConfig();
+  void SetupSystematicsFromXML();
 
   //! Setups up our custom RW engine with all the parameters passed in the card file
   void SetupRWEngine();
 
-  void Run();
-  void SaveEvents();
-  void TestEvents();
-  void GenerateEventSplines();
-  void GenerateEventWeights();
-  void GenerateEventWeightChunks(int procchunk = -1);
-  void BuildEventSplines(int procchunk = -1);
-  void MergeEventSplinesChunks();
-  /* 
-    Testing Functions
-  */
-  
-  /// Scan parameter space in 1D at finer resolution than points. Compare Raw/Spline on an event by event basis.
-  void TestSplines_1DEventScan();
-
-  /// Scan parameter space in 1D at finer resolution than points. Compare likelihoods for all testsamples.
-  void TestSplines_1DLikelihoodScan();
-
-  /// Randomly throw in parameter space. For each throw, calc average weight difference.
-  void TestSplines_NDEventThrow();
-
-  /// Randomly thow in parameter space. For each throw, calc likelihood difference for each sample.
-  void TestSplines_NDLikelihoodThrow();
-
-
-  /// Generate a set of spline vs weight canvases and save to file
-  void SaveSplinePlots();
+  //! Setups up the jointFCN.
+  void SetupFCN();
 
   /*
     Fitting Functions
   */
 
+  //! Main function to actually start iterating over the different required fit routines
+  void Run();
+
   //! Given a new map change the values that the RW engine is currently set to
   void UpdateRWEngine(std::map<std::string,double>& updateVals);
 
-  /*
-    MISC Functions
-  */
-
-  //! Get previous fit status from a file
-  Int_t GetStatus();
+  //! Given a single routine (see tutorial for options) run that fit routine now.
+  int RunFitRoutine(std::string routine);
 
-  void MergeSplines();
+  //! Throw the current covariance of dial values we have, and fill the thrownVals and thrownNorms maps.
+  //! If uniformly is true parameters will be thrown uniformly between their upper and lower limits.
+  void ThrowParameters();
 
+  //! Run Throws   
+  void GenerateThrows();
+ 
 protected:
 
   //! Our Custom ReWeight Object
   FitWeight* rw;
-  FitWeight* fRW;
-  
+
   std::string fOutputFile;
   std::string fInputFile;
 
   TFile* fInputRootFile;
   TFile* fOutputRootFile;
-  
+
+  //! Flag for whether the fit should be continued if an output file is already found.
+  bool fitContinue;
+
+  //! Minimizer Object for handling roots different minimizer methods
   JointFCN* fSampleFCN;
-  std::list<MeasurementBase*> fSamples;
-  
+
+  int nfreepars;
+
   std::string fCardFile;
 
   std::string fStrategy;
   std::vector<std::string> fRoutines;
   std::string fAllowedRoutines;
   
+  std::string fFakeDataInput;
+
   // Input Dial Vals
   //! Vector of dial names
   std::vector<std::string> fParams;
   std::map<std::string, std::string> fStateVals;
   std::map<std::string, double>      fStartVals;
   std::map<std::string, double>      fCurVals;
   std::map<std::string, double>      fErrorVals;
   std::map<std::string, double>      fMinVals;
   std::map<std::string, double>      fMaxVals;
   std::map<std::string, double>      fStepVals;
   std::map<std::string, int>         fTypeVals;
   std::map<std::string, bool>        fFixVals;
   std::map<std::string, bool>        fStartFixVals;
 
-  std::vector<std::string> fGenericInputNames;
-  std::map<std::string, std::string> fGenericInputFiles;
-  std::map<std::string, std::string> fGenericOutputFiles;
-  std::map<std::string, std::string> fGenericOutputTypes;
-  std::map<std::string, InputHandlerBase*> fGenericInputs;
+  //! Vector of fake parameter names
+  std::map<std::string,double> fFakeVals;
+
+  //! Map of thrown parameter names and values (After ThrowCovariance)
+  std::map<std::string,double> fThrownVals;
+
+
+  std::list   <ParamPull*>  fInputThrows; //!< Pointers to pull terms
+  std::vector <TH1D>        fInputDials; //!< Vector of Input Histograms
+  std::vector <TMatrixDSym> fInputCovar; //!< Vector of Input Covariances  
+
+  nuiskey fCompKey;
+  std::vector<std::string> fThrowList;
+  std::string fThrowString;
+
+  int fNThrows;
+  int fStartThrows;
 
 
-  std::vector<std::string> fSplineNames;
-  std::map<std::string, std::string> fSplineTypes;
-  std::map<std::string, std::string> fSplinePoints;
-    nuiskey fCompKey;
-  
-  
 };
 
 /*! @} */
 #endif
diff --git a/src/Routines/CMakeLists.txt b/src/Routines/CMakeLists.txt
index 2c5cf1c..a87e4a0 100644
--- a/src/Routines/CMakeLists.txt
+++ b/src/Routines/CMakeLists.txt
@@ -1,66 +1,68 @@
 # Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret
 
 ################################################################################
 #    This file is part of NUISANCE.
 #
 #    NUISANCE is free software: you can redistribute it and/or modify
 #    it under the terms of the GNU General Public License as published by
 #    the Free Software Foundation, either version 3 of the License, or
 #    (at your option) any later version.
 #
 #    NUISANCE is distributed in the hope that it will be useful,
 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 #    GNU General Public License for more details.
 #
 #    You should have received a copy of the GNU General Public License
 #    along with NUISANCE.  If not, see <http://www.gnu.org/licenses/>.
 ################################################################################
 set(IMPLFILES
 ComparisonRoutines.cxx
 SystematicRoutines.cxx
 SplineRoutines.cxx
+BayesianRoutines.cxx
 )
 
 if(USE_MINIMIZER)
   set(IMPLFILES ${IMPLFILES};MinimizerRoutines.cxx)
 endif()
 
 set(HEADERFILES
 ComparisonRoutines.h
 SystematicRoutines.h
+BayesianRoutines.h
 SplineRoutines.h
 )
 
 if(USE_MINIMIZER)
   set(HEADERFILES ${HEADERFILES};MinimizerRoutines.h)
 endif()
 
 set(LIBNAME Routines)
 
 if(CMAKE_BUILD_TYPE MATCHES DEBUG)
   add_library(${LIBNAME} STATIC ${IMPLFILES})
 else(CMAKE_BUILD_TYPE MATCHES RELEASE)
   add_library(${LIBNAME} SHARED ${IMPLFILES})
 endif()
 
 include_directories(${EXP_INCLUDE_DIRECTORIES})
 
 include_directories(${MINIMUM_INCLUDE_DIRECTORIES})
 
 include_directories(${CMAKE_SOURCE_DIR}/src/FCN)
 include_directories(${CMAKE_SOURCE_DIR}/src/MCStudies)
 
 set_target_properties(${LIBNAME} PROPERTIES VERSION
   "${NUISANCE_VERSION_MAJOR}.${NUISANCE_VERSION_MINOR}.${NUISANCE_VERSION_REVISION}")
 #set_target_properties(${LIBNAME} PROPERTIES LINK_FLAGS ${ROOT_LD_FLAGS})
 
 if(DEFINED PROJECTWIDE_EXTRA_DEPENDENCIES)
   add_dependencies(${LIBNAME} ${PROJECTWIDE_EXTRA_DEPENDENCIES})
 endif()
 
 install(TARGETS ${LIBNAME} DESTINATION lib)
 #Can uncomment this to install the headers... but is it really neccessary?
 #install(FILES ${HEADERFILES} DESTINATION include)
 
 set(MODULETargets ${MODULETargets} ${LIBNAME} PARENT_SCOPE)
diff --git a/src/Routines/ComparisonRoutines.cxx b/src/Routines/ComparisonRoutines.cxx
index c5463c0..1f4f7bb 100755
--- a/src/Routines/ComparisonRoutines.cxx
+++ b/src/Routines/ComparisonRoutines.cxx
@@ -1,537 +1,532 @@
 // Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret
 
 /*******************************************************************************
 *    This file is part of NUISANCE.
 *
 *    NUISANCE is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    NUISANCE is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with NUISANCE.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
 #include "ComparisonRoutines.h"
 
 /*
   Constructor/Destructor
 */
 //************************
 void ComparisonRoutines::Init() {
 //************************
 
   fOutputFile = "";
   fOutputRootFile = NULL;
 
   fStrategy = "Compare";
 
   fRoutines.clear();
 
   fCardFile = "";
 
   fFakeDataInput = "";
 
   fSampleFCN = NULL;
 
   fAllowedRoutines = ("Compare");
-  
+
 };
 
 //*************************************
 ComparisonRoutines::~ComparisonRoutines() {
 //*************************************
 };
 
 
 
 /*
   Input Functions
 */
 //*************************************
 ComparisonRoutines::ComparisonRoutines(int argc, char* argv[]) {
 //*************************************
 
   // Initialise Defaults
   Init();
   nuisconfig configuration = Config::Get();
 
   // Default containers
   std::string cardfile = "";
   std::string maxevents = "-1";
   int errorcount = 0;
   int verbocount = 0;
   std::vector<std::string> xmlcmds;
   std::vector<std::string> configargs;
 
   // Make easier to handle arguments.
   std::vector<std::string> args = GeneralUtils::LoadCharToVectStr(argc, argv);
   ParserUtils::ParseArgument(args, "-c", fCardFile, true);
   ParserUtils::ParseArgument(args, "-o", fOutputFile, false, false);
   ParserUtils::ParseArgument(args, "-n", maxevents, false, false);
   ParserUtils::ParseArgument(args, "-f", fStrategy, false, false);
   ParserUtils::ParseArgument(args, "-d", fFakeDataInput, false, false);
   ParserUtils::ParseArgument(args, "-i", xmlcmds);
   ParserUtils::ParseArgument(args, "-q", configargs);
   ParserUtils::ParseCounter(args, "e", errorcount);
   ParserUtils::ParseCounter(args, "v", verbocount);
   ParserUtils::CheckBadArguments(args);
 
   // Add extra defaults if none given
   if (fCardFile.empty() and xmlcmds.empty()) {
     ERR(FTL) << "No input supplied!" << std::endl;
     throw;
   }
 
   if (fOutputFile.empty() and !fCardFile.empty()) {
     fOutputFile = fCardFile + ".root";
     ERR(WRN) << "No output supplied so saving it to: " << fOutputFile << std::endl;
 
   } else if (fOutputFile.empty()) {
     ERR(FTL) << "No output file or cardfile supplied!" << std::endl;
     throw;
   }
 
   // Configuration Setup =============================
 
   // Check no comp key is available
   nuiskey fCompKey;
   if (Config::Get().GetNodes("nuiscomp").empty()) {
     fCompKey = Config::Get().CreateNode("nuiscomp");
   } else {
     fCompKey = Config::Get().GetNodes("nuiscomp")[0];
   }
 
-  if (!fCardFile.empty())   fCompKey.AddS("cardfile", fCardFile);
-  if (!fOutputFile.empty()) fCompKey.AddS("outputfile", fOutputFile);
-  if (!fStrategy.empty())   fCompKey.AddS("strategy", fStrategy);
+  if (!fCardFile.empty())   fCompKey.Set("cardfile", fCardFile);
+  if (!fOutputFile.empty()) fCompKey.Set("outputfile", fOutputFile);
+  if (!fStrategy.empty())   fCompKey.Set("strategy", fStrategy);
 
   // Load XML Cardfile
-  configuration.LoadConfig( fCompKey.GetS("cardfile"), "");
-
-  // Add CMD XML Structs
-  for (size_t i = 0; i < xmlcmds.size(); i++) {
-    configuration.AddXMLLine(xmlcmds[i]);
-  }
+  configuration.LoadSettings( fCompKey.GetS("cardfile"), "");
 
   // Add Config Args
   for (size_t i = 0; i < configargs.size(); i++) {
     configuration.OverrideConfig(configargs[i]);
   }
   if (maxevents.compare("-1")){
     configuration.OverrideConfig("MAXEVENTS=" + maxevents);
   }
 
   // Finish configuration XML
-  configuration.FinaliseConfig(fCompKey.GetS("outputfile") + ".xml");
+  configuration.FinaliseSettings(fCompKey.GetS("outputfile") + ".xml");
 
   // Add Error Verbo Lines
-  verbocount += Config::Get().GetParI("VERBOSITY");
-  errorcount += Config::Get().GetParI("ERROR");
-  bool trace = Config::Get().GetParB("TRACE");
+  verbocount += Config::GetParI("VERBOSITY");
+  errorcount += Config::GetParI("ERROR");
+  bool trace = Config::GetParB("TRACE");
   std::cout << "[ NUISANCE ]: Setting VERBOSITY=" << verbocount << std::endl;
   std::cout << "[ NUISANCE ]: Setting ERROR=" << errorcount << std::endl;
   SETVERBOSITY(verbocount);
   SETTRACE(trace);
 
   // Comparison Setup ========================================
 
   // Proper Setup
   fOutputRootFile = new TFile(fCompKey.GetS("outputfile").c_str(), "RECREATE");
   SetupComparisonsFromXML();
 
   SetupRWEngine();
   SetupFCN();
 
   return;
 };
 
 //*************************************
 void ComparisonRoutines::SetupComparisonsFromXML() {
 //*************************************
 
   LOG(FIT) << "Setting up nuiscomp" << std::endl;
 
   // Setup Parameters ------------------------------------------
   std::vector<nuiskey> parkeys = Config::QueryKeys("parameter");
   if (!parkeys.empty()) {
     LOG(FIT) << "Number of parameters :  " << parkeys.size() << std::endl;
   }
 
   for (size_t i = 0; i < parkeys.size(); i++) {
     nuiskey key = parkeys.at(i);
 
     // Check for type,name,nom
     if (!key.Has("type")) {
       ERR(FTL) << "No type given for parameter " << i << std::endl;
       ERR(FTL) << "type='PARAMETER_TYPE'" << std::endl;
       throw;
     } else if (!key.Has("name")) {
       ERR(FTL) << "No name given for parameter " << i << std::endl;
       ERR(FTL) << "name='SAMPLE_NAME'" << std::endl;
       throw;
     } else if (!key.Has("nominal")) {
       ERR(FTL) << "No nominal given for parameter " << i << std::endl;
       ERR(FTL) << "nominal='NOMINAL_VALUE'" << std::endl;
       throw;
     }
 
     // Get Inputs
     std::string partype = key.GetS("type");
     std::string parname = key.GetS("name");
     double parnom  = key.GetD("nominal");
     double parlow  = parnom - 1;
     double parhigh = parnom + 1;
     double parstep = 1;
 
     // override if state not given
     if (!key.Has("state")){
       key.SetS("state","FIX");
     }
 
     std::string parstate = key.GetS("state");
 
     // Check for incomplete limtis
     int limdef = ((int)key.Has("low")  +
                   (int)key.Has("high") +
                   (int)key.Has("step"));
 
     if (limdef > 0 and limdef < 3){
       ERR(FTL) << "Incomplete limit set given for parameter : " << parname << std::endl;
       ERR(FTL) << "Requires: low='LOWER_LIMIT' high='UPPER_LIMIT' step='STEP_SIZE' " << std::endl;
       throw;
     }
 
     // Extra limits
     if (key.Has("low")) {
 
       parlow  = key.GetD("low");
       parhigh = key.GetD("high");
       parstep = key.GetD("step");
 
       LOG(FIT) << "Read " << partype << " : "
                << parname << " = "
                << parnom << " : "
                << parlow << " < p < " << parhigh
                << " : " << parstate << std::endl;
     } else {
       LOG(FIT) << "Read " << partype << " : "
                << parname << " = "
                << parnom << " : "
                << parstate << std::endl;
     }
 
     // Convert if required
     if (parstate.find("ABS") != std::string::npos) {
       parnom  = FitBase::RWAbsToSigma( partype, parname, parnom  );
       parlow  = FitBase::RWAbsToSigma( partype, parname, parlow  );
       parhigh = FitBase::RWAbsToSigma( partype, parname, parhigh );
       parstep = FitBase::RWAbsToSigma( partype, parname, parstep );
     } else if (parstate.find("FRAC") != std::string::npos) {
       parnom  = FitBase::RWFracToSigma( partype, parname, parnom  );
       parlow  = FitBase::RWFracToSigma( partype, parname, parlow  );
       parhigh = FitBase::RWFracToSigma( partype, parname, parhigh );
       parstep = FitBase::RWFracToSigma( partype, parname, parstep );
     }
 
     // Push into vectors
     fParams.push_back(parname);
 
     fTypeVals[parname]  = FitBase::ConvDialType(partype);;
     fCurVals[parname]   = parnom;
     fStateVals[parname] = parstate;
 
   }
 
   // Setup Samples ----------------------------------------------
   std::vector<nuiskey> samplekeys =  Config::QueryKeys("sample");
   if (!samplekeys.empty()) {
     LOG(FIT) << "Number of samples : " << samplekeys.size() << std::endl;
   }
 
   for (size_t i = 0; i < samplekeys.size(); i++) {
     nuiskey key = samplekeys.at(i);
 
     // Get Sample Options
     std::string samplename = key.GetS("name");
     std::string samplefile = key.GetS("input");
 
     std::string sampletype =
       key.Has("type") ? key.GetS("type") : "DEFAULT";
 
     double samplenorm =
       key.Has("norm") ? key.GetD("norm") : 1.0;
 
     // Print out
     LOG(FIT) << "Read Sample " << i << ". : "
              << samplename << " (" << sampletype << ") [Norm=" << samplenorm<<"]"<< std::endl
              << "                                -> input='" << samplefile  << "'" << std::endl;
 
     // If FREE add to parameters otherwise continue
     if (sampletype.find("FREE") == std::string::npos) {
       continue;
     }
 
     // Form norm dial from samplename + sampletype + "_norm";
     std::string normname = samplename + "_norm";
 
     // Check normname not already present
     if (fTypeVals.find("normname") != fTypeVals.end()) {
       continue;
     }
 
     // Add new norm dial to list if its passed above checks
     fParams.push_back(normname);
 
     fTypeVals[normname] = kNORM;
     fStateVals[normname] = sampletype;
     fCurVals[normname] = samplenorm;
 
   }
 
   // Setup Fake Parameters -----------------------------
   std::vector<nuiskey> fakekeys = Config::QueryKeys("fakeparameter");
   if (!fakekeys.empty()) {
     LOG(FIT) << "Number of fake parameters : " << fakekeys.size() << std::endl;
   }
 
   for (size_t i = 0; i < fakekeys.size(); i++) {
     nuiskey key = fakekeys.at(i);
 
     // Check for type,name,nom
     if (!key.Has("name")) {
       ERR(FTL) << "No name given for fakeparameter " << i << std::endl;
       throw;
     } else if (!key.Has("nominal")) {
       ERR(FTL) << "No nominal given for fakeparameter " << i << std::endl;
       throw;
     }
 
     // Get Inputs
     std::string parname = key.GetS("name");
     double parnom  = key.GetD("nominal");
 
     // Push into vectors
     fFakeVals[parname] = parnom;
   }
 }
 
 //*************************************
 void ComparisonRoutines::SetupRWEngine() {
 //*************************************
 
   LOG(FIT) << "Setting up FitWeight Engine" << std::endl;
   for (UInt_t i = 0; i < fParams.size(); i++) {
     std::string name = fParams[i];
     FitBase::GetRW()->IncludeDial(name, fTypeVals.at(name));
   }
 
   return;
 }
 
 //*************************************
 void ComparisonRoutines::SetupFCN() {
   //*************************************
 
   LOG(FIT) << "Building the SampleFCN" << std::endl;
   if (fSampleFCN) delete fSampleFCN;
-  FitPar::Config().out = fOutputRootFile;
+  Config::Get().out = fOutputRootFile;
   fOutputRootFile->cd();
   fSampleFCN = new JointFCN(fOutputRootFile);
   SetFakeData();
 
   return;
 }
 
 //*************************************
 void ComparisonRoutines::SetFakeData() {
 //*************************************
 
   if (fFakeDataInput.empty()) return;
 
   if (fFakeDataInput.compare("MC") == 0) {
     LOG(FIT) << "Setting fake data from MC starting prediction." << std::endl;
     UpdateRWEngine(fFakeVals);
 
     FitBase::GetRW()->Reconfigure();
     fSampleFCN->ReconfigureAllEvents();
     fSampleFCN->SetFakeData("MC");
 
     UpdateRWEngine(fCurVals);
 
     LOG(FIT) << "Set all data to fake MC predictions." << std::endl;
   } else {
     LOG(FIT) << "Setting fake data from: " << fFakeDataInput << std::endl;
     fSampleFCN->SetFakeData(fFakeDataInput);
   }
 
   return;
 }
 
 /*
   Fitting Functions
 */
 //*************************************
 void ComparisonRoutines::UpdateRWEngine(
   std::map<std::string, double>& updateVals) {
   //*************************************
 
   for (UInt_t i = 0; i < fParams.size(); i++) {
     std::string name = fParams[i];
 
     if (updateVals.find(name) == updateVals.end()) continue;
     FitBase::GetRW()->SetDialValue(name, updateVals.at(name));
   }
 
   FitBase::GetRW()->Reconfigure();
   return;
 }
 
 //*************************************
 void ComparisonRoutines::Run() {
 //*************************************
 
   LOG(FIT) << "Running ComparisonRoutines : " << fStrategy << std::endl;
 
   if (FitPar::Config().GetParB("save_nominal")) {
     SaveNominal();
   }
 
   // Parse given routines
   fRoutines = GeneralUtils::ParseToStr(fStrategy, ",");
   if (fRoutines.empty()) {
     ERR(FTL) << "Trying to run ComparisonRoutines with no routines given!" << std::endl;
     throw;
   }
 
   for (UInt_t i = 0; i < fRoutines.size(); i++) {
     std::string routine = fRoutines.at(i);
 
     LOG(FIT) << "Routine: " << routine << std::endl;
     if (!routine.compare("Compare")) {
       UpdateRWEngine(fCurVals);
       GenerateComparison();
       PrintState();
       SaveCurrentState();
     }
   }
 
 
 
   return;
 }
 
 //*************************************
 void ComparisonRoutines::GenerateComparison() {
   //*************************************
   LOG(FIT) << "Generating Comparison." << std::endl;
   // Main Event Loop from event Manager
   fSampleFCN->ReconfigureAllEvents();
   return;
 
 }
 
 //*************************************
 void ComparisonRoutines::PrintState() {
   //*************************************
   LOG(FIT) << "------------" << std::endl;
 
   // Count max size
   int maxcount = 0;
   for (UInt_t i = 0; i < fParams.size(); i++) {
     maxcount = max(int(fParams[i].size()), maxcount);
   }
 
   // Header
   LOG(FIT) << " #    " << left << setw(maxcount) << "Parameter "
            << " = " << setw(10) << "Value"
            << " +- " << setw(10) << "Error"
            << " " << setw(8) << "(Units)"
            << " " << setw(10) << "Conv. Val"
            << " +- " << setw(10) << "Conv. Err"
            << " " << setw(8) << "(Units)" << std::endl;
 
   // Parameters
   for (UInt_t i = 0; i < fParams.size(); i++) {
     std::string syst = fParams.at(i);
 
     std::string typestr = FitBase::ConvDialType(fTypeVals[syst]);
     std::string curunits = "(sig.)";
     double curval = fCurVals[syst];
     double curerr = 0.0;
 
     if (fStateVals[syst].find("ABS") != std::string::npos) {
       curval = FitBase::RWSigmaToAbs(typestr, syst, curval);
       curerr = (FitBase::RWSigmaToAbs(typestr, syst, curerr) -
                 FitBase::RWSigmaToAbs(typestr, syst, 0.0));
       curunits = "(Abs.)";
     } else if (fStateVals[syst].find("FRAC") != std::string::npos) {
       curval = FitBase::RWSigmaToFrac(typestr, syst, curval);
       curerr = (FitBase::RWSigmaToFrac(typestr, syst, curerr) -
                 FitBase::RWSigmaToFrac(typestr, syst, 0.0));
       curunits = "(Frac)";
     }
 
     std::string convunits = "(" + FitBase::GetRWUnits(typestr, syst) + ")";
     double convval = FitBase::RWSigmaToAbs(typestr, syst, curval);
     double converr = (FitBase::RWSigmaToAbs(typestr, syst, curerr) -
                       FitBase::RWSigmaToAbs(typestr, syst, 0.0));
 
     std::ostringstream curparstring;
 
     curparstring << " " << setw(3) << left << i << ". " << setw(maxcount)
                  << syst << " = " << setw(10) << curval << " +- " << setw(10)
                  << curerr << " " << setw(8) << curunits << " " << setw(10)
                  << convval << " +- " << setw(10) << converr << " " << setw(8)
                  << convunits;
 
     LOG(FIT) << curparstring.str() << std::endl;
   }
 
   LOG(FIT) << "------------" << std::endl;
   double like = fSampleFCN->GetLikelihood();
   LOG(FIT) << std::left << std::setw(46) << "Likelihood for JointFCN: " << like << std::endl;
   LOG(FIT) << "------------" << std::endl;
 }
 
 /*
   Write Functions
 */
 //*************************************
 void ComparisonRoutines::SaveCurrentState(std::string subdir) {
 //*************************************
 
   LOG(FIT) << "Saving current full FCN predictions" << std::endl;
 
   // Setup DIRS
   TDirectory* curdir = gDirectory;
   if (!subdir.empty()) {
     TDirectory* newdir = (TDirectory*)gDirectory->mkdir(subdir.c_str());
     newdir->cd();
   }
 
   fSampleFCN->Write();
 
   // Change back to current DIR
   curdir->cd();
 
   return;
 }
 
 //*************************************
 void ComparisonRoutines::SaveNominal() {
   //*************************************
 
   fOutputRootFile->cd();
 
   LOG(FIT) << "Saving Nominal Predictions (be cautious with this)" << std::endl;
   FitBase::GetRW()->Reconfigure();
   GenerateComparison();
   SaveCurrentState("nominal");
 };
 
 
diff --git a/src/Routines/ComparisonRoutines.h b/src/Routines/ComparisonRoutines.h
index 701481c..1d967ac 100755
--- a/src/Routines/ComparisonRoutines.h
+++ b/src/Routines/ComparisonRoutines.h
@@ -1,168 +1,168 @@
 // Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret
 
 /*******************************************************************************
 *    This file is part of NUISANCE.
 *
 *    NUISANCE is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    NUISANCE is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with NUISANCE.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
 #ifndef COMPARISON_ROUTINES_H
 #define COMPARISON_ROUTINES_H
 /*! \addtogroup Routines @{ */
 
 #include "TH1.h"
 #include "TF1.h"
 #include "TMatrixD.h"
 #include "TVectorD.h"
 #include "TSystem.h"
 #include "TFile.h"
 #include "TProfile.h"
 
 #include <vector>
 #include <string>
 #include <iostream>
 #include <sstream>
 #include <cstring>
 
 #include "FitEvent.h"
 #include "JointFCN.h"
-#include "FitParameters.h"
+
 #include "GeneralUtils.h"
 #include "NuisConfig.h"
 #include "NuisKey.h"
 #include "FitLogger.h"
 #include "ParserUtils.h"
 
 enum minstate {
   kErrorStatus = -1,
   kGoodStatus,
   kFitError,
   kNoChange,
   kFitFinished,
   kFitUnfinished,
   kStateChange,
 };
 
 //*************************************
 /// Collects all possible fit routines into a single class to avoid repeated code
 class ComparisonRoutines {
 //*************************************
 
 public:
 
   /*
     Constructor/Destructor
   */
 
   /// Constructor reads in arguments given at the command line for the fit here.
   ComparisonRoutines(int argc, char* argv[]);
     
   /// Default destructor
   ~ComparisonRoutines();
 
   /// Reset everything to default/NULL
   void Init();
   
   /*
     Input Functions
   */
 
   /// Queries configuration keys to setup Parameters/Samples/FakeParameters
   void SetupComparisonsFromXML();
 
   /*
     Setup Functions
   */
 
   /// Setups up our custom RW engine with all the parameters passed in the card file
   void SetupRWEngine();
 
   /// Setups up the jointFCN.
   void SetupFCN();
 
   /// Set the current data histograms in each sample to the fake data.
   void SetFakeData();
 
   /*
     Fitting Functions
   */
 
   /// Main function to actually start iterating over the different required fit routines
   void Run();
 
   /// Creates a comparison from FCN
   void GenerateComparison();
   
   /// Given a new map change the values that the RW engine is currently set to
   void UpdateRWEngine(std::map<std::string,double>& updateVals);
 
   /// Print current value
   void PrintState();
   
   /*
     Write Functions
   */
 
   /// Save the sample plots for current MC
   /// dir if not empty forces plots to be saved in a subdirectory of outputfile
   void SaveCurrentState(std::string subdir="");
 
   /// Save starting predictions into a seperate folder
   void SaveNominal();
 
   /*
     MISC Functions
   */
 
   /// Get previous fit status from a file
   Int_t GetStatus();
 
 protected:
 
   //! Our Custom ReWeight Object
   FitWeight* rw;
 
   std::string fOutputFile; ///< Output file name
   // std::string fInputFile;  ///< Input file name
 
   // TFile* fInputRootFile;   ///< 
   TFile* fOutputRootFile; ///< Output ROOT TFile
 
   JointFCN* fSampleFCN; ///< Joint Samples Container that handles reconfigures.
 
   std::string fCardFile; ///< Input card/XML file.
 
   std::string fStrategy; ///< Comparison routine selection.
   std::vector<std::string> fRoutines; ///< Split vector of comparison routine selection.
   std::string fAllowedRoutines; ///< Hard coded list of allowed routines.
   
   /// Fake data flag. Can be 'MC' to use 'fake_parameter'
   /// or 'path_to_file.root' to use previous NUISANCE MC predictions.
   std::string fFakeDataInput; 
 
   // Input Dial Vals
   std::vector<std::string> fParams; ///< Vector of dial names.
   std::map<std::string, std::string> fStateVals; ///< Map of dial states
   std::map<std::string, double>      fCurVals; ///< Map of dial values
   std::map<std::string, int>         fTypeVals; ///< Map of dial type enums.
 
   // Fake Dial Vals
   std::map<std::string,double> fFakeVals; ///< Map of fake data settings.
 
   // Configuration
   nuiskey fCompKey; ///< Configuration Key for this Comparison Instance
 
 };
 
 /*! @} */
 #endif
diff --git a/src/Routines/MinimizerRoutines.cxx b/src/Routines/MinimizerRoutines.cxx
index e5ad2a5..ee3e995 100755
--- a/src/Routines/MinimizerRoutines.cxx
+++ b/src/Routines/MinimizerRoutines.cxx
@@ -1,1511 +1,1506 @@
 // Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret
 
 /*******************************************************************************
 *    This file is part of NUISANCE.
 *
 *    NUISANCE is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    NUISANCE is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with NUISANCE.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
 
 #include "MinimizerRoutines.h"
 
 #include "Simple_MH_Sampler.h"
 
 /*
   Constructor/Destructor
 */
 //************************
 void MinimizerRoutines::Init() {
   //************************
 
   fInputFile = "";
   fInputRootFile = NULL;
 
   fOutputFile = "";
   fOutputRootFile = NULL;
 
   fCovar = NULL;
   fCovFree = NULL;
   fCorrel = NULL;
   fCorFree = NULL;
   fDecomp = NULL;
   fDecFree = NULL;
 
   fStrategy = "Migrad,FixAtLimBreak,Migrad";
   fRoutines.clear();
 
   fCardFile = "";
 
   fFakeDataInput = "";
 
   fSampleFCN = NULL;
 
   fMinimizer = NULL;
   fMinimizerFCN = NULL;
   fCallFunctor = NULL;
 
   fAllowedRoutines =
       ("Migrad,Simplex,Combined,"
        "Brute,Fumili,ConjugateFR,"
        "ConjugatePR,BFGS,BFGS2,"
        "SteepDesc,GSLSimAn,FixAtLim,FixAtLimBreak,"
        "Chi2Scan1D,Chi2Scan2D,Contours,ErrorBands,"
        "DataToys,MCMC");
 };
 
 //*************************************
 MinimizerRoutines::~MinimizerRoutines(){
     //*************************************
 };
 
 /*
   Input Functions
 */
 //*************************************
 MinimizerRoutines::MinimizerRoutines(int argc, char* argv[]) {
   //*************************************
 
   // Initialise Defaults
   Init();
   nuisconfig configuration = Config::Get();
 
   // Default containers
   std::string cardfile = "";
   std::string maxevents = "-1";
   int errorcount = 0;
   int verbocount = 0;
   std::vector<std::string> xmlcmds;
   std::vector<std::string> configargs;
 
   // Make easier to handle arguments.
   std::vector<std::string> args = GeneralUtils::LoadCharToVectStr(argc, argv);
   ParserUtils::ParseArgument(args, "-c", fCardFile, true);
   ParserUtils::ParseArgument(args, "-o", fOutputFile, false, false);
   ParserUtils::ParseArgument(args, "-n", maxevents, false, false);
   ParserUtils::ParseArgument(args, "-f", fStrategy, false, false);
   ParserUtils::ParseArgument(args, "-d", fFakeDataInput, false, false);
   ParserUtils::ParseArgument(args, "-i", xmlcmds);
   ParserUtils::ParseArgument(args, "-q", configargs);
   ParserUtils::ParseCounter(args, "e", errorcount);
   ParserUtils::ParseCounter(args, "v", verbocount);
   ParserUtils::CheckBadArguments(args);
 
   // Add extra defaults if none given
   if (fCardFile.empty() and xmlcmds.empty()) {
     ERR(FTL) << "No input supplied!" << std::endl;
     throw;
   }
 
   if (fOutputFile.empty() and !fCardFile.empty()) {
     fOutputFile = fCardFile + ".root";
     ERR(WRN) << "No output supplied so saving it to: " << fOutputFile
              << std::endl;
 
   } else if (fOutputFile.empty()) {
     ERR(FTL) << "No output file or cardfile supplied!" << std::endl;
     throw;
   }
 
   // Configuration Setup =============================
 
   // Check no comp key is available
   nuiskey fCompKey;
   if (Config::Get().GetNodes("nuiscomp").empty()) {
     fCompKey = Config::Get().CreateNode("nuiscomp");
   } else {
     fCompKey = Config::Get().GetNodes("nuiscomp")[0];
   }
 
-  if (!fCardFile.empty()) fCompKey.AddS("cardfile", fCardFile);
-  if (!fOutputFile.empty()) fCompKey.AddS("outputfile", fOutputFile);
-  if (!fStrategy.empty()) fCompKey.AddS("strategy", fStrategy);
+  if (!fCardFile.empty())   fCompKey.Set("cardfile", fCardFile);
+  if (!fOutputFile.empty()) fCompKey.Set("outputfile", fOutputFile);
+  if (!fStrategy.empty())   fCompKey.Set("strategy", fStrategy);
 
   // Load XML Cardfile
-  configuration.LoadConfig(fCompKey.GetS("cardfile"), "");
-
-  // Add CMD XML Structs
-  for (size_t i = 0; i < xmlcmds.size(); i++) {
-    configuration.AddXMLLine(xmlcmds[i]);
-  }
+  configuration.LoadSettings( fCompKey.GetS("cardfile"), "");
 
   // Add Config Args
   for (size_t i = 0; i < configargs.size(); i++) {
     configuration.OverrideConfig(configargs[i]);
   }
   if (maxevents.compare("-1")) {
     configuration.OverrideConfig("MAXEVENTS=" + maxevents);
   }
 
   // Finish configuration XML
-  configuration.FinaliseConfig(fCompKey.GetS("outputfile") + ".xml");
+  configuration.FinaliseSettings(fCompKey.GetS("outputfile") + ".xml");
 
   // Add Error Verbo Lines
-  verbocount += Config::Get().GetParI("VERBOSITY");
-  errorcount += Config::Get().GetParI("ERROR");
+  verbocount += Config::GetParI("VERBOSITY");
+  errorcount += Config::GetParI("ERROR");
   std::cout << "[ NUISANCE ]: Setting VERBOSITY=" << verbocount << std::endl;
   std::cout << "[ NUISANCE ]: Setting ERROR=" << errorcount << std::endl;
   // FitPar::log_verb = verbocount;
   SETVERBOSITY(verbocount);
   // ERR_VERB(errorcount);
 
   // Minimizer Setup ========================================
   fOutputRootFile = new TFile(fCompKey.GetS("outputfile").c_str(), "RECREATE");
   SetupMinimizerFromXML();
 
   SetupCovariance();
   SetupRWEngine();
   SetupFCN();
 
   return;
 };
 
 //*************************************
 void MinimizerRoutines::SetupMinimizerFromXML() {
   //*************************************
 
   LOG(FIT) << "Setting up nuismin" << std::endl;
 
   // Setup Parameters ------------------------------------------
   std::vector<nuiskey> parkeys = Config::QueryKeys("parameter");
   if (!parkeys.empty()) {
     LOG(FIT) << "Number of parameters :  " << parkeys.size() << std::endl;
   }
 
   for (size_t i = 0; i < parkeys.size(); i++) {
     nuiskey key = parkeys.at(i);
 
     // Check for type,name,nom
     if (!key.Has("type")) {
       ERR(FTL) << "No type given for parameter " << i << std::endl;
       throw;
     } else if (!key.Has("name")) {
       ERR(FTL) << "No name given for parameter " << i << std::endl;
       throw;
     } else if (!key.Has("nominal")) {
       ERR(FTL) << "No nominal given for parameter " << i << std::endl;
       throw;
     }
 
     // Get Inputs
     std::string partype = key.GetS("type");
     std::string parname = key.GetS("name");
     double parnom = key.GetD("nominal");
     double parlow = parnom - 1;
     double parhigh = parnom + 1;
     double parstep = 1;
 
     // Override state if none given
     if (!key.Has("state")) {
       key.SetS("state", "FIX");
     }
 
     std::string parstate = key.GetS("state");
 
     // Extra limits
     if (key.Has("low")) {
       parlow = key.GetD("low");
       parhigh = key.GetD("high");
       parstep = key.GetD("step");
 
       LOG(FIT) << "Read " << partype << " : " << parname << " = " << parnom
                << " : " << parlow << " < p < " << parhigh << " : " << parstate
                << std::endl;
     } else {
       LOG(FIT) << "Read " << partype << " : " << parname << " = " << parnom
                << " : " << parstate << std::endl;
     }
 
     // Run Parameter Conversion if needed
     if (parstate.find("ABS") != std::string::npos) {
       parnom = FitBase::RWAbsToSigma(partype, parname, parnom);
       parlow = FitBase::RWAbsToSigma(partype, parname, parlow);
       parhigh = FitBase::RWAbsToSigma(partype, parname, parhigh);
       parstep = FitBase::RWAbsToSigma(partype, parname, parstep);
     } else if (parstate.find("FRAC") != std::string::npos) {
       parnom = FitBase::RWFracToSigma(partype, parname, parnom);
       parlow = FitBase::RWFracToSigma(partype, parname, parlow);
       parhigh = FitBase::RWFracToSigma(partype, parname, parhigh);
       parstep = FitBase::RWFracToSigma(partype, parname, parstep);
     }
 
     // Push into vectors
     fParams.push_back(parname);
 
     fTypeVals[parname] = FitBase::ConvDialType(partype);
     ;
     fStartVals[parname] = parnom;
     fCurVals[parname] = parnom;
 
     fErrorVals[parname] = 0.0;
 
     fStateVals[parname] = parstate;
     bool fixstate = parstate.find("FIX") != std::string::npos;
     fFixVals[parname] = fixstate;
     fStartFixVals[parname] = fFixVals[parname];
 
     fMinVals[parname] = parlow;
     fMaxVals[parname] = parhigh;
     fStepVals[parname] = parstep;
   }
 
   // Setup Samples ----------------------------------------------
   std::vector<nuiskey> samplekeys = Config::QueryKeys("sample");
   if (!samplekeys.empty()) {
     LOG(FIT) << "Number of samples : " << samplekeys.size() << std::endl;
   }
 
   for (size_t i = 0; i < samplekeys.size(); i++) {
     nuiskey key = samplekeys.at(i);
 
     // Get Sample Options
     std::string samplename = key.GetS("name");
     std::string samplefile = key.GetS("input");
 
     std::string sampletype = key.Has("type") ? key.GetS("type") : "DEFAULT";
 
     double samplenorm = key.Has("norm") ? key.GetD("norm") : 1.0;
 
     // Print out
     LOG(FIT) << "Read sample info " << i << " : " << samplename << std::endl
              << "\t\t input -> " << samplefile << std::endl
              << "\t\t state -> " << sampletype << std::endl
              << "\t\t norm  -> " << samplenorm << std::endl;
 
     // If FREE add to parameters otherwise continue
     if (sampletype.find("FREE") == std::string::npos) {
       continue;
     }
 
     // Form norm dial from samplename + sampletype + "_norm";
     std::string normname = samplename + "_norm";
 
     // Check normname not already present
     if (fTypeVals.find(normname) != fTypeVals.end()) {
       continue;
     }
 
     // Add new norm dial to list if its passed above checks
     fParams.push_back(normname);
 
     fTypeVals[normname] = kNORM;
     fStateVals[normname] = sampletype;
     fStartVals[normname] = samplenorm;
     fCurVals[normname] = samplenorm;
 
     fErrorVals[normname] = 0.0;
 
     fMinVals[normname] = 0.1;
     fMaxVals[normname] = 10.0;
     fStepVals[normname] = 0.5;
 
     bool state = sampletype.find("FREE") == std::string::npos;
     fFixVals[normname] = state;
     fStartFixVals[normname] = state;
   }
 
   // Setup Fake Parameters -----------------------------
   std::vector<nuiskey> fakekeys = Config::QueryKeys("fakeparameter");
   if (!fakekeys.empty()) {
     LOG(FIT) << "Number of fake parameters : " << fakekeys.size() << std::endl;
   }
 
   for (size_t i = 0; i < fakekeys.size(); i++) {
     nuiskey key = fakekeys.at(i);
 
     // Check for type,name,nom
     if (!key.Has("name")) {
       ERR(FTL) << "No name given for fakeparameter " << i << std::endl;
       throw;
     } else if (!key.Has("nom")) {
       ERR(FTL) << "No nominal given for fakeparameter " << i << std::endl;
       throw;
     }
 
     // Get Inputs
     std::string parname = key.GetS("name");
     double parnom = key.GetD("nom");
 
     // Push into vectors
     fFakeVals[parname] = parnom;
   }
 }
 
 /*
   Setup Functions
 */
 //*************************************
 void MinimizerRoutines::SetupRWEngine() {
   //*************************************
 
   for (UInt_t i = 0; i < fParams.size(); i++) {
     std::string name = fParams[i];
     FitBase::GetRW()->IncludeDial(name, fTypeVals.at(name));
   }
   UpdateRWEngine(fStartVals);
 
   return;
 }
 
 //*************************************
 void MinimizerRoutines::SetupFCN() {
   //*************************************
 
   LOG(FIT) << "Making the jointFCN" << std::endl;
   if (fSampleFCN) delete fSampleFCN;
   // fSampleFCN = new JointFCN(fCardFile, fOutputRootFile);
   fSampleFCN = new JointFCN(fOutputRootFile);
 
   SetFakeData();
 
   fMinimizerFCN = new MinimizerFCN(fSampleFCN);
   fCallFunctor = new ROOT::Math::Functor(*fMinimizerFCN, fParams.size());
 
   fSampleFCN->CreateIterationTree("fit_iterations", FitBase::GetRW());
 
   return;
 }
 
 //******************************************
 void MinimizerRoutines::SetupFitter(std::string routine) {
   //******************************************
 
   // Make the fitter
   std::string fitclass = "";
   std::string fittype = "";
 
   bool UseMCMC = false;
   // Get correct types
   if (!routine.compare("Migrad")) {
     fitclass = "Minuit2";
     fittype = "Migrad";
   } else if (!routine.compare("Simplex")) {
     fitclass = "Minuit2";
     fittype = "Simplex";
   } else if (!routine.compare("Combined")) {
     fitclass = "Minuit2";
     fittype = "Combined";
   } else if (!routine.compare("Brute")) {
     fitclass = "Minuit2";
     fittype = "Scan";
   } else if (!routine.compare("Fumili")) {
     fitclass = "Minuit2";
     fittype = "Fumili";
   } else if (!routine.compare("ConjugateFR")) {
     fitclass = "GSLMultiMin";
     fittype = "ConjugateFR";
   } else if (!routine.compare("ConjugatePR")) {
     fitclass = "GSLMultiMin";
     fittype = "ConjugatePR";
   } else if (!routine.compare("BFGS")) {
     fitclass = "GSLMultiMin";
     fittype = "BFGS";
   } else if (!routine.compare("BFGS2")) {
     fitclass = "GSLMultiMin";
     fittype = "BFGS2";
   } else if (!routine.compare("SteepDesc")) {
     fitclass = "GSLMultiMin";
     fittype = "SteepestDescent";
     //  } else if (!routine.compare("GSLMulti"))    { fitclass = "GSLMultiFit";
     //  fittype = "";         // Doesn't work out of the box
   } else if (!routine.compare("GSLSimAn")) {
     fitclass = "GSLSimAn";
     fittype = "";
   } else if (!routine.compare("MCMC")) {
     UseMCMC = true;
   }
 
   // make minimizer
   if (fMinimizer) delete fMinimizer;
 
   if (UseMCMC) {
     fMinimizer = new Simple_MH_Sampler();
   } else {
     fMinimizer = ROOT::Math::Factory::CreateMinimizer(fitclass, fittype);
   }
 
   fMinimizer->SetMaxFunctionCalls(
       FitPar::Config().GetParI("minimizer.maxcalls"));
 
   if (!routine.compare("Brute")) {
     fMinimizer->SetMaxFunctionCalls(fParams.size() * fParams.size() * 4);
     fMinimizer->SetMaxIterations(fParams.size() * fParams.size() * 4);
   }
 
   fMinimizer->SetMaxIterations(
       FitPar::Config().GetParI("minimizer.maxiterations"));
   fMinimizer->SetTolerance(FitPar::Config().GetParD("minimizer.tolerance"));
   fMinimizer->SetStrategy(FitPar::Config().GetParI("minimizer.strategy"));
   fMinimizer->SetFunction(*fCallFunctor);
 
   int ipar = 0;
   // Add Fit Parameters
   for (UInt_t i = 0; i < fParams.size(); i++) {
     std::string syst = fParams.at(i);
 
     bool fixed = true;
     double vstart, vstep, vlow, vhigh;
     vstart = vstep = vlow = vhigh = 0.0;
 
     if (fCurVals.find(syst) != fCurVals.end()) vstart = fCurVals.at(syst);
     if (fMinVals.find(syst) != fMinVals.end()) vlow = fMinVals.at(syst);
     if (fMaxVals.find(syst) != fMaxVals.end()) vhigh = fMaxVals.at(syst);
     if (fStepVals.find(syst) != fStepVals.end()) vstep = fStepVals.at(syst);
     if (fFixVals.find(syst) != fFixVals.end()) fixed = fFixVals.at(syst);
 
     // fix for errors
     if (vhigh == vlow) vhigh += 1.0;
 
     fMinimizer->SetVariable(ipar, syst, vstart, vstep);
     fMinimizer->SetVariableLimits(ipar, vlow, vhigh);
 
     if (fixed) {
       fMinimizer->FixVariable(ipar);
       LOG(FIT) << "Fixed Param: " << syst << std::endl;
 
     } else {
       LOG(FIT) << "Free  Param: " << syst << " Start:" << vstart
                << " Range:" << vlow << " to " << vhigh << " Step:" << vstep
                << std::endl;
     }
 
     ipar++;
   }
 
   LOG(FIT) << "Setup Minimizer: " << fMinimizer->NDim() << "(NDim) "
            << fMinimizer->NFree() << "(NFree)" << std::endl;
 
   return;
 }
 
 //*************************************
 // Set fake data from user input
 void MinimizerRoutines::SetFakeData() {
   //*************************************
 
   // If the fake data input field (-d) isn't provided, return to caller
   if (fFakeDataInput.empty()) return;
 
   // If user specifies -d MC we set the data to the MC
   // User can also specify fake data parameters to reweight by doing
   // "fake_parameter" in input card file
   // "fake_parameter" gets read in ReadCard function (reads to fFakeVals)
   if (fFakeDataInput.compare("MC") == 0) {
     LOG(FIT) << "Setting fake data from MC starting prediction." << std::endl;
     // fFakeVals get read in in ReadCard
     UpdateRWEngine(fFakeVals);
 
     // Reconfigure the reweight engine
     FitBase::GetRW()->Reconfigure();
     // Reconfigure all the samples to the new reweight
     fSampleFCN->ReconfigureAllEvents();
     // Feed on and set the fake-data in each measurement class
     fSampleFCN->SetFakeData("MC");
 
     // Changed the reweight engine values back to the current values
     // So we start the fit at a different value than what we set the fake-data
     // to
     UpdateRWEngine(fCurVals);
 
     LOG(FIT) << "Set all data to fake MC predictions." << std::endl;
   } else {
     fSampleFCN->SetFakeData(fFakeDataInput);
   }
 
   return;
 }
 
 /*
   Fitting Functions
 */
 //*************************************
 void MinimizerRoutines::UpdateRWEngine(
     std::map<std::string, double>& updateVals) {
   //*************************************
 
   for (UInt_t i = 0; i < fParams.size(); i++) {
     std::string name = fParams[i];
 
     if (updateVals.find(name) == updateVals.end()) continue;
     FitBase::GetRW()->SetDialValue(name, updateVals.at(name));
   }
 
   FitBase::GetRW()->Reconfigure();
   return;
 }
 
 //*************************************
 void MinimizerRoutines::Run() {
   //*************************************
 
   LOG(FIT) << "Running MinimizerRoutines : " << fStrategy << std::endl;
   if (FitPar::Config().GetParB("save_nominal")) {
     SaveNominal();
   }
 
   // Parse given routines
   fRoutines = GeneralUtils::ParseToStr(fStrategy, ",");
   if (fRoutines.empty()) {
     ERR(FTL) << "Trying to run MinimizerRoutines with no routines given!"
              << std::endl;
     throw;
   }
 
   for (UInt_t i = 0; i < fRoutines.size(); i++) {
     std::string routine = fRoutines.at(i);
     int fitstate = kFitUnfinished;
     LOG(FIT) << "Running Routine: " << routine << std::endl;
 
     // Try Routines
     if (routine.find("LowStat") != std::string::npos)
       LowStatRoutine(routine);
     else if (routine == "FixAtLim")
       FixAtLimit();
     else if (routine == "FixAtLimBreak")
       fitstate = FixAtLimit();
     else if (routine.find("ErrorBands") != std::string::npos)
       GenerateErrorBands();
     else if (routine.find("DataToys") != std::string::npos)
       ThrowDataToys();
     else if (!routine.compare("Chi2Scan1D"))
       Create1DScans();
     else if (!routine.compare("Chi2Scan2D"))
       Chi2Scan2D();
     else
       fitstate = RunFitRoutine(routine);
 
     // If ending early break here
     if (fitstate == kFitFinished || fitstate == kNoChange) {
       LOG(FIT) << "Ending fit routines loop." << std::endl;
       break;
     }
   }
 
   return;
 }
 
 //*************************************
 int MinimizerRoutines::RunFitRoutine(std::string routine) {
   //*************************************
   int endfits = kFitUnfinished;
 
   // set fitter at the current start values
   fOutputRootFile->cd();
   SetupFitter(routine);
 
   // choose what to do with the minimizer depending on routine.
   if (!routine.compare("Migrad") or !routine.compare("Simplex") or
       !routine.compare("Combined") or !routine.compare("Brute") or
       !routine.compare("Fumili") or !routine.compare("ConjugateFR") or
       !routine.compare("ConjugatePR") or !routine.compare("BFGS") or
       !routine.compare("BFGS2") or !routine.compare("SteepDesc") or
       //    !routine.compare("GSLMulti") or
       !routine.compare("GSLSimAn") or !routine.compare("MCMC")) {
     if (fMinimizer->NFree() > 0) {
       LOG(FIT) << fMinimizer->Minimize() << std::endl;
       GetMinimizerState();
     }
   }
 
   // other otptions
   else if (!routine.compare("Contour")) {
     CreateContours();
   }
 
   return endfits;
 }
 
 //*************************************
 void MinimizerRoutines::PrintState() {
   //*************************************
   LOG(FIT) << "------------" << std::endl;
 
   // Count max size
   int maxcount = 0;
   for (UInt_t i = 0; i < fParams.size(); i++) {
     maxcount = max(int(fParams[i].size()), maxcount);
   }
 
   // Header
   LOG(FIT) << " #    " << left << setw(maxcount) << "Parameter "
            << " = " << setw(10) << "Value"
            << " +- " << setw(10) << "Error"
            << " " << setw(8) << "(Units)"
            << " " << setw(10) << "Conv. Val"
            << " +- " << setw(10) << "Conv. Err"
            << " " << setw(8) << "(Units)" << std::endl;
 
   // Parameters
   for (UInt_t i = 0; i < fParams.size(); i++) {
     std::string syst = fParams.at(i);
 
     std::string typestr = FitBase::ConvDialType(fTypeVals[syst]);
     std::string curunits = "(sig.)";
     double curval = fCurVals[syst];
     double curerr = fErrorVals[syst];
 
     if (fStateVals[syst].find("ABS") != std::string::npos) {
       curval = FitBase::RWSigmaToAbs(typestr, syst, curval);
       curerr = (FitBase::RWSigmaToAbs(typestr, syst, curerr) -
                 FitBase::RWSigmaToAbs(typestr, syst, 0.0));
       curunits = "(Abs.)";
     } else if (fStateVals[syst].find("FRAC") != std::string::npos) {
       curval = FitBase::RWSigmaToFrac(typestr, syst, curval);
       curerr = (FitBase::RWSigmaToFrac(typestr, syst, curerr) -
                 FitBase::RWSigmaToFrac(typestr, syst, 0.0));
       curunits = "(Frac)";
     }
 
     std::string convunits = "(" + FitBase::GetRWUnits(typestr, syst) + ")";
     double convval = FitBase::RWSigmaToAbs(typestr, syst, curval);
     double converr = (FitBase::RWSigmaToAbs(typestr, syst, curerr) -
                       FitBase::RWSigmaToAbs(typestr, syst, 0.0));
 
     std::ostringstream curparstring;
 
     curparstring << " " << setw(3) << left << i << ". " << setw(maxcount)
                  << syst << " = " << setw(10) << curval << " +- " << setw(10)
                  << curerr << " " << setw(8) << curunits << " " << setw(10)
                  << convval << " +- " << setw(10) << converr << " " << setw(8)
                  << convunits;
 
     LOG(FIT) << curparstring.str() << std::endl;
   }
 
   LOG(FIT) << "------------" << std::endl;
   double like = fSampleFCN->GetLikelihood();
   LOG(FIT) << std::left << std::setw(46) << "Likelihood for JointFCN: " << like
            << std::endl;
   LOG(FIT) << "------------" << std::endl;
 }
 
 //*************************************
 void MinimizerRoutines::GetMinimizerState() {
   //*************************************
 
   LOG(FIT) << "Minimizer State: " << std::endl;
   // Get X and Err
   const double* values = fMinimizer->X();
   const double* errors = fMinimizer->Errors();
   //  int ipar = 0;
 
   for (UInt_t i = 0; i < fParams.size(); i++) {
     std::string syst = fParams.at(i);
 
     fCurVals[syst] = values[i];
     fErrorVals[syst] = errors[i];
   }
 
   PrintState();
 
   // Covar
   SetupCovariance();
   if (fMinimizer->CovMatrixStatus() > 0) {
     // Fill Full Covar
     std::cout << "Filling covariance" << std::endl;
     for (int i = 0; i < fCovar->GetNbinsX(); i++) {
       for (int j = 0; j < fCovar->GetNbinsY(); j++) {
         fCovar->SetBinContent(i + 1, j + 1, fMinimizer->CovMatrix(i, j));
       }
     }
 
     int freex = 0;
     int freey = 0;
     for (int i = 0; i < fCovar->GetNbinsX(); i++) {
       if (fMinimizer->IsFixedVariable(i)) continue;
       freey = 0;
 
       for (int j = 0; j < fCovar->GetNbinsY(); j++) {
         if (fMinimizer->IsFixedVariable(j)) continue;
 
         fCovFree->SetBinContent(freex + 1, freey + 1,
                                 fMinimizer->CovMatrix(i, j));
         freey++;
       }
       freex++;
     }
 
     fCorrel = PlotUtils::GetCorrelationPlot(fCovar, "correlation");
     fDecomp = PlotUtils::GetDecompPlot(fCovar, "decomposition");
     if (fMinimizer->NFree() > 0) {
       fCorFree = PlotUtils::GetCorrelationPlot(fCovFree, "correlation_free");
       fDecFree = PlotUtils::GetDecompPlot(fCovFree, "decomposition_free");
     }
   }
 
   std::cout << "Got STATE" << std::endl;
 
   return;
 };
 
 //*************************************
 void MinimizerRoutines::LowStatRoutine(std::string routine) {
   //*************************************
 
   LOG(FIT) << "Running Low Statistics Routine: " << routine << std::endl;
   int lowstatsevents = FitPar::Config().GetParI("minimizer.lowstatevents");
   int maxevents = FitPar::Config().GetParI("input.maxevents");
   int verbosity = FitPar::Config().GetParI("VERBOSITY");
 
   std::string trueroutine = routine;
   std::string substring = "LowStat";
   trueroutine.erase(trueroutine.find(substring), substring.length());
 
   // Set MAX EVENTS=1000
-  FitPar::Config().SetParI("input.maxevents", lowstatsevents);
-  FitPar::Config().SetParI("VERBOSITY", 3);
+  Config::SetPar("input.maxevents", lowstatsevents);
+  Config::SetPar("VERBOSITY", 3);
   SetupFCN();
 
   RunFitRoutine(trueroutine);
 
-  FitPar::Config().SetParI("input.maxevents", maxevents);
+  Config::SetPar("input.maxevents", maxevents);
   SetupFCN();
 
-  FitPar::Config().SetParI("VERBOSITY", verbosity);
+  Config::SetPar("VERBOSITY", verbosity);
   return;
 }
 
 //*************************************
 void MinimizerRoutines::Create1DScans() {
   //*************************************
 
   // 1D Scan Routine
   // Steps through all free parameters about nominal using the step size
   // Creates a graph for each free parameter
 
   // At the current point create a 1D Scan for all parametes (Uncorrelated)
   for (UInt_t i = 0; i < fParams.size(); i++) {
     if (fFixVals[fParams[i]]) continue;
 
     LOG(FIT) << "Running 1D Scan for " << fParams[i] << std::endl;
     fSampleFCN->CreateIterationTree(fParams[i] + "_scan1D_iterations",
                                     FitBase::GetRW());
 
     double scanmiddlepoint = fCurVals[fParams[i]];
 
     // Determine N points needed
     double limlow = fMinVals[fParams[i]];
     double limhigh = fMaxVals[fParams[i]];
     double step = fStepVals[fParams[i]];
 
     int npoints = int(fabs(limhigh - limlow) / (step + 0.));
 
     TH1D* contour =
         new TH1D(("Chi2Scan1D_" + fParams[i]).c_str(),
                  ("Chi2Scan1D_" + fParams[i] + ";" + fParams[i]).c_str(),
                  npoints, limlow, limhigh);
 
     // Fill bins
     for (int x = 0; x < contour->GetNbinsX(); x++) {
       // Set X Val
       fCurVals[fParams[i]] = contour->GetXaxis()->GetBinCenter(x + 1);
 
       // Run Eval
       double* vals = FitUtils::GetArrayFromMap(fParams, fCurVals);
       double chi2 = fSampleFCN->DoEval(vals);
       delete vals;
 
       // Fill Contour
       contour->SetBinContent(x + 1, chi2);
     }
 
     // Save contour
     contour->Write();
 
     // Reset Parameter
     fCurVals[fParams[i]] = scanmiddlepoint;
 
     // Save TTree
     fSampleFCN->WriteIterationTree();
   }
 
   return;
 }
 
 //*************************************
 void MinimizerRoutines::Chi2Scan2D() {
   //*************************************
 
   // Chi2 Scan 2D
   // Creates a 2D chi2 scan by stepping through all free parameters
   // Works for all pairwise combos of free parameters
 
   // Scan I
   for (UInt_t i = 0; i < fParams.size(); i++) {
     if (fFixVals[fParams[i]]) continue;
 
     // Scan J
     for (UInt_t j = 0; j < i; j++) {
       if (fFixVals[fParams[j]]) continue;
 
       fSampleFCN->CreateIterationTree(
           fParams[i] + "_" + fParams[j] + "_" + "scan2D_iterations",
           FitBase::GetRW());
 
       double scanmid_i = fCurVals[fParams[i]];
       double scanmid_j = fCurVals[fParams[j]];
 
       double limlow_i = fMinVals[fParams[i]];
       double limhigh_i = fMaxVals[fParams[i]];
       double step_i = fStepVals[fParams[i]];
 
       double limlow_j = fMinVals[fParams[j]];
       double limhigh_j = fMaxVals[fParams[j]];
       double step_j = fStepVals[fParams[j]];
 
       int npoints_i = int(fabs(limhigh_i - limlow_i) / (step_i + 0.)) + 1;
       int npoints_j = int(fabs(limhigh_j - limlow_j) / (step_j + 0.)) + 1;
 
       TH2D* contour = new TH2D(
           ("Chi2Scan2D_" + fParams[i] + "_" + fParams[j]).c_str(),
           ("Chi2Scan2D_" + fParams[i] + "_" + fParams[j] + ";" + fParams[i] +
            ";" + fParams[j])
               .c_str(),
           npoints_i, limlow_i, limhigh_i, npoints_j, limlow_j, limhigh_j);
 
       // Begin Scan
       LOG(FIT) << "Running scan for " << fParams[i] << " " << fParams[j]
                << std::endl;
 
       // Fill bins
       for (int x = 0; x < contour->GetNbinsX(); x++) {
         // Set X Val
         fCurVals[fParams[i]] = contour->GetXaxis()->GetBinCenter(x + 1);
 
         // Loop Y
         for (int y = 0; y < contour->GetNbinsY(); y++) {
           // Set Y Val
           fCurVals[fParams[j]] = contour->GetYaxis()->GetBinCenter(y + 1);
 
           // Run Eval
           double* vals = FitUtils::GetArrayFromMap(fParams, fCurVals);
           double chi2 = fSampleFCN->DoEval(vals);
           delete vals;
 
           // Fill Contour
           contour->SetBinContent(x + 1, y + 1, chi2);
 
           fCurVals[fParams[j]] = scanmid_j;
         }
 
         fCurVals[fParams[i]] = scanmid_i;
         fCurVals[fParams[j]] = scanmid_j;
       }
 
       // Save contour
       contour->Write();
 
       // Save Iterations
       fSampleFCN->WriteIterationTree();
     }
   }
 
   return;
 }
 
 //*************************************
 void MinimizerRoutines::CreateContours() {
   //*************************************
 
   // Use MINUIT for this if possible
   ERR(FTL) << " Contours not yet implemented as it is really slow!"
            << std::endl;
   throw;
 
   return;
 }
 
 //*************************************
 int MinimizerRoutines::FixAtLimit() {
   //*************************************
 
   bool fixedparam = false;
   for (UInt_t i = 0; i < fParams.size(); i++) {
     std::string syst = fParams.at(i);
     if (fFixVals[syst]) continue;
 
     double curVal = fCurVals.at(syst);
     double minVal = fMinVals.at(syst);
     double maxVal = fMinVals.at(syst);
 
     if (fabs(curVal - minVal) < 0.0001) {
       fCurVals[syst] = minVal;
       fFixVals[syst] = true;
       fixedparam = true;
     }
 
     if (fabs(maxVal - curVal) < 0.0001) {
       fCurVals[syst] = maxVal;
       fFixVals[syst] = true;
       fixedparam = true;
     }
   }
 
   if (!fixedparam) {
     LOG(FIT) << "No dials needed fixing!" << std::endl;
     return kNoChange;
   } else
     return kStateChange;
 }
 
 /*
   Write Functions
 */
 //*************************************
 void MinimizerRoutines::SaveResults() {
   //*************************************
 
   fOutputRootFile->cd();
 
   if (fMinimizer) {
     SetupCovariance();
     SaveMinimizerState();
   }
 
   SaveCurrentState();
 }
 
 //*************************************
 void MinimizerRoutines::SaveMinimizerState() {
   //*************************************
 
   std::cout << "Saving Minimizer State" << std::endl;
   if (!fMinimizer) {
     ERR(FTL) << "Can't save minimizer state without min object" << std::endl;
     throw;
   }
 
   // Save main fit tree
   fSampleFCN->WriteIterationTree();
 
   // Get Vals and Errors
   GetMinimizerState();
 
   // Save tree with fit status
   std::vector<std::string> nameVect;
   std::vector<double> valVect;
   std::vector<double> errVect;
   std::vector<double> minVect;
   std::vector<double> maxVect;
   std::vector<double> startVect;
   std::vector<int> endfixVect;
   std::vector<int> startfixVect;
 
   //  int NFREEPARS = fMinimizer->NFree();
   int NPARS = fMinimizer->NDim();
 
   int ipar = 0;
   // Dial Vals
   for (UInt_t i = 0; i < fParams.size(); i++) {
     std::string name = fParams.at(i);
     nameVect.push_back(name);
 
     valVect.push_back(fCurVals.at(name));
 
     errVect.push_back(fErrorVals.at(name));
 
     minVect.push_back(fMinVals.at(name));
 
     maxVect.push_back(fMaxVals.at(name));
 
     startVect.push_back(fStartVals.at(name));
 
     endfixVect.push_back(fFixVals.at(name));
 
     startfixVect.push_back(fStartFixVals.at(name));
 
     ipar++;
   }
 
   int NFREE = fMinimizer->NFree();
   int NDIM = fMinimizer->NDim();
 
   double CHI2 = fSampleFCN->GetLikelihood();
   int NBINS = fSampleFCN->GetNDOF();
   int NDOF = NBINS - NFREE;
 
   // Write fit results
   TTree* fit_tree = new TTree("fit_result", "fit_result");
   fit_tree->Branch("parameter_names", &nameVect);
   fit_tree->Branch("parameter_values", &valVect);
   fit_tree->Branch("parameter_errors", &errVect);
   fit_tree->Branch("parameter_min", &minVect);
   fit_tree->Branch("parameter_max", &maxVect);
   fit_tree->Branch("parameter_start", &startVect);
   fit_tree->Branch("parameter_fix", &endfixVect);
   fit_tree->Branch("parameter_startfix", &startfixVect);
   fit_tree->Branch("CHI2", &CHI2, "CHI2/D");
   fit_tree->Branch("NDOF", &NDOF, "NDOF/I");
   fit_tree->Branch("NBINS", &NBINS, "NBINS/I");
   fit_tree->Branch("NDIM", &NDIM, "NDIM/I");
   fit_tree->Branch("NFREE", &NFREE, "NFREE/I");
   fit_tree->Fill();
   fit_tree->Write();
 
   // Make dial variables
   TH1D dialvar = TH1D("fit_dials", "fit_dials", NPARS, 0, NPARS);
   TH1D startvar = TH1D("start_dials", "start_dials", NPARS, 0, NPARS);
   TH1D minvar = TH1D("min_dials", "min_dials", NPARS, 0, NPARS);
   TH1D maxvar = TH1D("max_dials", "max_dials", NPARS, 0, NPARS);
 
   TH1D dialvarfree = TH1D("fit_dials_free", "fit_dials_free", NFREE, 0, NFREE);
   TH1D startvarfree =
       TH1D("start_dials_free", "start_dials_free", NFREE, 0, NFREE);
   TH1D minvarfree = TH1D("min_dials_free", "min_dials_free", NFREE, 0, NFREE);
   TH1D maxvarfree = TH1D("max_dials_free", "max_dials_free", NFREE, 0, NFREE);
 
   int freecount = 0;
 
   for (UInt_t i = 0; i < nameVect.size(); i++) {
     std::string name = nameVect.at(i);
 
     dialvar.SetBinContent(i + 1, valVect.at(i));
     dialvar.SetBinError(i + 1, errVect.at(i));
     dialvar.GetXaxis()->SetBinLabel(i + 1, name.c_str());
 
     startvar.SetBinContent(i + 1, startVect.at(i));
     startvar.GetXaxis()->SetBinLabel(i + 1, name.c_str());
 
     minvar.SetBinContent(i + 1, minVect.at(i));
     minvar.GetXaxis()->SetBinLabel(i + 1, name.c_str());
 
     maxvar.SetBinContent(i + 1, maxVect.at(i));
     maxvar.GetXaxis()->SetBinLabel(i + 1, name.c_str());
 
     if (NFREE > 0) {
       if (!startfixVect.at(i)) {
         freecount++;
 
         dialvarfree.SetBinContent(freecount, valVect.at(i));
         dialvarfree.SetBinError(freecount, errVect.at(i));
         dialvarfree.GetXaxis()->SetBinLabel(freecount, name.c_str());
 
         startvarfree.SetBinContent(freecount, startVect.at(i));
         startvarfree.GetXaxis()->SetBinLabel(freecount, name.c_str());
 
         minvarfree.SetBinContent(freecount, minVect.at(i));
         minvarfree.GetXaxis()->SetBinLabel(freecount, name.c_str());
 
         maxvarfree.SetBinContent(freecount, maxVect.at(i));
         maxvarfree.GetXaxis()->SetBinLabel(freecount, name.c_str());
       }
     }
   }
 
   // Save Dial Plots
   dialvar.Write();
   startvar.Write();
   minvar.Write();
   maxvar.Write();
 
   if (NFREE > 0) {
     dialvarfree.Write();
     startvarfree.Write();
     minvarfree.Write();
     maxvarfree.Write();
   }
 
   // Save fit_status plot
   TH1D statusplot = TH1D("fit_status", "fit_status", 8, 0, 8);
   std::string fit_labels[8] = {"status",    "cov_status", "maxiter",
                                "maxfunc",   "iter",       "func",
                                "precision", "tolerance"};
   double fit_vals[8];
   fit_vals[0] = fMinimizer->Status() + 0.;
   fit_vals[1] = fMinimizer->CovMatrixStatus() + 0.;
   fit_vals[2] = fMinimizer->MaxIterations() + 0.;
   fit_vals[3] = fMinimizer->MaxFunctionCalls() + 0.;
   fit_vals[4] = fMinimizer->NIterations() + 0.;
   fit_vals[5] = fMinimizer->NCalls() + 0.;
   fit_vals[6] = fMinimizer->Precision() + 0.;
   fit_vals[7] = fMinimizer->Tolerance() + 0.;
 
   for (int i = 0; i < 8; i++) {
     statusplot.SetBinContent(i + 1, fit_vals[i]);
     statusplot.GetXaxis()->SetBinLabel(i + 1, fit_labels[i].c_str());
   }
 
   statusplot.Write();
 
   // Save Covars
   if (fCovar) fCovar->Write();
   if (fCovFree) fCovFree->Write();
   if (fCorrel) fCorrel->Write();
   if (fCorFree) fCorFree->Write();
   if (fDecomp) fDecomp->Write();
   if (fDecFree) fDecFree->Write();
 
   return;
 }
 
 //*************************************
 void MinimizerRoutines::SaveCurrentState(std::string subdir) {
   //*************************************
 
   LOG(FIT) << "Saving current full FCN predictions" << std::endl;
 
   // Setup DIRS
   TDirectory* curdir = gDirectory;
   if (!subdir.empty()) {
     TDirectory* newdir = (TDirectory*)gDirectory->mkdir(subdir.c_str());
     newdir->cd();
   }
 
   FitBase::GetRW()->Reconfigure();
   fSampleFCN->ReconfigureAllEvents();
   fSampleFCN->Write();
 
   // Change back to current DIR
   curdir->cd();
 
   return;
 }
 
 //*************************************
 void MinimizerRoutines::SaveNominal() {
   //*************************************
 
   fOutputRootFile->cd();
 
   LOG(FIT) << "Saving Nominal Predictions (be cautious with this)" << std::endl;
   FitBase::GetRW()->Reconfigure();
   SaveCurrentState("nominal");
 };
 
 //*************************************
 void MinimizerRoutines::SavePrefit() {
   //*************************************
 
   fOutputRootFile->cd();
 
   LOG(FIT) << "Saving Prefit Predictions" << std::endl;
   UpdateRWEngine(fStartVals);
   SaveCurrentState("prefit");
   UpdateRWEngine(fCurVals);
 };
 
 /*
   MISC Functions
 */
 //*************************************
 int MinimizerRoutines::GetStatus() {
   //*************************************
 
   return 0;
 }
 
 //*************************************
 void MinimizerRoutines::SetupCovariance() {
   //*************************************
 
   // Remove covares if they exist
   if (fCovar) delete fCovar;
   if (fCovFree) delete fCovFree;
   if (fCorrel) delete fCorrel;
   if (fCorFree) delete fCorFree;
   if (fDecomp) delete fDecomp;
   if (fDecFree) delete fDecFree;
 
   LOG(FIT) << "Building covariance matrix.." << std::endl;
 
   int NFREE = 0;
   int NDIM = 0;
 
   // Get NFREE from min or from vals (for cases when doing throws)
   if (fMinimizer) {
     std::cout << "NFREE FROM MINIMIZER" << std::endl;
     NFREE = fMinimizer->NFree();
     NDIM = fMinimizer->NDim();
   } else {
     NDIM = fParams.size();
     for (UInt_t i = 0; i < fParams.size(); i++) {
       std::cout << "Getting Param " << fParams[i] << std::endl;
 
       if (!fFixVals[fParams[i]]) NFREE++;
     }
   }
 
   if (NDIM == 0) return;
   LOG(FIT) << "NFREE == " << NFREE << std::endl;
   fCovar = new TH2D("covariance", "covariance", NDIM, 0, NDIM, NDIM, 0, NDIM);
   if (NFREE > 0) {
     fCovFree = new TH2D("covariance_free", "covariance_free", NFREE, 0, NFREE,
                         NFREE, 0, NFREE);
   } else {
     fCovFree = NULL;
   }
 
   // Set Bin Labels
   int countall = 0;
   int countfree = 0;
   for (UInt_t i = 0; i < fParams.size(); i++) {
     std::cout << "Getting Param " << i << std::endl;
     std::cout << "ParamI = " << fParams[i] << std::endl;
 
     fCovar->GetXaxis()->SetBinLabel(countall + 1, fParams[i].c_str());
     fCovar->GetYaxis()->SetBinLabel(countall + 1, fParams[i].c_str());
     countall++;
 
     if (!fFixVals[fParams[i]] and NFREE > 0) {
       fCovFree->GetXaxis()->SetBinLabel(countfree + 1, fParams[i].c_str());
       fCovFree->GetYaxis()->SetBinLabel(countfree + 1, fParams[i].c_str());
       countfree++;
     }
   }
 
   std::cout << "Filling Matrices" << std::endl;
 
   fCorrel = PlotUtils::GetCorrelationPlot(fCovar, "correlation");
   fDecomp = PlotUtils::GetDecompPlot(fCovar, "decomposition");
 
   if (NFREE > 0) {
     fCorFree = PlotUtils::GetCorrelationPlot(fCovFree, "correlation_free");
     fDecFree = PlotUtils::GetDecompPlot(fCovFree, "decomposition_free");
   } else {
     fCorFree = NULL;
     fDecFree = NULL;
   }
 
   std::cout << " Set the covariance" << std::endl;
   return;
 };
 
 //*************************************
 void MinimizerRoutines::ThrowCovariance(bool uniformly) {
   //*************************************
   std::vector<double> rands;
 
   if (!fDecFree) {
     ERR(WRN) << "Trying to throw 0 free parameters" << std::endl;
     return;
   }
 
   // Generate Random Gaussians
   for (Int_t i = 0; i < fDecFree->GetNbinsX(); i++) {
     rands.push_back(gRandom->Gaus(0.0, 1.0));
   }
 
   // Reset Thrown Values
   for (UInt_t i = 0; i < fParams.size(); i++) {
     fThrownVals[fParams[i]] = fCurVals[fParams[i]];
   }
 
   // Loop and get decomp
   for (Int_t i = 0; i < fDecFree->GetNbinsX(); i++) {
     std::string parname = std::string(fDecFree->GetXaxis()->GetBinLabel(i + 1));
     double mod = 0.0;
 
     if (!uniformly) {
       for (Int_t j = 0; j < fDecFree->GetNbinsY(); j++) {
         mod += rands[j] * fDecFree->GetBinContent(j + 1, i + 1);
       }
     }
 
     if (fCurVals.find(parname) != fCurVals.end()) {
       if (uniformly)
         fThrownVals[parname] =
             gRandom->Uniform(fMinVals[parname], fMaxVals[parname]);
       else {
         fThrownVals[parname] = fCurVals[parname] + mod;
       }
     }
   }
 
   // Check Limits
   for (UInt_t i = 0; i < fParams.size(); i++) {
     std::string syst = fParams[i];
     if (fFixVals[syst]) continue;
     if (fThrownVals[syst] < fMinVals[syst]) fThrownVals[syst] = fMinVals[syst];
     if (fThrownVals[syst] > fMaxVals[syst]) fThrownVals[syst] = fMaxVals[syst];
   }
 
   return;
 };
 
 //*************************************
 void MinimizerRoutines::GenerateErrorBands() {
   //*************************************
 
   TDirectory* errorDIR = (TDirectory*)fOutputRootFile->mkdir("error_bands");
   errorDIR->cd();
 
   // Make a second file to store throws
   std::string tempFileName = fOutputFile;
   if (tempFileName.find(".root") != std::string::npos)
     tempFileName.erase(tempFileName.find(".root"), 5);
   tempFileName += ".throws.root";
   TFile* tempfile = new TFile(tempFileName.c_str(), "RECREATE");
 
   tempfile->cd();
   int nthrows = FitPar::Config().GetParI("error_throws");
 
   UpdateRWEngine(fCurVals);
   fSampleFCN->ReconfigureAllEvents();
 
   TDirectory* nominal = (TDirectory*)tempfile->mkdir("nominal");
   nominal->cd();
   fSampleFCN->Write();
 
   TDirectory* outnominal = (TDirectory*)fOutputRootFile->mkdir("nominal_throw");
   outnominal->cd();
   fSampleFCN->Write();
 
   errorDIR->cd();
   TTree* parameterTree = new TTree("throws", "throws");
   double chi2;
   for (UInt_t i = 0; i < fParams.size(); i++)
     parameterTree->Branch(fParams[i].c_str(), &fThrownVals[fParams[i]],
                           (fParams[i] + "/D").c_str());
   parameterTree->Branch("chi2", &chi2, "chi2/D");
 
   bool uniformly = FitPar::Config().GetParB("error_uniform");
 
   // Run Throws and save
   for (Int_t i = 0; i < nthrows; i++) {
     TDirectory* throwfolder = (TDirectory*)tempfile->mkdir(Form("throw_%i", i));
     throwfolder->cd();
 
     // Generate Random Parameter Throw
     ThrowCovariance(uniformly);
 
     // Run Eval
     double* vals = FitUtils::GetArrayFromMap(fParams, fThrownVals);
     chi2 = fSampleFCN->DoEval(vals);
     delete vals;
 
     // Save the FCN
     fSampleFCN->Write();
 
     parameterTree->Fill();
   }
 
   errorDIR->cd();
   fDecFree->Write();
   fCovFree->Write();
   parameterTree->Write();
 
   delete parameterTree;
 
   // Now go through the keys in the temporary file and look for TH1D, and TH2D
   // plots
   TIter next(nominal->GetListOfKeys());
   TKey* key;
   while ((key = (TKey*)next())) {
     TClass* cl = gROOT->GetClass(key->GetClassName());
     if (!cl->InheritsFrom("TH1D") and !cl->InheritsFrom("TH2D")) continue;
     TH1D* baseplot = (TH1D*)key->ReadObj();
     std::string plotname = std::string(baseplot->GetName());
 
     int nbins = baseplot->GetNbinsX() * baseplot->GetNbinsY();
 
     // Setup TProfile with RMS option
     TProfile* tprof =
         new TProfile((plotname + "_prof").c_str(), (plotname + "_prof").c_str(),
                      nbins, 0, nbins, "S");
 
     // Setup The TTREE
     double* bincontents;
     bincontents = new double[nbins];
 
     double* binlowest;
     binlowest = new double[nbins];
 
     double* binhighest;
     binhighest = new double[nbins];
 
     errorDIR->cd();
     TTree* bintree =
         new TTree((plotname + "_tree").c_str(), (plotname + "_tree").c_str());
     for (Int_t i = 0; i < nbins; i++) {
       bincontents[i] = 0.0;
       binhighest[i] = 0.0;
       binlowest[i] = 0.0;
       bintree->Branch(Form("content_%i", i), &bincontents[i],
                       Form("content_%i/D", i));
     }
 
     for (Int_t i = 0; i < nthrows; i++) {
       TH1* newplot =
           (TH1*)tempfile->Get(Form(("throw_%i/" + plotname).c_str(), i));
 
       for (Int_t j = 0; j < nbins; j++) {
         tprof->Fill(j + 0.5, newplot->GetBinContent(j + 1));
         bincontents[j] = newplot->GetBinContent(j + 1);
 
         if (bincontents[j] < binlowest[j] or i == 0)
           binlowest[j] = bincontents[j];
         if (bincontents[j] > binhighest[j] or i == 0)
           binhighest[j] = bincontents[j];
       }
 
       errorDIR->cd();
       bintree->Fill();
 
       delete newplot;
     }
 
     errorDIR->cd();
 
     for (Int_t j = 0; j < nbins; j++) {
       if (!uniformly) {
         baseplot->SetBinError(j + 1, tprof->GetBinError(j + 1));
 
       } else {
         baseplot->SetBinContent(j + 1, (binlowest[j] + binhighest[j]) / 2.0);
         baseplot->SetBinError(j + 1, (binhighest[j] - binlowest[j]) / 2.0);
       }
     }
 
     errorDIR->cd();
     baseplot->Write();
     tprof->Write();
     bintree->Write();
 
     delete baseplot;
     delete tprof;
     delete bintree;
     delete[] bincontents;
   }
 
   return;
 };
 
 void MinimizerRoutines::ThrowDataToys() {
   LOG(FIT) << "Generating Toy Data Throws" << std::endl;
-  int verb = Config::Get().GetParI("VERBOSITY");
+  int verb = Config::GetParI("VERBOSITY");
   SETVERBOSITY(FIT);
 
   int nthrows = FitPar::Config().GetParI("NToyThrows");
   double maxlike = -1.0;
   double minlike = -1.0;
   std::vector<double> values;
   for (int i = 0; i < 1.E4; i++) {
     fSampleFCN->ThrowDataToy();
     double like = fSampleFCN->GetLikelihood();
     values.push_back(like);
     if (maxlike == -1.0 or like > maxlike) maxlike = like;
     if (minlike == -1.0 or like < minlike) minlike = like;
   }
   SETVERBOSITY(verb);
 
   // Fill Histogram
   TH1D* likes = new TH1D("toydatalikelihood", "toydatalikelihood",
                          int(sqrt(nthrows)), minlike, maxlike);
   for (size_t i = 0; i < values.size(); i++) {
     likes->Fill(values[i]);
   }
 
   // Save to file
   LOG(FIT) << "Writing toy data throws" << std::endl;
   fOutputRootFile->cd();
   likes->Write();
 }
diff --git a/src/Routines/MinimizerRoutines.h b/src/Routines/MinimizerRoutines.h
index 310ca60..0733601 100755
--- a/src/Routines/MinimizerRoutines.h
+++ b/src/Routines/MinimizerRoutines.h
@@ -1,270 +1,270 @@
 // Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret
 
 /*******************************************************************************
 *    This file is part of NUISANCE.
 *
 *    NUISANCE is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    NUISANCE is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with NUISANCE.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
 
 #ifndef MINIMIZER_ROUTINES_H
 #define MINIMIZER_ROUTINES_H
 
 /*!
  *  \addtogroup Minimizer
  *  @{
  */
 
 #include "TH1.h"
 #include "TF1.h"
 #include "TMatrixD.h"
 #include "TVectorD.h"
 #include "Minuit2/FCNBase.h"
 #include "TFitterMinuit.h"
 #include "TSystem.h"
 #include "TFile.h"
 #include "TProfile.h"
 
 
 #include <vector>
 #include <string>
 #include <iostream>
 #include <sstream>
 #include <cstring>
 
 #include "FitEvent.h"
 #include "JointFCN.h"
 #include "MinimizerFCN.h"
-#include "FitParameters.h"
+
 
 #include "Math/Minimizer.h"
 #include "Math/Factory.h"
 #include "Math/Functor.h"
 #include "FitLogger.h"
 #include "ParserUtils.h"
 
 enum minstate {
   kErrorStatus = -1,
   kGoodStatus,
   kFitError,
   kNoChange,
   kFitFinished,
   kFitUnfinished,
   kStateChange,
 };
 
 //*************************************
 //! Collects all possible fit routines into a single class to avoid repeated code
 class MinimizerRoutines{
 //*************************************
 
 public:
 
   /*
     Constructor/Destructor
   */
 
   //! Constructor reads in arguments given at the command line for the fit here.
   MinimizerRoutines(int argc, char* argv[]);
     
   //! Default destructor
   ~MinimizerRoutines();
 
   //! Reset everything to default/NULL
   void Init();
   
   /*
     Input Functions
   */
 
   //! Splits the arguments ready for initial setup
   void ParseArgs(int argc, char* argv[]);
 
   //! Sorts out configuration and verbosity right at the very start.
   //! Calls readCard to set everything else up.
   void InitialSetup();
 
   //! Loops through each line of the card file and passes it to other read functions
   void ReadCard(std::string cardfile);
 
   //! Check for parameter string in the line and assign the correct type.
   //! Fills maps for each of the parameters
   int ReadParameters(std::string parstring);
 
   //! Reads in fake parameters and assigns them (Requires the parameter to be included as a normal parameter as well)
   int ReadFakeDataPars(std::string parstring);
 
   //! Read in the samples so we can set up the free normalisation dials if required
   int ReadSamples(std::string sampleString);
 void SetupMinimizerFromXML();
 
   /*
     Setup Functions
   */
 
   //! Setup the configuration given the arguments passed at the commandline and card file
   void SetupConfig();
 
   //! Setups up our custom RW engine with all the parameters passed in the card file
   void SetupRWEngine();
 
   //! Setups up the jointFCN.
   void SetupFCN();
 
   //! Sets up the minimizerObj for ROOT. there are cases where this is called repeatedly, e.g. If you are using a brute force scan before using Migrad.
   void SetupFitter(std::string routine);
 
   //! Set the current data histograms in each sample to the fake data.
   void SetFakeData();
 
   //! Setup the covariances with the correct dimensions. At the start this is either uncorrelated or merged given all the input covariances.
   //! At the end of the fit this produces the blank covariances which can then be filled by the minimizerObj with best fit covariances.
   void SetupCovariance();
 
   /*
     Fitting Functions
   */
 
   //! Main function to actually start iterating over the different required fit routines
   void Run();
 
   //! Given a new map change the values that the RW engine is currently set to
   void UpdateRWEngine(std::map<std::string,double>& updateVals);
 
   //! Given a single routine (see tutorial for options) run that fit routine now.
   int RunFitRoutine(std::string routine);
 
   //! Get the current state of minimizerObj and fill it into currentVals and currentNorms
   void GetMinimizerState();
 
   //! Print current value
   void PrintState();
   
   //! Performs a fit routine where the input.maxevents is set to a much lower value to try and move closer to the best fit minimum.
   void LowStatRoutine(std::string routine);
 
   //! Perform a chi2 scan in 1D around the current point
   void Create1DScans();
 
   //! Perform a chi2 scan in 2D around the current point
   void Chi2Scan2D();
 
   //! Currently a placeholder NEEDS UPDATING
   void CreateContours();
 
   //! If any currentVals are close to the limits set them to the limit and fix them
   int FixAtLimit();
 
   //! Throw the current covariance of dial values we have, and fill the thrownVals and thrownNorms maps.
   //! If uniformly is true parameters will be thrown uniformly between their upper and lower limits.
   void ThrowCovariance(bool uniformly);
 
   //! Given the covariance we currently have generate error bands by throwing the covariance.
   //! The FitPar config "error_uniform" defines whether to throw using the covariance or uniformly.
   //! The FitPar config "error_throws" defines how many throws are needed.
   //! Currently only supports TH1D plots.
   void GenerateErrorBands();
 
   /*
     Write Functions
   */
 
   //! Write plots and TTrees listing the minimizerObj result of the fit to file
   void SaveMinimizerState();
 
   //! Save the sample plots for current MC
   //! dir if not empty forces plots to be saved in a subdirectory of outputfile
   void SaveCurrentState(std::string subdir="");
 
   //! Save starting predictions into a seperate folder
   void SaveNominal();
 
   //! Save predictions before the fit is ran into a seperate folder
   void SavePrefit();
 
   void SaveResults();
   /*
     MISC Functions
   */
 
   //! Get previous fit status from a file
   Int_t GetStatus();
 
   /// Makes a histogram of likelihoods when throwing the data according to its statistics
   void ThrowDataToys();
 
 protected:
 
   //! Our Custom ReWeight Object
   FitWeight* rw;
 
   std::string fOutputFile;
   std::string fInputFile;
 
   TFile* fInputRootFile;
   TFile* fOutputRootFile;
 
   //! Flag for whether the fit should be continued if an output file is already found.
   bool fitContinue;
 
   //! Minimizer Object for handling roots different minimizer methods
   ROOT::Math::Minimizer* fMinimizer;
 
   JointFCN* fSampleFCN;
   MinimizerFCN* fMinimizerFCN;
   ROOT::Math::Functor* fCallFunctor;
 
   int nfreepars;
 
   std::string fCardFile;
 
   std::string fStrategy;
   std::vector<std::string> fRoutines;
   std::string fAllowedRoutines;
   
   std::string fFakeDataInput;
 
   // Input Dial Vals
   //! Vector of dial names
   std::vector<std::string> fParams;
   std::map<std::string, std::string> fStateVals;
   std::map<std::string, double>      fStartVals;
   std::map<std::string, double>      fCurVals;
   std::map<std::string, double>      fErrorVals;
   std::map<std::string, double>      fMinVals;
   std::map<std::string, double>      fMaxVals;
   std::map<std::string, double>      fStepVals;
   std::map<std::string, int>         fTypeVals;
   std::map<std::string, bool>        fFixVals;
   std::map<std::string, bool>        fStartFixVals;
 
   //! Vector of fake parameter names
   std::map<std::string,double> fFakeVals;
 
   //! Map of thrown parameter names and values (After ThrowCovariance)
   std::map<std::string,double> fThrownVals;
 
   TH2D* fCorrel;
   TH2D* fDecomp;
   TH2D* fCovar;
   
   TH2D* fCorFree;
   TH2D* fDecFree;
   TH2D* fCovFree;
 
     nuiskey fCompKey;
 
 };
 
 /*! @} */
 #endif
diff --git a/src/Routines/Simple_MH_Sampler.h b/src/Routines/Simple_MH_Sampler.h
index 48d43fa..527be29 100644
--- a/src/Routines/Simple_MH_Sampler.h
+++ b/src/Routines/Simple_MH_Sampler.h
@@ -1,334 +1,334 @@
 #include "Math/Minimizer.h"
 
 #include "FitLogger.h"
 
 using ROOT::Math::Minimizer;
 
 class Simple_MH_Sampler : public Minimizer {
   TRandom3 RNJesus;
 
   size_t step_i;
   int moved;
 
   size_t thin;
   size_t thin_ctr;
 
   size_t discard;
 
   struct Param {
     Param()
         : IsFixed(false),
           name(""),
           Val(0xdeadbeef),
           StepWidth(0xdeadbeef),
           LowLim(0xdeadbeef),
           UpLim(0xdeadbeef) {}
     Param(bool i, std::string n, double v, double s, double l, double u)
         : IsFixed(i), name(n), Val(v), StepWidth(s), LowLim(l), UpLim(u) {}
     bool IsFixed;
     std::string name;
     double Val, StepWidth, LowLim, UpLim;
   };
 
   std::vector<Param> start_params;
 
   double curr_value;
   std::vector<double> curr_params;
 
   double propose_value;
   std::vector<double> propose_params;
 
   double min_value;
   std::vector<double> min_params;
 
   TGraph trace;
 
   void RestartParams() {
     curr_params.resize(start_params.size());
     for (size_t p_it = 0; p_it < start_params.size(); ++p_it) {
       curr_params[p_it] = start_params[p_it].Val;
     }
     min_params = curr_params;
     propose_params = curr_params;
   }
 
   TTree *StepTree;
 
   void Write();
 
   ROOT::Math::IMultiGenFunction const *FCN;
 
  public:
   Simple_MH_Sampler() : Minimizer(), RNJesus(), trace() {
-    thin = Config::Get().ConfI("MCMC.thin");
+    thin = Config::GetParI("MCMC.thin");
     thin_ctr = 0;
-    discard = Config::Get().ConfI("MCMC.BurnInSteps");
+    discard = Config::GetParI("MCMC.BurnInSteps");
   }
 
   void SetFunction(ROOT::Math::IMultiGenFunction const &func) { FCN = &func; }
 
   bool SetVariable(unsigned int ivar, std::string const &name, double val,
                    double step) {
     if (start_params.size() <= ivar) {
       start_params.resize(ivar + 1);
     }
     start_params[ivar] = Param(false, name, val, step, 0xdeadbeef, 0xdeadbeef);
     RestartParams();
     return true;
   }
 
   bool SetLowerLimitedVariable(unsigned int ivar, std::string const &name,
                                double val, double step, double lower) {
     SetVariable(ivar, name, val, step);
     start_params[ivar].LowLim = lower;
     return true;
   }
   bool SetUpperLimitedVariable(unsigned int ivar, std::string const &name,
                                double val, double step, double upper) {
     SetVariable(ivar, name, val, step);
     start_params[ivar].UpLim = upper;
     return true;
   }
   bool SetLimitedVariable(unsigned int ivar, std::string const &name,
                           double val, double step, double lower, double upper) {
     SetLowerLimitedVariable(ivar, name, val, step, lower);
     start_params[ivar].UpLim = upper;
     return true;
   }
   bool SetFixedVariable(unsigned int ivar, std::string const &name,
                         double val) {
     SetVariable(ivar, name, val, 0xdeadbeef);
     start_params[ivar].IsFixed = true;
     return true;
   }
   bool SetVariableValue(unsigned int ivar, double value) {
     if (start_params.size() <= ivar) {
       ERROR(WRN, "Tried to set uninitialised variable.");
       return false;
     }
     start_params[ivar].Val = value;
     return true;
   }
   bool SetVariableStepSize(unsigned int ivar, double value) {
     if (start_params.size() <= ivar) {
       ERROR(WRN, "Tried to set uninitialised variable.");
       return false;
     }
     start_params[ivar].StepWidth = value;
     return true;
   }
   bool SetVariableLowerLimit(unsigned int ivar, double lower) {
     if (start_params.size() <= ivar) {
       ERROR(WRN, "Tried to set uninitialised variable.");
       return false;
     }
     start_params[ivar].LowLim = lower;
     return true;
   }
   bool SetVariableUpperLimit(unsigned int ivar, double upper) {
     if (start_params.size() <= ivar) {
       ERROR(WRN, "Tried to set uninitialised variable.");
       return false;
     }
     start_params[ivar].UpLim = upper;
     return true;
   }
   bool SetVariableLimits(unsigned int ivar, double lower, double upper) {
     SetVariableLowerLimit(ivar, lower);
     SetVariableUpperLimit(ivar, upper);
     return true;
   }
   bool FixVariable(unsigned int ivar) {
     if (start_params.size() <= ivar) {
       ERROR(WRN, "Tried to fix uninitialised variable.");
       return false;
     }
     start_params[ivar].IsFixed = true;
     return true;
   }
   bool ReleaseVariable(unsigned int ivar) {
     if (start_params.size() <= ivar) {
       ERROR(WRN, "Tried to fix uninitialised variable.");
       return false;
     }
     start_params[ivar].IsFixed = false;
     return true;
   }
   bool IsFixedVariable(unsigned int ivar) {
     if (start_params.size() <= ivar) {
       ERROR(WRN, "Tried to fix uninitialised variable.");
       return false;
     }
     return start_params[ivar].IsFixed;
   }
 
   double MinValue() const { return min_value; }
   const double *X() const { return min_params.data(); }
   const double *Errors() const { return min_params.data(); }
 
   unsigned int NDim() const { return start_params.size(); }
 
   unsigned int NFree() const {
     unsigned int NFree = 0;
 
     for (size_t p_it = 0; p_it < start_params.size(); ++p_it) {
       NFree += !start_params[p_it].IsFixed;
     }
     return NFree;
   }
 
   void AddBranches() {
     TFile *ogf = gFile;
-    if (FitPar::Config().out && FitPar::Config().out->IsOpen()) {
-      FitPar::Config().out->cd();
+    if (Config::Get().out && Config::Get().out->IsOpen()) {
+      Config::Get().out->cd();
     }
 
     StepTree = new TTree("MCMChain", "");
     StepTree->Branch("Step", &step_i, "Step/I");
     StepTree->Branch("Value", &curr_value, "Value/D");
     StepTree->Branch("Moved", &moved, "Moved/I");
 
     std::stringstream ss("");
     for (size_t p_it = 0; p_it < curr_params.size(); ++p_it) {
       ss.str("");
       ss << "param_" << p_it;
       StepTree->Branch(ss.str().c_str(), &curr_params[p_it],
                        (ss.str() + "/D").c_str());
     }
 
     if (ogf && ogf->IsOpen()) {
       ogf->cd();
     }
   }
 
   void Fill() { StepTree->Fill(); }
 
   void Propose() {
     for (size_t p_it = 0; p_it < start_params.size(); ++p_it) {
       double propose_param = curr_params[p_it];
 
       if (!start_params[p_it].IsFixed) {
         size_t attempts = 0;
         do {
           if (attempts > 1000) {
             THROW("After 1000 attempts, failed to throw Gaus("
                   << start_params[p_it].Val << ", "
                   << start_params[p_it].StepWidth << ") inside limits: [ "
                   << start_params[p_it].LowLim << " -- "
                   << start_params[p_it].UpLim << " ]");
           }
 
           double thr =
               RNJesus.Gaus(curr_params[p_it], start_params[p_it].StepWidth);
 
           if ((start_params[p_it].LowLim != 0xdeadbeef) &&
               (thr < start_params[p_it].LowLim)) {
             attempts++;
             continue;
           }
 
           if ((start_params[p_it].UpLim != 0xdeadbeef) &&
               (thr > start_params[p_it].UpLim)) {
             attempts++;
             continue;
           }
 
           propose_param = thr;
           break;
 
         } while (true);
       }
 
       propose_params[p_it] = propose_param;
     }
   }
 
   void Evaluate() {
     propose_value = exp(-(*FCN)(propose_params.data()) / 10000.0);
     if (propose_value < min_value) {
       min_params = propose_params;
     }
   }
 
   void PrintResults() {
     QLOG(FIT, "Simple_MH_Sampler State: ");
     for (size_t p_it = 0; p_it < start_params.size(); ++p_it) {
       QLOG(FIT, "\t[" << p_it
                       << "]: " << (start_params[p_it].IsFixed ? " FIX" : "FREE")
                       << " " << curr_params[p_it]);
     }
     QLOG(FIT, "Curr LHood: " << curr_value << ", Min LHood: " << min_value);
   }
 
   void Step() {
     moved = false;
 
     if (propose_value != propose_value) {
       curr_params = propose_params;
       curr_value = propose_value;
       PrintResults();
       THROW("Proposed a NAN value.");
     }
 
     std::cout << "[" << step_i << "] proposed: " << propose_value
               << " | current: " << curr_value << std::endl;
     double a = propose_value / curr_value;
     std::cout << "\ta = " << a << std::endl;
     if (a >= 1.0) {
       moved = true;
       std::cout << "\tMoved." << std::endl;
     } else {
       double b = RNJesus.Uniform(1);
       if (b < a) {
         moved = true;
         std::cout << "\tMoved (" << b << ")" << std::endl;
       } else {
         std::cout << "\tStayed. (" << b << ")" << std::endl;
       }
     }
 
     if (moved) {
       curr_params = propose_params;
       curr_value = propose_value;
     }
   }
 
   bool Minimize() {
     if (!start_params.size()) {
       ERROR(FTL, "No Parameters passed to Simple_MH_Sampler.");
       return false;
     }
 
     RestartParams();
 
     AddBranches();
 
     size_t NSteps = Options().MaxIterations();
     trace.Set(NSteps);
     QLOG(FIT, "Running chain for " << NSteps << " steps.");
     step_i = 0;
     while (step_i < NSteps) {
       Propose();
 
       Evaluate();
 
       Step();
 
       trace.SetPoint(step_i, step_i, curr_value);
 
       if (step_i >= discard) {
         thin_ctr++;
         if (thin_ctr == thin) {
           Fill();
           thin_ctr = 0;
         }
       }
       step_i++;
     }
 
     StepTree->Write();
     trace.Write("MCMCTrace");
 
     return true;
   };
 };
diff --git a/src/Routines/SplineRoutines.cxx b/src/Routines/SplineRoutines.cxx
index 8a24297..9369da2 100755
--- a/src/Routines/SplineRoutines.cxx
+++ b/src/Routines/SplineRoutines.cxx
@@ -1,2593 +1,2588 @@
 // Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret
 
 /*******************************************************************************
 *    This file is part of NUISANCE.
 *
 *    NUISANCE is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    NUISANCE is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with NUISANCE.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
 #include "SplineRoutines.h"
 
 void SplineRoutines::Init() {
 
   fStrategy = "SaveEvents";
   fRoutines.clear();
 
   fCardFile = "";
 
   fSampleFCN = NULL;
   fRW = NULL;
 
   fAllowedRoutines = ("SaveEvents,TestEvents,SaveSplineEvents");
 };
 
 SplineRoutines::~SplineRoutines() {
 };
 
 SplineRoutines::SplineRoutines(int argc, char* argv[]) {
 
   // Initialise Defaults
   Init();
   nuisconfig configuration = Config::Get();
 
   // Default containers
   std::string cardfile = "";
   std::string maxevents = "-1";
   int errorcount = 0;
   int verbocount = 0;
   std::vector<std::string> xmlcmds;
   std::vector<std::string> configargs;
 
   // Make easier to handle arguments.
   std::vector<std::string> args = GeneralUtils::LoadCharToVectStr(argc, argv);
   ParserUtils::ParseArgument(args, "-c", fCardFile, true);
   ParserUtils::ParseArgument(args, "-o", fOutputFile, false, false);
   ParserUtils::ParseArgument(args, "-n", maxevents, false, false);
   ParserUtils::ParseArgument(args, "-f", fStrategy, false, false);
   ParserUtils::ParseArgument(args, "-i", xmlcmds);
   ParserUtils::ParseArgument(args, "-q", configargs);
   ParserUtils::ParseCounter(args, "e", errorcount);
   ParserUtils::ParseCounter(args, "v", verbocount);
   ParserUtils::CheckBadArguments(args);
 
   // Add extra defaults if none given
   if (fCardFile.empty() and xmlcmds.empty()) {
     ERR(FTL) << "No input supplied!" << std::endl;
     throw;
   }
 
   if (fOutputFile.empty() and !fCardFile.empty()) {
     fOutputFile = fCardFile + ".root";
     ERR(WRN) << "No output supplied so saving it to: " << fOutputFile << std::endl;
 
   } else if (fOutputFile.empty()) {
     ERR(FTL) << "No output file or cardfile supplied!" << std::endl;
     throw;
   }
 
   // Configuration Setup =============================
 
   // Check no comp key is available
   nuiskey fCompKey;
   if (Config::Get().GetNodes("nuiscomp").empty()) {
     fCompKey = Config::Get().CreateNode("nuiscomp");
   } else {
     fCompKey = Config::Get().GetNodes("nuiscomp")[0];
   }
 
-  if (!fCardFile.empty())   fCompKey.AddS("cardfile", fCardFile);
-  fCompKey.AddS("outputfile", fOutputFile);
-  if (!fStrategy.empty())   fCompKey.AddS("strategy", fStrategy);
+  if (!fCardFile.empty())   fCompKey.Set("cardfile", fCardFile);
+  fCompKey.Set("outputfile", fOutputFile);
+  if (!fStrategy.empty())   fCompKey.Set("strategy", fStrategy);
 
   // Load XML Cardfile
-  configuration.LoadConfig( fCompKey.GetS("cardfile"), "");
-
-  // Add CMD XML Structs
-  for (size_t i = 0; i < xmlcmds.size(); i++) {
-    configuration.AddXMLLine(xmlcmds[i]);
-  }
+  configuration.LoadSettings( fCompKey.GetS("cardfile"), "");
 
   // Add Config Args
   for (size_t i = 0; i < configargs.size(); i++) {
     configuration.OverrideConfig(configargs[i]);
   }
   if (maxevents.compare("-1")) {
     std::cout << "[ NUISANCE ] : Overriding " << "MAXEVENTS=" + maxevents << std::endl;
     configuration.OverrideConfig("MAXEVENTS=" + maxevents);
   }
 
   // Finish configuration XML
-  configuration.FinaliseConfig(fCompKey.GetS("outputfile") + ".xml");
+  configuration.FinaliseSettings(fCompKey.GetS("outputfile") + ".xml");
 
   // Add Error Verbo Lines
-  verbocount += Config::Get().GetParI("VERBOSITY");
-  errorcount += Config::Get().GetParI("ERROR");
+  verbocount += Config::GetParI("VERBOSITY");
+  errorcount += Config::GetParI("ERROR");
   std::cout << "[ NUISANCE ]: Setting VERBOSITY=" << verbocount << std::endl;
   std::cout << "[ NUISANCE ]: Setting ERROR=" << errorcount << std::endl;
   // FitPar::log_verb = verbocount;
   SETVERBOSITY(verbocount);
   // ERR_VERB(errorcount);
 
   // Starting Setup
   // ---------------------------
   SetupRWEngine();
 
   return;
 };
 
 
 /*
   Setup Functions
 */
 //*************************************
 void SplineRoutines::SetupRWEngine() {
 //*************************************
 
   fRW = new FitWeight("splineweight");
   // std::vector<nuiskey> splinekeys    = Config::QueryKeys("spline");
   std::vector<nuiskey> parameterkeys = Config::QueryKeys("parameter");
 
   // Add Parameters
   for (size_t i = 0; i < parameterkeys.size(); i++) {
     nuiskey key = parameterkeys[i];
 
     std::string parname = key.GetS("name");
     std::string partype = key.GetS("type");
     double nom = key.GetD("nominal");
 
     fRW->IncludeDial( key.GetS("name"),
                       FitBase::ConvDialType(key.GetS("type")), nom);
     fRW->SetDialValue( key.GetS("name"), key.GetD("nominal") );
 
   }
   fRW->Reconfigure();
 
   return;
 }
 
 
 /*
   Fitting Functions
 */
 //*************************************
 void SplineRoutines::UpdateRWEngine(std::map<std::string, double>& updateVals) {
 //*************************************
 
   for (UInt_t i = 0; i < fParams.size(); i++) {
     std::string name = fParams[i];
 
     if (updateVals.find(name) == updateVals.end()) continue;
     fRW->SetDialValue(name, updateVals.at(name));
   }
 
   fRW->Reconfigure();
   return;
 }
 
 //*************************************
 void SplineRoutines::Run() {
 //*************************************
   std::cout << "Running " << std::endl;
 
   // Parse given routines
   fRoutines = GeneralUtils::ParseToStr(fStrategy, ",");
   if (fRoutines.empty()) {
     ERR(FTL) << "Trying to run ComparisonRoutines with no routines given!" << std::endl;
     throw;
   }
 
   for (size_t i = 0; i < fRoutines.size(); i++) {
 
     LOG(FIT) << "Running Routine: " << fRoutines[i] << std::endl;
     std::string rout = fRoutines[i];
     if       (!rout.compare("SaveEvents")) SaveEvents();
     else if  (!rout.compare("TestEvents")) TestEvents();
     else if  (!rout.compare("GenerateEventSplines")) {  GenerateEventWeights(); BuildEventSplines(); }
     else if  (!rout.compare("GenerateEventWeights")) { GenerateEventWeights(); }
     else if  (!rout.compare("GenerateEventWeightChunks")){ GenerateEventWeightChunks(FitPar::Config().GetParI("spline_procchunk")); }
     else if  (!rout.compare("BuildEventSplines"))    { BuildEventSplines(); }
     else if  (!rout.compare("TestSplines_1DEventScan")) TestSplines_1DEventScan();
     else if  (!rout.compare("TestSplines_NDEventThrow")) TestSplines_NDEventThrow();
     else if  (!rout.compare("SaveSplinePlots")) SaveSplinePlots();
     else if  (!rout.compare("TestSplines_1DLikelihoodScan")) TestSplines_1DLikelihoodScan();
     else if  (!rout.compare("TestSplines_NDLikelihoodThrow")) TestSplines_NDLikelihoodThrow();
     else if (!rout.compare("BuildEventSplinesChunks")) {
       int chunk = FitPar::Config().GetParI("spline_procchunk");
       BuildEventSplines(chunk);
     } else if (!rout.compare("MergeEventSplinesChunks")) {
       MergeEventSplinesChunks();
     }
   }
 
 
 }
 
 //*************************************
 void SplineRoutines::SaveEvents() {
 //*************************************
 
   if (fRW) delete fRW;
   SetupRWEngine();
   fRW->Reconfigure();
   fRW->Print();
 
   // Generate a set of nominal events
   // Method, Loop over inputs, create input handler, then create a ttree
   std::vector<nuiskey> eventkeys = Config::QueryKeys("events");
   for (size_t i = 0; i < eventkeys.size(); i++) {
     nuiskey key = eventkeys.at(i);
 
     // Get I/O
     std::string inputfilename  = key.GetS("input");
     if (inputfilename.empty()) {
       ERR(FTL) << "No input given for set of input events!" << std::endl;
       throw;
     }
 
     std::string outputfilename = key.GetS("output");
     if (outputfilename.empty()) {
       outputfilename = inputfilename + ".nuisance.root";
       ERR(FTL) << "No output give for set of output events! Saving to "
                << outputfilename << std::endl;
     }
 
     // Make new outputfile
     TFile* outputfile = new TFile(outputfilename.c_str(), "RECREATE");
     outputfile->cd();
 
     // Make a new input handler
     std::vector<std::string> file_descriptor =
       GeneralUtils::ParseToStr(inputfilename, ":");
     if (file_descriptor.size() != 2) {
       ERR(FTL) << "File descriptor had no filetype declaration: \"" << inputfilename
                << "\". expected \"FILETYPE:file.root\"" << std::endl;
       throw;
     }
     InputUtils::InputType inptype =
       InputUtils::ParseInputType(file_descriptor[0]);
 
     InputHandlerBase* input = InputUtils::CreateInputHandler("eventsaver", inptype, file_descriptor[1]);
 
     // Get info from inputhandler
     int nevents = input->GetNEvents();
     int countwidth = (nevents / 10);
     FitEvent* nuisevent = input->FirstNuisanceEvent();
 
     // Setup a TTree to save the event
     outputfile->cd();
     TTree* eventtree = new TTree("nuisance_events", "nuisance_events");
     nuisevent->AddBranchesToTree(eventtree);
 
     // Loop over all events and fill the TTree
     int icount = 0;
     // int countwidth = nevents / 5;
 
     while (nuisevent) {
 
       // Get Event Weight
       nuisevent->RWWeight = fRW->CalcWeight(nuisevent);
       // if (nuisevent->RWWeight != 1.0){
       // std::cout << "Weight = " << nuisevent->RWWeight << std::endl;
       // }
       // Save everything
       eventtree->Fill();
 
       // Logging
       if (icount % countwidth == 0) {
         LOG(REC) << "Saved " << icount << "/" << nevents
                  << " nuisance events. [M, W] = ["
                  << nuisevent->Mode << ", " << nuisevent->RWWeight << "]" << std::endl;
       }
 
       // iterate
       nuisevent = input->NextNuisanceEvent();
       icount++;
     }
 
     // Save flux and close file
     outputfile->cd();
     eventtree->Write();
     input->GetFluxHistogram()->Write("nuisance_fluxhist");
     input->GetEventHistogram()->Write("nuisance_eventhist");
 
     // Close Output
     outputfile->Close();
 
     // Delete Inputs
     delete input;
   }
 
   // remove Keys
   eventkeys.clear();
 
   // Finished
   LOG(FIT) << "Finished processing all nuisance events." << std::endl;
 }
 
 //*************************************
 void SplineRoutines::TestEvents() {
 //*************************************
 
   LOG(FIT) << "Testing events." << std::endl;
 
   // Create a new file for the test samples
   if (!fOutputRootFile) {
     fOutputRootFile = new TFile(fCompKey.GetS("outputfile").c_str(), "RECREATE");
   }
 
   // Loop over all tests
   int count = 0;
   std::vector<nuiskey> testkeys = Config::QueryKeys("sampletest");
   for (std::vector<nuiskey>::iterator iter = testkeys.begin();
        iter != testkeys.end(); iter++) {
     nuiskey key = (*iter);
 
     // 0. Create new measurement list
     std::list<MeasurementBase*> samplelist;
 
     // 1. Build Sample From Events
     std::string samplename = key.GetS("name");
     std::string eventsid = key.GetS("inputid");
     nuiskey eventskey = Config::QueryLastKey("events", "id=" + eventsid);
     std::string rawfile = eventskey.GetS("input");
     LOG(FIT) << "Creating sample " << samplename << std::endl;
     MeasurementBase* rawsample = SampleUtils::CreateSample(samplename, rawfile, "", "", FitBase::GetRW());
 
     // 2. Build Sample From Nuisance Events
     std::string eventsfile = eventskey.GetS("output");
     LOG(FIT) << "Creating Fit Eevnt Sample " << samplename << " " << eventsfile << std::endl;
     MeasurementBase* nuissample = SampleUtils::CreateSample(samplename, "FEVENT:" + eventsfile, "", "", FitBase::GetRW());
 
     // 3. Make some folders to save stuff
     TDirectory* sampledir   = (TDirectory*) fOutputRootFile->mkdir(Form((samplename + "_test_%d").c_str(), count));
     TDirectory* rawdir      = (TDirectory*) sampledir->mkdir("raw");
     TDirectory* nuisancedir = (TDirectory*) sampledir->mkdir("nuisance");
     TDirectory* difdir      = (TDirectory*) sampledir->mkdir("difference");
 
     // 4. Reconfigure both
     rawdir->cd();
     rawsample->Reconfigure();
     rawsample->Write();
 
     nuisancedir->cd();
     nuissample->Reconfigure();
     nuissample->Write();
 
     // 4. Compare Raw to Nuisance Events
 
     // Loop over all keyse
     TIter next(rawdir->GetListOfKeys());
     TKey *dirkey;
     while ((dirkey = (TKey*)next())) {
 
       // If not a 1D/2D histogram skip
       TClass *cl = gROOT->GetClass(dirkey->GetClassName());
       if (!cl->InheritsFrom("TH1D") and !cl->InheritsFrom("TH2D")) continue;
 
       // Get TH1* from both dir
       TH1 *rawplot      = (TH1*)rawdir->Get(dirkey->GetName());
       TH1 *nuisanceplot = (TH1*)nuisancedir->Get(dirkey->GetName());
 
       // Take Difference
       nuisanceplot->Add(rawplot, -1.0);
 
       // Save to dif folder
       difdir->cd();
       nuisanceplot->Write();
     }
 
     // 5. Tidy Up
     samplelist.clear();
 
     // Iterator
     count++;
   }
 }
 
 void SplineRoutines::GenerateEventWeightChunks(int procchunk) {
   if (fRW) delete fRW;
   SetupRWEngine();
 
   // Setup the spline reader
   SplineWriter* splwrite = new SplineWriter(fRW);
   std::vector<nuiskey> splinekeys = Config::QueryKeys("spline");
 
   // Add splines to splinewriter
   for (std::vector<nuiskey>::iterator iter = splinekeys.begin();
        iter != splinekeys.end(); iter++) {
     nuiskey splkey = (*iter);
 
     // Add Spline Info To Reader
     splwrite->AddSpline(splkey);
   }
   splwrite->SetupSplineSet();
 
   // Event Loop
   // Loop over all events and calculate weights for each parameter set.
 
   // Generate a set of nominal events
   // Method, Loop over inputs, create input handler, then create a ttree
   std::vector<nuiskey> eventkeys = Config::QueryKeys("events");
   for (size_t i = 0; i < eventkeys.size(); i++) {
     nuiskey key = eventkeys.at(i);
 
     // Get I/O
     std::string inputfilename  = key.GetS("input");
     if (inputfilename.empty()) {
       ERR(FTL) << "No input given for set of input events!" << std::endl;
       throw;
     }
 
     std::string outputfilename = key.GetS("output");
     if (outputfilename.empty()) {
       outputfilename = inputfilename + ".nuisance.root";
       ERR(FTL) << "No output give for set of output events! Saving to "
                << outputfilename << std::endl;
     }
     outputfilename += ".weights.root";
 
     // Make new outputfile
     TFile* outputfile = new TFile(outputfilename.c_str(), "RECREATE");
     outputfile->cd();
 
     // Make a new input handler
     std::vector<std::string> file_descriptor =
       GeneralUtils::ParseToStr(inputfilename, ":");
     if (file_descriptor.size() != 2) {
       ERR(FTL) << "File descriptor had no filetype declaration: \"" << inputfilename
                << "\". expected \"FILETYPE:file.root\"" << std::endl;
       throw;
     }
     InputUtils::InputType inptype =
       InputUtils::ParseInputType(file_descriptor[0]);
 
     InputHandlerBase* input = InputUtils::CreateInputHandler("eventsaver", inptype, file_descriptor[1]);
 
     // Get info from inputhandler
     int nevents = input->GetNEvents();
     // int countwidth = (nevents / 1000);
     FitEvent* nuisevent = input->FirstNuisanceEvent();
 
     // Setup a TTree to save the event
     outputfile->cd();
     TTree* eventtree = new TTree("nuisance_events", "nuisance_events");
 
     // Add a flag that allows just splines to be saved.
     nuisevent->AddBranchesToTree(eventtree);
 
     // Save the spline reader
     splwrite->Write("spline_reader");
 
     // Setup the spline TTree
     TTree* weighttree = new TTree("weight_tree", "weight_tree");
     splwrite->AddWeightsToTree(weighttree);
 
     // Make container for all weights
     int nweights = splwrite->GetNWeights();
     // int npar = splwrite->GetNPars();
     // double* weightcont = new double[nweights];
 
     int lasttime = time(NULL);
 
     // Load N Chunks of the Weights into Memory
     // Split into N processing chunks
     int nchunks = FitPar::Config().GetParI("spline_chunks");
     if (nchunks <= 0) nchunks = 1;
     if (nchunks >= nevents / 2) nchunks = nevents / 2;
 
     std::cout << "Starting NChunks " << nchunks << std::endl;
     for (int ichunk = 0; ichunk < nchunks; ichunk++) {
 
       // Skip to only do one processing chunk
       if (procchunk != -1 and procchunk != ichunk) continue;
 
       LOG(FIT) << "On Processing Chunk " << ichunk << std::endl;
       int neventsinchunk   = nevents / nchunks;
       int loweventinchunk  = neventsinchunk * ichunk;
       // int higheventinchunk = neventsinchunk * (ichunk + 1);
 
       double** allweightcont = new double*[neventsinchunk];
       for (int k = 0; k < neventsinchunk; k++){
         allweightcont[k] = new double[nweights];
       }
 
       // Start Set Processing Here.
       for (int iset = 0; iset < nweights; iset++) {
 
         splwrite->ReconfigureSet(iset);
 
         // Could reorder this to save the weightconts in order instead of reconfiguring per event.
         // Loop over all events and fill the TTree
         for (int i = 0; i < neventsinchunk; i++){
 
           nuisevent = input->GetNuisanceEvent(i+loweventinchunk);
           double w = splwrite->GetWeightForThisSet(nuisevent);
 
 	  if (iset == 0){
 	    allweightcont[i][0] = w;
 	  } else {
 	    allweightcont[i][iset] = w/allweightcont[i][0];
 	  }
 
           // Save everything
           if (iset == 0) {
             eventtree->Fill();
           } 
         }
 	
 	std::ostringstream timestring;
         int timeelapsed = time(NULL) - lasttime;
         if  (timeelapsed) {
           lasttime = time(NULL);
 
           int setsleft = (nweights-iset-1) + (nweights * (nchunks - ichunk - 1));
           float proj = (float(setsleft) *timeelapsed) / 60 / 60;
           timestring << setsleft << " sets remaining. Last one took " << timeelapsed << ". " << proj << " hours remaining.";
 
         }
 
 	LOG(REC) << "Processed Set " << iset << "/" << nweights <<" in chunk " << ichunk << "/" << nchunks << " " << timestring.str() << std::endl;
 
       }
 
       // Fill weights for this chunk into the TTree
       for (int k = 0; k < neventsinchunk; k++){
         splwrite->SetWeights(allweightcont[k]);
         weighttree->Fill();
       }
     }
 
     // at end of the chunk, when all sets have been done
     // loop over the container and fill weights to ttree
 
     outputfile->cd();
     eventtree->Write();
     weighttree->Write();
     input->GetFluxHistogram()->Write("nuisance_fluxhist");
     input->GetEventHistogram()->Write("nuisance_eventhist");
     splwrite->Write("spline_reader");
     outputfile->Close();
 
     // Close Output
     outputfile->Close();
 
     // Delete Inputs
     delete input;
   }
 
   // remove Keys
   eventkeys.clear();
 
 }
 
 //*************************************
 void SplineRoutines::GenerateEventWeights() {
 //*************************************
   if (fRW) delete fRW;
   SetupRWEngine();
 
   // Setup the spline reader
   SplineWriter* splwrite = new SplineWriter(fRW);
   std::vector<nuiskey> splinekeys = Config::QueryKeys("spline");
 
   // Add splines to splinewriter
   for (std::vector<nuiskey>::iterator iter = splinekeys.begin();
        iter != splinekeys.end(); iter++) {
     nuiskey splkey = (*iter);
 
     // Add Spline Info To Reader
     splwrite->AddSpline(splkey);
   }
   splwrite->SetupSplineSet();
 
   // Event Loop
   // Loop over all events and calculate weights for each parameter set.
 
   // Generate a set of nominal events
   // Method, Loop over inputs, create input handler, then create a ttree
   std::vector<nuiskey> eventkeys = Config::QueryKeys("events");
   for (size_t i = 0; i < eventkeys.size(); i++) {
     nuiskey key = eventkeys.at(i);
 
     // Get I/O
     std::string inputfilename  = key.GetS("input");
     if (inputfilename.empty()) {
       ERR(FTL) << "No input given for set of input events!" << std::endl;
       throw;
     }
 
     std::string outputfilename = key.GetS("output");
     if (outputfilename.empty()) {
       outputfilename = inputfilename + ".nuisance.root";
       ERR(FTL) << "No output give for set of output events! Saving to "
                << outputfilename << std::endl;
     }
     outputfilename += ".weights.root";
 
     // Make new outputfile
     TFile* outputfile = new TFile(outputfilename.c_str(), "RECREATE");
     outputfile->cd();
 
     // Make a new input handler
     std::vector<std::string> file_descriptor =
       GeneralUtils::ParseToStr(inputfilename, ":");
     if (file_descriptor.size() != 2) {
       ERR(FTL) << "File descriptor had no filetype declaration: \"" << inputfilename
                << "\". expected \"FILETYPE:file.root\"" << std::endl;
       throw;
     }
     InputUtils::InputType inptype =
       InputUtils::ParseInputType(file_descriptor[0]);
 
     InputHandlerBase* input = InputUtils::CreateInputHandler("eventsaver", inptype, file_descriptor[1]);
 
     // Get info from inputhandler
     int nevents = input->GetNEvents();
     int countwidth = (nevents / 1000);
     FitEvent* nuisevent = input->FirstNuisanceEvent();
 
     // Setup a TTree to save the event
     outputfile->cd();
     TTree* eventtree = new TTree("nuisance_events", "nuisance_events");
 
     // Add a flag that allows just splines to be saved.
     nuisevent->AddBranchesToTree(eventtree);
 
     // Save the spline reader
     splwrite->Write("spline_reader");
 
     // Setup the spline TTree
     TTree* weighttree = new TTree("weight_tree", "weight_tree");
     splwrite->AddWeightsToTree(weighttree);
 
     // Make container for all weights
     int nweights = splwrite->GetNWeights();
     // int npar = splwrite->GetNPars();
     double* weightcont = new double[nweights];
 
     int lasttime = time(NULL);
 
     // Could reorder this to save the weightconts in order instead of reconfiguring per event.
     // Loop over all events and fill the TTree
     while (nuisevent) {
 
 
       // Calculate the weights for each parameter set
       splwrite->GetWeightsForEvent(nuisevent, weightcont);
 
       // Save everything
 
       eventtree->Fill();
       weighttree->Fill();
 
 
       // Logging
       if (i % countwidth == 0) {
 
         std::ostringstream timestring;
         int timeelapsed = time(NULL) - lasttime;
         if (i != 0 and timeelapsed) {
           lasttime = time(NULL);
 
           int eventsleft = nevents - i;
           float speed = float(countwidth) / float(timeelapsed);
           float proj = (float(eventsleft) / float(speed)) / 60 / 60;
           timestring << proj << " hours remaining.";
 
         }
         LOG(REC) << "Saved " << i << "/" << nevents << " nuisance spline weights. " << timestring.str() << std::endl;
       }
 
       // Iterate
       i++;
       nuisevent = input->NextNuisanceEvent();
     }
 
     // at end of the chunk, when all sets have been done
     // loop over the container and fill weights to ttree
 
     outputfile->cd();
     eventtree->Write();
     weighttree->Write();
     input->GetFluxHistogram()->Write("nuisance_fluxhist");
     input->GetEventHistogram()->Write("nuisance_eventhist");
     splwrite->Write("spline_reader");
     outputfile->Close();
 
     // Close Output
     outputfile->Close();
 
     // Delete Inputs
     delete input;
   }
 
   // remove Keys
   eventkeys.clear();
 
 }
 
 
 
 
 //*************************************
 void SplineRoutines::GenerateEventSplines() {
 //*************************************
   if (fRW) delete fRW;
   SetupRWEngine();
 
   // Setup the spline reader
   SplineWriter* splwrite = new SplineWriter(fRW);
   std::vector<nuiskey> splinekeys = Config::QueryKeys("spline");
 
   // Add splines to splinewriter
   for (std::vector<nuiskey>::iterator iter = splinekeys.begin();
        iter != splinekeys.end(); iter++) {
     nuiskey splkey = (*iter);
 
     // Add Spline Info To Reader
     splwrite->AddSpline(splkey);
   }
   splwrite->SetupSplineSet();
 
 
   // Make an ugly list for N cores
   int ncores = FitPar::Config().GetParI("NCORES");//omp_get_max_threads();
   std::vector<SplineWriter*> splwriterlist;
 
   for (int i = 0; i < ncores; i++) {
     SplineWriter* tmpwriter = new SplineWriter(fRW);
 
     for (std::vector<nuiskey>::iterator iter = splinekeys.begin();
          iter != splinekeys.end(); iter++) {
       nuiskey splkey = (*iter);
 
       // Add Spline Info To Reader
       tmpwriter->AddSpline(splkey);
     }
     tmpwriter->SetupSplineSet();
 
     splwriterlist.push_back(tmpwriter);
   }
 
 
   // Event Loop
   // Loop over all events and calculate weights for each parameter set.
 
   // Generate a set of nominal events
   // Method, Loop over inputs, create input handler, then create a ttree
   std::vector<nuiskey> eventkeys = Config::QueryKeys("events");
   for (size_t i = 0; i < eventkeys.size(); i++) {
     nuiskey key = eventkeys.at(i);
 
     // Get I/O
     std::string inputfilename  = key.GetS("input");
     if (inputfilename.empty()) {
       ERR(FTL) << "No input given for set of input events!" << std::endl;
       throw;
     }
 
     std::string outputfilename = key.GetS("output");
     if (outputfilename.empty()) {
       outputfilename = inputfilename + ".nuisance.root";
       ERR(FTL) << "No output give for set of output events! Saving to "
                << outputfilename << std::endl;
     }
 
     // Make new outputfile
     TFile* outputfile = new TFile(outputfilename.c_str(), "RECREATE");
     outputfile->cd();
 
     // Make a new input handler
     std::vector<std::string> file_descriptor =
       GeneralUtils::ParseToStr(inputfilename, ":");
     if (file_descriptor.size() != 2) {
       ERR(FTL) << "File descriptor had no filetype declaration: \"" << inputfilename
                << "\". expected \"FILETYPE:file.root\"" << std::endl;
       throw;
     }
     InputUtils::InputType inptype =
       InputUtils::ParseInputType(file_descriptor[0]);
 
     InputHandlerBase* input = InputUtils::CreateInputHandler("eventsaver", inptype, file_descriptor[1]);
 
     // Get info from inputhandler
     int nevents = input->GetNEvents();
     int countwidth = (nevents / 1000);
     FitEvent* nuisevent = input->FirstNuisanceEvent();
 
     // Setup a TTree to save the event
     outputfile->cd();
     TTree* eventtree = new TTree("nuisance_events", "nuisance_events");
 
     // Add a flag that allows just splines to be saved.
     nuisevent->AddBranchesToTree(eventtree);
 
     // Save the spline reader
     splwrite->Write("spline_reader");
 
     // Setup the spline TTree
     TTree* weighttree = new TTree("weight_tree", "weight_tree");
     splwrite->AddWeightsToTree(weighttree);
 
     // Make container for all weights
     int nweights = splwrite->GetNWeights();
     double** weightcont = new double*[nevents];
     for (int k = 0; k < nevents; k++) {
       weightcont[k] = new double[nweights];
     }
 
     int npar = splwrite->GetNPars();
 
 
     int lasttime = time(NULL);
 
     // Could reorder this to save the weightconts in order instead of reconfiguring per event.
     // Loop over all events and fill the TTree
     while (nuisevent) {
 
       // std::cout << "Fitting event " << i << std::endl;
       // Calculate the weights for each parameter set
       // splwrite->FitSplinesForEvent(nuisevent);
       splwrite->GetWeightsForEvent(nuisevent, weightcont[i]);
       bool hasresponse = false;
       for (int j = 0; j < nweights; j++) {
 
         if (weightcont[i][j] != 1.0) {
           //    std::cout << "Non Zero Weight at " << i << " " << j << std::endl;
           hasresponse = true;
         } else {
           //    std::cout << "Empty Weight at " << i << " " << j << std::endl;
         }
       }
       if (!hasresponse) {
         //  std::cout << "Deleting flat response " << nuisevent->Mode << std::endl;
         delete weightcont[i];
         weightcont[i] = NULL;
       }
 
       // Save everything
       eventtree->Fill();
       weighttree->Fill();
       // splinetree->Fill();
 
       // nuisevent->Print();
       // std::cout << "Done with event " << i << std::endl;
 
       // Push weight sets into a the array
 
       // sleep(4);
       // Logging
       if (i % countwidth == 0) {
 
         std::ostringstream timestring;
         int timeelapsed = time(NULL) - lasttime;
         if (i != 0 and timeelapsed) {
           lasttime = time(NULL);
 
           int eventsleft = nevents - i;
           float speed = float(countwidth) / float(timeelapsed);
           float proj = (float(eventsleft) / float(speed)) / 60 / 60;
           timestring << proj << " hours remaining.";
 
         }
         LOG(REC) << "Saved " << i << "/" << nevents << " nuisance spline weights. " << timestring.str() << std::endl;
       }
 
       // Iterate
       i++;
       nuisevent = input->NextNuisanceEvent();
     }
 
     outputfile->cd();
     eventtree->Write();
     weighttree->Write();
     input->GetFluxHistogram()->Write("nuisance_fluxhist");
     input->GetEventHistogram()->Write("nuisance_eventhist");
     outputfile->Close();
 
     outputfile = new TFile(outputfilename.c_str(), "UPDATE");
     outputfile->cd();
 
     weighttree = (TTree*) outputfile->Get("weight_tree");
 //    splwrite->ReadWeightsFromTree(weighttree);
 
 
     // Divide weights container into Ncores.
     // Parrallelise this loop checking for what core we are on.
     // for (int i = 0; i < nevents; i++){
     // splwriterlist[int(i / (nevents/4))]->FitSplinesForEvent(coeff);
     // }
 
     // // Now loop over weights tree
     // for (int i = 0; i < weighttree->GetEntries(); i++) {
     //   weighttree->GetEntry(i);
     //   splwrite->FitSplinesForEvent();
     //   splinetree->Fill();
 
     //   if (i % countwidth == 0) {
 
     //     std::ostringstream timestring;
     //     int timeelapsed = time(NULL) - lasttime;
     //     if (i != 0 and timeelapsed) {
     //       lasttime = time(NULL);
 
     //       int eventsleft = nevents - i;
     //       float speed = float(countwidth) / float(timeelapsed);
     //       float proj = (float(eventsleft) / float(speed)) / 60 / 60;
     //       timestring << proj << " hours remaining.";
 
     //     }
     //     LOG(REC) << "Built " << i << "/" << nevents << " nuisance spline events. " << timestring.str() << std::endl;
     //   }
     // }
 
     // Get Splines
     float** allcoeff = new float*[nevents];
     for (int k = 0; k < nevents; k++) {
       allcoeff[k] = new float[npar];
     }
 
 
 
     //    #pragma omp parallel for num_threads(ncores)
     for (int i = 0; i < nevents; i++) {
 
       //#pragma omp atomic
       //      printf("Using Thread %d to build event %d \n", int(omp_get_thread_num()), (int)i );
       //      std::cout<< " -> Writer = " << splwriterlist[ i / (nevents/ncores) ] << std::endl;
 
       //      #pragma omp atomic
       if (weightcont[i]) {
         splwriterlist[ int(omp_get_thread_num()) ]->FitSplinesForEvent(weightcont[i], allcoeff[i]);
       } else {
         for (int j = 0; j < npar; j++) {
           allcoeff[i][j] = float(0.0);
         }
       }
 
       //      splwrite->FitSplinesForEvent(weightcont[i], allcoeff[i]);
 
 
       if (i % 500 == 0) {
 
         if (LOG_LEVEL(REC)) {
           printf("Using Thread %d to build event %d \n", int(omp_get_thread_num()), (int)i );
         }
       }
       /*
 
         std::ostringstream timestring;
         int timeelapsed = time(NULL) - lasttime;
         if (i != 0 and timeelapsed) {
           lasttime = time(NULL);
 
           int eventsleft = nevents - i;
           float speed = float(countwidth) / float(timeelapsed);
           float proj = (float(eventsleft) / float(speed)) / 60 / 60;
           timestring << proj << " hours remaining.";
       timestring << " Using Writer at " << i / (nevents/ncores) << " = " << splwriterlist[ i / (nevents/ncores) ] << std::endl;
 
         }
         LOG(REC) << "Built " << i << "/" << nevents << " nuisance spline events. " << timestring.str() << std::endl;
       }
       */
     }
 
     // Save Splines into TTree
     float* coeff = new float[npar];
     outputfile->cd();
     TTree* splinetree = new TTree("spline_tree", "spline_tree");
 
     splinetree->Branch("SplineCoeff", coeff, Form("SplineCoeff[%d]/F", npar));
 
     std::cout << "Saving to the allcoeff" << std::endl;
     for (int k = 0; k < nevents; k++) {
       for (int l = 0; l < npar; l++) {
         coeff[l] = allcoeff[k][l];
       }
       std::cout << "Coeff 0, 1, 2 = " << coeff[0] << " " << coeff[1] << " " << coeff[2] << std::endl;
       splinetree->Fill();
     }
 
     // Save flux and close file
     outputfile->cd();
     splinetree->Write();
 
     // Delete the container.
     for (int k = 0; k < nevents; k++) {
       delete weightcont[k];
     }
     delete weightcont;
     delete coeff;
 
     // Close Output
     outputfile->Close();
 
     // Delete Inputs
     delete input;
   }
 
   // remove Keys
   eventkeys.clear();
 
 }
 
 
 
 //*************************************
 void SplineRoutines::BuildEventSplines(int procchunk) {
 //*************************************
   if (fRW) delete fRW;
   SetupRWEngine();
 
   // Setup the spline reader
   SplineWriter* splwrite = new SplineWriter(fRW);
   std::vector<nuiskey> splinekeys = Config::QueryKeys("spline");
 
   // Add splines to splinewriter
   for (std::vector<nuiskey>::iterator iter = splinekeys.begin();
        iter != splinekeys.end(); iter++) {
     nuiskey splkey = (*iter);
 
     // Add Spline Info To Reader
     splwrite->AddSpline(splkey);
   }
   splwrite->SetupSplineSet();
 
 
   // Make an ugly list for N cores
   int ncores = FitPar::Config().GetParI("spline_cores");//omp_get_max_threads();
   if (ncores > omp_get_max_threads()) ncores = omp_get_max_threads();
   if (ncores <= 0) ncores = 1;
 
   std::vector<SplineWriter*> splwriterlist;
 
   for (int i = 0; i < ncores; i++) {
     SplineWriter* tmpwriter = new SplineWriter(fRW);
 
     for (std::vector<nuiskey>::iterator iter = splinekeys.begin();
          iter != splinekeys.end(); iter++) {
       nuiskey splkey = (*iter);
 
       // Add Spline Info To Reader
       tmpwriter->AddSpline(splkey);
     }
     tmpwriter->SetupSplineSet();
 
     splwriterlist.push_back(tmpwriter);
   }
 
 
   // Event Loop
   // Loop over all events and calculate weights for each parameter set.
 
   // Generate a set of nominal events
   // Method, Loop over inputs, create input handler, then create a ttree
   std::vector<nuiskey> eventkeys = Config::QueryKeys("events");
   for (size_t i = 0; i < eventkeys.size(); i++) {
     nuiskey key = eventkeys.at(i);
 
     // Get I/O
     std::string inputfilename  = key.GetS("input");
     if (inputfilename.empty()) {
       ERR(FTL) << "No input given for set of input events!" << std::endl;
       throw;
     }
 
     std::string outputfilename = key.GetS("output");
     if (outputfilename.empty()) {
       outputfilename = inputfilename + ".nuisance.root";
       ERR(FTL) << "No output give for set of output events! Saving to "
                << outputfilename << std::endl;
     }
 
     // Make new outputfile
     TFile* outputfile;
     if (procchunk == -1) outputfile = new TFile(outputfilename.c_str(), "RECREATE");
     else  outputfile = new TFile((outputfilename + std::string(Form(".coeffchunk_%d.root", procchunk))).c_str(), "RECREATE");
 
     outputfile->cd();
 
     // Get Weights File
     TFile* weightsfile = new TFile((outputfilename + ".weights.root").c_str(), "READ");
     TTree* weighttree = (TTree*) weightsfile->Get("weight_tree");
 
     // Get SPLWRite Info
     //splwrite->ReadWeightsFromTree(weighttree);
     int nevents = weighttree->GetEntries();
     // int countwidth = (nevents / 1000);
     int nweights = splwrite->GetNWeights();
     int npar = splwrite->GetNPars();
 
     // Access Weights
     double* eventweights = new double[nweights];
     weighttree->SetBranchAddress("SplineWeights", eventweights);
 
 
     // Make counter
     // int lasttime = time(NULL);
 
 
     // Setup Splines To Be Saved into TTree
     outputfile->cd();
     TTree* splinetree = new TTree("spline_tree", "spline_tree");
 
     float* coeff = new float[npar];
     splinetree->Branch("SplineCoeff", coeff, Form("SplineCoeff[%d]/F", npar));
 
 
     // Load N Chunks of the Weights into Memory
     // Split into N processing chunks
     int nchunks = FitPar::Config().GetParI("spline_chunks");
     if (nchunks <= 0) nchunks = 1;
     if (nchunks >= nevents / 2) nchunks = nevents / 2;
 
     std::cout << "Starting NChunks " << nchunks << std::endl;
     sleep(1);
     for (int ichunk = 0; ichunk < nchunks; ichunk++) {
 
       // Skip to only do one processing chunk
       if (procchunk != -1 and procchunk != ichunk) continue;
 
       LOG(FIT) << "On Processing Chunk " << ichunk << std::endl;
       int neventsinchunk   = nevents / nchunks;
       int loweventinchunk  = neventsinchunk * ichunk;
       // int higheventinchunk = neventsinchunk * (ichunk + 1);
 
 
       // Build Chunk Containers for Event Weights
       double** weightcont = new double*[nevents];
       float** allcoeff = new float*[nevents];
 
       // Load Chunks into Containers
       for (int k = 0; k < neventsinchunk; k++) {
         weighttree->GetEntry(loweventinchunk + k);
 
         weightcont[k] = new double[nweights];
         allcoeff[k] = new float[npar];
 
         bool hasresponse = false;
         for (int j = 0; j < nweights; j++) {
           weightcont[k][j] = eventweights[j];
           if (eventweights[j] != 1.0) hasresponse = true;
         }
         if (!hasresponse) delete weightcont[k];
       }
 
 
       // Loop over ncores and process chunks
       //      #pragma omp parallel for num_threads(ncores)
       for (int k = 0; k < neventsinchunk; k++) {
 
         if (weightcont[k]) {
           splwriterlist[ int(omp_get_thread_num()) ]->FitSplinesForEvent(weightcont[k], allcoeff[k]);
         } else {
           for (int j = 0; j < npar; j++) {
             allcoeff[k][j] = float(0.0);
           }
         }
 
         if (k + loweventinchunk % 500 == 0) {
 
           if (LOG_LEVEL(REC)) {
             printf("Using Thread %d to build event %d in chunk %d \n", int(omp_get_thread_num()), (int) loweventinchunk + k, ichunk );
           }
 
         }
       }
 
       // Save Coeff To Tree
       std::cout << "Saving coeffs to Tree in Chunk " << ichunk << std::endl;
       for (int k = 0; k < neventsinchunk; k++) {
         for (int l = 0; l < npar; l++) {
           coeff[l] = allcoeff[k][l];
         }
         // std::cout << "Coeff 0, 1, 2 = " << coeff[0] << " " << coeff[1] << " " << coeff[2] << std::endl;
         splinetree->Fill();
       }
 
       // Delete the container.
       for (int k = 0; k < neventsinchunk; k++) {
         if (weightcont[k]) delete weightcont[k];
         if (allcoeff[k]) delete allcoeff[k];
       }
       delete allcoeff;
       delete weightcont;
     }
     // Save flux and close file
     outputfile->cd();
     splinetree->Write();
 
 
     if (procchunk == -1 or procchunk == 0) {
       outputfile->cd();
       splwrite->Write("spline_reader");
 
       TTree* nuisanceevents = (TTree*) weightsfile->Get("nuisance_events");
       nuisanceevents->CloneTree()->Write();
       weighttree->CloneTree()->Write();
 
       TH1D* nuisance_fluxhist = (TH1D*) weightsfile->Get("nuisance_fluxhist");
       TH1D* nuisance_eventhist = (TH1D*) weightsfile->Get("nuisance_eventhist");
       nuisance_fluxhist->Write("nuisance_fluxhist");
       nuisance_eventhist->Write("nuisance_eventhist");
     }
     weightsfile->Close();
 
 
     // Add option to build seperate chunks
 
     // Close Output
     outputfile->Close();
   }
 
   // remove Keys
   eventkeys.clear();
 
 }
 
 void SplineRoutines::MergeEventSplinesChunks() {
 
   if (fRW) delete fRW;
   SetupRWEngine();
 
   // Setup the spline reader
   SplineWriter* splwrite = new SplineWriter(fRW);
   std::vector<nuiskey> splinekeys = Config::QueryKeys("spline");
 
   // Add splines to splinewriter
   for (std::vector<nuiskey>::iterator iter = splinekeys.begin();
        iter != splinekeys.end(); iter++) {
     nuiskey splkey = (*iter);
 
     // Add Spline Info To Reader
     splwrite->AddSpline(splkey);
   }
   splwrite->SetupSplineSet();
 
   std::vector<nuiskey> eventkeys = Config::QueryKeys("events");
   for (size_t i = 0; i < eventkeys.size(); i++) {
     nuiskey key = eventkeys.at(i);
 
     // Get I/O
     std::string inputfilename  = key.GetS("input");
     if (inputfilename.empty()) {
       ERR(FTL) << "No input given for set of input events!" << std::endl;
       throw;
     }
 
     std::string outputfilename = key.GetS("output");
     if (outputfilename.empty()) {
       outputfilename = inputfilename + ".nuisance.root";
       ERR(FTL) << "No output give for set of output events! Saving to "
                << outputfilename << std::endl;
     }
 
     // Make new outputfile
     TFile* outputfile = new TFile(outputfilename.c_str(), "RECREATE");
     outputfile->cd();
 
     // Get Weights File
     TFile* weightsfile = new TFile((outputfilename + ".weights.root").c_str(), "READ");
     TTree* weighttree = (TTree*) weightsfile->Get("weight_tree");
 
     // Get SPLWRite Info
     //splwrite->ReadWeightsFromTree(weighttree);
     int nevents = weighttree->GetEntries();
     // int countwidth = (nevents / 1000);
     // int nweights = splwrite->GetNWeights();
     int npar = splwrite->GetNPars();
 
     // Make counter
     // int lasttime = time(NULL);
 
 
     // Setup Splines To Be Saved into TTree
     outputfile->cd();
     TTree* splinetree = new TTree("spline_tree", "spline_tree");
 
     float* coeff = new float[npar];
     splinetree->Branch("SplineCoeff", coeff, Form("SplineCoeff[%d]/F", npar));
 
 
     // Load N Chunks of the Weights into Memory
     // Split into N processing chunks
     int nchunks = FitPar::Config().GetParI("spline_chunks");
     if (nchunks <= 0) nchunks = 1;
     if (nchunks >= nevents / 2) nchunks = nevents / 2;
     int neventsinchunk   = nevents / nchunks;
 
 
     for (int ichunk = 0; ichunk < nchunks; ichunk++) {
 
       // Get Output File
       TFile* chunkfile = new TFile( (outputfilename + std::string(Form(".coeffchunk_%d.root", ichunk))).c_str() );
 
       // Get TTree for spline coeffchunk
       TTree* splinetreechunk = (TTree*) chunkfile->Get("spline_tree");
 
       // Set Branch Address to coeffchunk
       float* coeffchunk = new float[npar];
       splinetreechunk->SetBranchAddress("SplineCoeff", coeffchunk);
 
       // Loop over nevents in chunk
       for (int k = 0; k < neventsinchunk; k++) {
         splinetreechunk->GetEntry(k);
         for (int j = 0; j < npar; j++) {
           coeff[j] = coeffchunk[j];
         }
         splinetree->Fill();
       }
 
       // Close up
       chunkfile->Close();
       delete coeffchunk;
 
       std::cout << "Merged chunk " << ichunk << std::endl;
 
     }
 
     // Save flux and close file
     outputfile->cd();
     splinetree->Write();
 
     outputfile->cd();
     splwrite->Write("spline_reader");
 
     TTree* nuisanceevents = (TTree*) weightsfile->Get("nuisance_events");
     nuisanceevents->CloneTree()->Write();
     weighttree->CloneTree()->Write();
 
     TH1D* nuisance_fluxhist = (TH1D*) weightsfile->Get("nuisance_fluxhist");
     TH1D* nuisance_eventhist = (TH1D*) weightsfile->Get("nuisance_eventhist");
     nuisance_fluxhist->Write("nuisance_fluxhist");
     nuisance_eventhist->Write("nuisance_eventhist");
 
     weightsfile->Close();
 
 
     // Add option to build seperate chunks
 
     // Close Output
     outputfile->Close();
   }
 
   // remove Keys
   eventkeys.clear();
 
 }
 
 // void SplineRoutines::BuildSplineChunk(){
 //}
 
 // void SplineRoutines::MergeSplineChunks(){
 //}
 
 
 //*************************************
 void SplineRoutines::MergeSplines() {
 //*************************************
   // Loop over all 'splinemerge' keys.
   // Add them to the Merger.
   // Call setup splines.
 
   // Get the key with eventinput
   // - remaining keys should have splineinput
   // - Loop over number of entries.
   // - FillEntry in merger.
   // - Fill NUISANCEEvent into a new TTree.
 
   SplineMerger* splmerge = new SplineMerger();
   std::vector<nuiskey> splinekeys = Config::QueryKeys("splinemerge");
   for (std::vector<nuiskey>::iterator iter = splinekeys.begin();
        iter != splinekeys.end(); iter++) {
     nuiskey splkey = (*iter);
 
     TFile* infile = new TFile(splkey.GetS("input").c_str(), "READ");
     splmerge->AddSplineSetFromFile(infile);
 
   }
   splmerge->SetupSplineSet();
 
   // Now get Event File
   std::vector<nuiskey> eventkeys = Config::QueryKeys("eventmerge");
   nuiskey key = eventkeys[0];
 
   std::string inputfilename  = key.GetS("input");
 
   // Make a new input handler
   std::vector<std::string> file_descriptor =
     GeneralUtils::ParseToStr(inputfilename, ":");
   if (file_descriptor.size() != 2) {
     ERR(FTL) << "File descriptor had no filetype declaration: \"" << inputfilename
              << "\". expected \"FILETYPE:file.root\"" << std::endl;
     throw;
   }
   InputUtils::InputType inptype =
     InputUtils::ParseInputType(file_descriptor[0]);
 
   InputHandlerBase* input = InputUtils::CreateInputHandler("eventsaver", inptype, file_descriptor[1]);
 
   std::string outputfilename = key.GetS("output");
   if (outputfilename.empty()) {
     outputfilename = inputfilename + ".nuisance.root";
     ERR(FTL) << "No output give for set of output events! Saving to "
              << outputfilename << std::endl;
   }
 
   // Make new outputfile
   TFile* outputfile = new TFile(outputfilename.c_str(), "RECREATE");
   outputfile->cd();
 
 
   // Get info from inputhandler
   int nevents = input->GetNEvents();
   int countwidth = (nevents / 1000);
   FitEvent* nuisevent = input->FirstNuisanceEvent();
 
   // Setup a TTree to save the event
   outputfile->cd();
   TTree* eventtree = new TTree("nuisance_events", "nuisance_events");
 
   // Add a flag that allows just splines to be saved.
   nuisevent->AddBranchesToTree(eventtree);
 
   // Save the spline reader
   splmerge->Write("spline_reader");
 
   // Setup the spline TTree
   TTree* splinetree = new TTree("spline_tree", "spline_tree");
   splmerge->AddCoefficientsToTree(splinetree);
 
   int lasttime = time(NULL);
   int i = 0;
   // Loop over all events and fill the TTree
   while (nuisevent) {
 
     // Calculate the weights for each parameter set
     splmerge->FillMergedSplines(i);
 
     // Save everything
     eventtree->Fill();
     splinetree->Fill();
 
     // Logging
     if (i % countwidth == 0) {
 
       std::ostringstream timestring;
       int timeelapsed = time(NULL) - lasttime;
       if (i != 0 and timeelapsed) {
         lasttime = time(NULL);
 
         int eventsleft = nevents - i;
         float speed = float(countwidth) / float(timeelapsed);
         float proj = (float(eventsleft) / float(speed)) / 60 / 60;
         timestring << proj << " hours remaining.";
 
       }
       LOG(REC) << "Saved " << i << "/" << nevents << " nuisance spline events. " << timestring.str() << std::endl;
     }
 
     // Iterate
     i++;
     nuisevent = input->NextNuisanceEvent();
   }
 
   // Save flux and close file
   outputfile->cd();
   eventtree->Write();
   splinetree->Write();
 
   input->GetFluxHistogram()->Write("nuisance_fluxhist");
   input->GetEventHistogram()->Write("nuisance_eventhist");
 
   // Close Output
   outputfile->Close();
 
   // Delete Inputs
   delete input;
 }
 
 
 //*************************************
 void SplineRoutines::TestSplines_1DEventScan() {
 //*************************************
 
   // Setup RW Engine
   if (fRW) delete fRW;
   SetupRWEngine();
 
   // Make a spline RW Engine too.
   FitWeight* splweight = new FitWeight("splinerwaweight");
   // std::vector<nuiskey> splinekeys    = Config::QueryKeys("spline");
   std::vector<nuiskey> parameterkeys = Config::QueryKeys("parameter");
   TH1D* parhisttemplate = new TH1D("parhist", "parhist", parameterkeys.size(), 0.0, float(parameterkeys.size()));
 
   // Add Parameters
   for (size_t i = 0; i < parameterkeys.size(); i++) {
     nuiskey key = parameterkeys[i];
 
     std::string parname = key.GetS("name");
     std::string partype = key.GetS("type");
     double nom = key.GetD("nominal");
 
     parhisttemplate->SetBinContent(i + 1, nom);
     parhisttemplate->GetXaxis()->SetBinLabel(i + 1, parname.c_str());
 
     splweight->IncludeDial( key.GetS("name"),
                             kSPLINEPARAMETER, nom);
     splweight->SetDialValue( key.GetS("name"), key.GetD("nominal") );
 
   }
   splweight->Reconfigure();
 
   // Make a high resolution spline set.
   std::vector<double> nomvals = fRW->GetDialValues();
   // int testres = FitPar::Config().GetParI("spline_test_resolution");
 
   std::vector< std::vector<double> > scanparset_vals;
   std::vector< TH1D* > scanparset_hists;
 
   // Loop over all params
   // Add Parameters
   for (size_t i = 0; i < parameterkeys.size(); i++) {
     nuiskey key = parameterkeys[i];
 
     // Get Par Name
     std::string name = key.GetS("name");
 
     if (!key.Has("low") or !key.Has("high") or !key.Has("step")) {
       continue;
     }
 
     // Push Back Scan
     double low  = key.GetD("low");
     double high = key.GetD("high");
     double cur = low;
     double step = key.GetD("step");
 
     while (cur <= high) {
 
       // Make new set
       std::vector<double> newvals = nomvals;
       newvals[i] = cur;
 
       // Add to vects
       scanparset_vals.push_back(newvals);
 
       TH1D* parhist = (TH1D*)parhisttemplate->Clone();
       for (size_t j = 0; j < newvals.size(); j++) {
         parhist->SetBinContent(j + 1, newvals[j]);
       }
       scanparset_hists.push_back(parhist);
 
 
       // Move to next one
       cur += step;
     }
   }
 
   // Print out the parameter set to test
   for (uint i = 0; i < scanparset_vals.size(); i++) {
     std::cout << "Parset " << i;
     for (uint j = 0 ; j < scanparset_vals[i].size(); j++) {
       std::cout << " " << scanparset_vals[i][j];
     }
     std::cout << std::endl;
   }
   
   // Weight holders
   double* rawweights = new double[scanparset_vals.size()];
   double* splweights = new double[scanparset_vals.size()];
   double* difweights = new double[scanparset_vals.size()];
   int nweights = scanparset_vals.size();
   // int NParSets = scanparset_vals.size();
 
   // Loop over all event I/O
   std::vector<nuiskey> eventkeys = Config::QueryKeys("events");
   for (size_t i = 0; i < eventkeys.size(); i++) {
     nuiskey key = eventkeys.at(i);
 
     // Get I/O
     std::string inputfilename  = key.GetS("input");
     if (inputfilename.empty()) {
       ERR(FTL) << "No input given for set of input events!" << std::endl;
       throw;
     }
 
     std::string outputfilename = key.GetS("output");
     if (outputfilename.empty()) {
       outputfilename = inputfilename + ".nuisance.root";
       ERR(FTL) << "No output give for set of output events! Saving to "
                << outputfilename << std::endl;
     }
 
     // Make a new input handler
     std::vector<std::string> file_descriptor =
       GeneralUtils::ParseToStr(inputfilename, ":");
     if (file_descriptor.size() != 2) {
       ERR(FTL) << "File descriptor had no filetype declaration: \"" << inputfilename
                << "\". expected \"FILETYPE:file.root\"" << std::endl;
       throw;
     }
     InputUtils::InputType inptype =
       InputUtils::ParseInputType(file_descriptor[0]);
 
 
     // Make handlers for input and output
     InputHandlerBase* input  = InputUtils::CreateInputHandler("rawevents", inptype, file_descriptor[1]);
     InputHandlerBase* output =  InputUtils::CreateInputHandler("splineevents", InputUtils::kEVSPLN_Input, outputfilename);
 
     // Get Base Events for each case.
     FitEvent* rawevent = input->FirstNuisanceEvent();
     FitEvent* splevent = output->FirstNuisanceEvent();
 
 
     // Setup outputfile
     std::string outputtest = outputfilename + ".splinetest.1DEventScan.root";
     TFile* outputtestfile = new TFile(outputtest.c_str(), "RECREATE");
     outputtestfile->cd();
 
     // Save Parameter Sets
     for (size_t i = 0; i < scanparset_hists.size(); i++) {
       scanparset_hists[i]->Write(Form("Paramater_Set_%i", (int)i));
     }
 
     // Save a TTree of weights and differences.
     TTree* weighttree = new TTree("weightscan", "weightscan");
 
     // Make a branch for each weight set
     for (size_t i = 0; i < scanparset_hists.size(); i++) {
       weighttree->Branch(Form("RawWeights_Set_%i", (int)i), &rawweights[i], Form("RawWeights_Set_%i/D", (int)i) );
       weighttree->Branch(Form("SplineWeights_Set_%i", (int)i), &splweights[i], Form("SplineWeights_Set_%i/D", (int)i) );
       weighttree->Branch(Form("DifWeights_Set_%i", (int)i), &difweights[i], Form("DifWeights_Set_%i/D", (int)i) );
 
     }
 
     // Count
     // int i = 0;
     int nevents = input->GetNEvents();
     int lasttime = time(NULL);
 
     // Load N Chunks of the Weights into Memory
     // Split into N processing chunks
     int nchunks = FitPar::Config().GetParI("spline_chunks");
     if (nchunks <= 0) nchunks = 1;
     if (nchunks >= nevents / 2) nchunks = nevents / 2;
     
     std::cout << "Starting NChunks " << nchunks << std::endl;
     for (int ichunk = 0; ichunk < nchunks; ichunk++) {
 
       // Skip to only do one processing chunk
       //      if (procchunk != -1 and procchunk != ichunk) continue;
 
       LOG(FIT) << "On Processing Chunk " << ichunk << std::endl;
       int neventsinchunk   = nevents / nchunks;
       int loweventinchunk  = neventsinchunk * ichunk;
       // int higheventinchunk = neventsinchunk * (ichunk + 1);
 
       double** allrawweights = new double*[neventsinchunk];
       double** allsplweights = new double*[neventsinchunk];
       double** alldifweights = new double*[neventsinchunk];
       for (int k = 0; k < neventsinchunk; k++){
         allrawweights[k] = new double[nweights];
 	allsplweights[k] = new double[nweights];
 	alldifweights[k] = new double[nweights];
       }
 
       // Start Set Processing Here.
       for (int iset = 0; iset < nweights; iset++) {
 
 	// Reconfigure
         fRW->SetAllDials(&scanparset_vals[iset][0], scanparset_vals[iset].size());
         fRW->Reconfigure();
 
         // Reconfigure spline RW
         splweight->SetAllDials(&scanparset_vals[iset][0], scanparset_vals[iset].size());
         splweight->Reconfigure();
 
         splevent->fSplineRead->SetNeedsReconfigure(true);
 
         // Could reorder this to save the weightconts in order instead of reconfiguring per event.
         // Loop over all events and fill the TTree
         for (int i = 0; i < neventsinchunk; i++){
 
 	  rawevent = input->GetNuisanceEvent(i+loweventinchunk);
 	  splevent = output->GetNuisanceEvent(i+loweventinchunk);
 
 	  allrawweights[i][iset] = fRW->CalcWeight(rawevent);
 	  allsplweights[i][iset] = splweight->CalcWeight(splevent);
 	  alldifweights[i][iset] = allsplweights[i][iset] - allrawweights[i][iset];
         }
 	
 	std::ostringstream timestring;
         int timeelapsed = time(NULL) - lasttime;
         if  (timeelapsed) {
           lasttime = time(NULL);
 
           int setsleft = (nweights-iset-1) + (nweights * (nchunks - ichunk - 1));
           float proj = (float(setsleft) *timeelapsed) / 60 / 60;
           timestring << setsleft << " sets remaining. Last one took " << timeelapsed << ". " << proj << " hours remaining.";
 
         }
 
 	LOG(REC) << "Processed Set " << iset << "/" << nweights <<" in chunk " << ichunk << "/" << nchunks << " " << timestring.str() << std::endl;
 
       }
 
       // Fill weights for this chunk into the TTree
       for (int k = 0; k < neventsinchunk; k++){
 	for (int l = 0; l < nweights; l++){
 	  rawweights[l] = allrawweights[k][l];
 	  splweights[l] = allsplweights[k][l];
 	  difweights[l] = alldifweights[k][l];
 	}
         weighttree->Fill();
       }
     }
 
 
     // Loop over nchunks
 
     // Loop over parameter sets
     // Set All Dials and reconfigure
 
     // Loop over events in chunk
     // Fill Chunkweightcontainers
     
     // Once all dials are done, fill the weight tree
     
     // Iterator to next chunk
     
 
     outputtestfile->cd();
     weighttree->Write();
     outputtestfile->Close();
   }
 }
 
   
 
 
 
 
 /*
   // Make a high resolution spline set.
   std::vector<double> nomvals = fRW->GetDialValues();
   int testres = FitPar::Config().GetParI("spline_test_resolution");
 
   std::vector< std::vector<double> > scanparset_vals;
   std::vector< TH1D* > scanparset_hists;
 
   // Loop over all params
   // Add Parameters
   for (size_t i = 0; i < parameterkeys.size(); i++) {
     nuiskey key = parameterkeys[i];
 
     // Get Par Name
     std::string name = key.GetS("name");
 
     if (!key.Has("low") or !key.Has("high") or !key.Has("step")) {
       continue;
     }
 
     // Push Back Scan
     double low  = key.GetD("low");
     double high = key.GetD("high");
     double cur = low;
     double step = key.GetD("step");
 
     while (cur <= high) {
 
       // Make new set
       std::vector<double> newvals = nomvals;
       newvals[i] = cur;
 
       // Add to vects
       scanparset_vals.push_back(newvals);
 
       TH1D* parhist = (TH1D*)parhisttemplate->Clone();
       for (size_t j = 0; j < newvals.size(); j++) {
         parhist->SetBinContent(j + 1, newvals[j]);
       }
       scanparset_hists.push_back(parhist);
 
 
       // Move to next one
       cur += step;
     }
   }
 
   // Print out the parameter set to test
   for (int i = 0; i < scanparset_vals.size(); i++) {
     std::cout << "Parset " << i;
     for (int j = 0 ; j < scanparset_vals[i].size(); j++) {
       std::cout << " " << scanparset_vals[i][j];
     }
     std::cout << std::endl;
   }
 
 
   // Weight holders
   double* rawweights = new double[scanparset_vals.size()];
   double* splweights = new double[scanparset_vals.size()];
   double* difweights = new double[scanparset_vals.size()];
 
   int NParSets = scanparset_vals.size();
 
   // Loop over all event I/O
   std::vector<nuiskey> eventkeys = Config::QueryKeys("events");
   for (size_t i = 0; i < eventkeys.size(); i++) {
     nuiskey key = eventkeys.at(i);
 
     // Get I/O
     std::string inputfilename  = key.GetS("input");
     if (inputfilename.empty()) {
       ERR(FTL) << "No input given for set of input events!" << std::endl;
       throw;
     }
 
     std::string outputfilename = key.GetS("output");
     if (outputfilename.empty()) {
       outputfilename = inputfilename + ".nuisance.root";
       ERR(FTL) << "No output give for set of output events! Saving to "
                << outputfilename << std::endl;
     }
 
     // Make a new input handler
     std::vector<std::string> file_descriptor =
       GeneralUtils::ParseToStr(inputfilename, ":");
     if (file_descriptor.size() != 2) {
       ERR(FTL) << "File descriptor had no filetype declaration: \"" << inputfilename
                << "\". expected \"FILETYPE:file.root\"" << std::endl;
       throw;
     }
     InputUtils::InputType inptype =
       InputUtils::ParseInputType(file_descriptor[0]);
 
 
     // Make handlers for input and output
     InputHandlerBase* input  = InputUtils::CreateInputHandler("rawevents", inptype, file_descriptor[1]);
     InputHandlerBase* output =  InputUtils::CreateInputHandler("splineevents", InputUtils::kEVSPLN_Input, outputfilename);
 
     // Get Base Events for each case.
     FitEvent* rawevent = input->FirstNuisanceEvent();
     FitEvent* splevent = output->FirstNuisanceEvent();
 
 
     // Setup outputfile
     std::string outputtest = outputfilename + ".splinetest.1DEventScan.root";
     TFile* outputtestfile = new TFile(outputtest.c_str(), "RECREATE");
     outputtestfile->cd();
 
     // Save Parameter Sets
     for (size_t i = 0; i < scanparset_hists.size(); i++) {
       scanparset_hists[i]->Write(Form("Paramater_Set_%i", (int)i));
     }
 
     // Save a TTree of weights and differences.
     TTree* weighttree = new TTree("weightscan", "weightscan");
 
     // Make a branch for each weight set
     for (size_t i = 0; i < scanparset_hists.size(); i++) {
       weighttree->Branch(Form("RawWeights_Set_%i", (int)i), &rawweights[i], Form("RawWeights_Set_%i/D", (int)i) );
       weighttree->Branch(Form("SplineWeights_Set_%i", (int)i), &splweights[i], Form("SplineWeights_Set_%i/D", (int)i) );
       weighttree->Branch(Form("DifWeights_Set_%i", (int)i), &difweights[i], Form("DifWeights_Set_%i/D", (int)i) );
 
     }
 
     // Count
     int i = 0;
     int nevents = input->GetNEvents();
     while (rawevent and splevent) {
 
       // Loop over 1D parameter sets.
       for (size_t j = 0; j < scanparset_vals.size(); j++) {
 
         // Reconfigure
         fRW->SetAllDials(&scanparset_vals[j][0], scanparset_vals[j].size());
         fRW->Reconfigure();
 
         // Reconfigure spline RW
         splweight->SetAllDials(&scanparset_vals[j][0], scanparset_vals[j].size());
         splweight->Reconfigure();
 
         splevent->fSplineRead->SetNeedsReconfigure(true);
 
         // Calc weight for both events
         rawweights[j] = fRW->CalcWeight(rawevent);
         splweights[j] = splweight->CalcWeight(splevent);
         difweights[j] = splweights[j] - rawweights[j];
       }
 
 
       if (i % 1000 == 0) {
         LOG(FIT) << "Processed " << i << "/" << nevents << std::endl;
       }
 
       // Fill Array
       weighttree->Fill();
 
       // Iterate to next event.
       i++;
       rawevent = input->NextNuisanceEvent();
       splevent = output->NextNuisanceEvent();
     }
 
     outputtestfile->cd();
     weighttree->Write();
     outputtestfile->Close();
   }
 }
 
 */
 
 //*************************************
 void SplineRoutines::TestSplines_NDEventThrow() {
 //*************************************
 
   // Setup RW Engine
   if (fRW) delete fRW;
   SetupRWEngine();
 
   // Make a spline RW Engine too.
   FitWeight* splweight = new FitWeight("splinerwaweight");
   std::vector<nuiskey> parameterkeys = Config::QueryKeys("parameter");
   TH1D* parhisttemplate = new TH1D("parhist", "parhist", parameterkeys.size(), 0.0, float(parameterkeys.size()));
 
   // Add Parameters
   for (size_t i = 0; i < parameterkeys.size(); i++) {
     nuiskey key = parameterkeys[i];
 
     std::string parname = key.GetS("name");
     std::string partype = key.GetS("type");
     double nom = key.GetD("nominal");
 
     parhisttemplate->SetBinContent(i + 1, nom);
     parhisttemplate->GetXaxis()->SetBinLabel(i + 1, parname.c_str());
 
     splweight->IncludeDial( key.GetS("name"),
                             kSPLINEPARAMETER, nom);
     splweight->SetDialValue( key.GetS("name"), key.GetD("nominal") );
 
   }
   splweight->Reconfigure();
 
   // Make a high resolution spline set.
   std::vector<double> nomvals = fRW->GetDialValues();
   // int testres = FitPar::Config().GetParI("spline_test_resolution");
 
   std::vector< std::string > scanparset_names;
   std::vector< std::vector<double> > scanparset_vals;
   std::vector< TH1D* > scanparset_hists;
 
   // Loop over all params
   // Add Parameters
   int nthrows = FitPar::Config().GetParI("spline_test_throws");
   for (int i = 0; i < nthrows; i++) {
 
     std::vector<double> newvals = nomvals;
 
     for (size_t j = 0; j < parameterkeys.size(); j++) {
       nuiskey key = parameterkeys[j];
 
       if (!key.Has("low") or !key.Has("high") or !key.Has("step")) {
         continue;
       }
 
       // Push Back Scan
       double low  = key.GetD("low");
       double high = key.GetD("high");
       newvals[j] =  gRandom->Uniform(low, high);
 
     }
     // Add to vects
     scanparset_vals.push_back(newvals);
 
     TH1D* parhist = (TH1D*)parhisttemplate->Clone();
     for (size_t j = 0; j < newvals.size(); j++) {
       parhist->SetBinContent(j + 1, newvals[j]);
     }
     scanparset_hists.push_back(parhist);
   }
 
   // Print out the parameter set to test
   for (uint i = 0; i < scanparset_vals.size(); i++) {
     std::cout << "Parset " << i;
     for (uint j = 0 ; j < scanparset_vals[i].size(); j++) {
       std::cout << " " << scanparset_vals[i][j];
     }
     std::cout << std::endl;
   }
 
 
   // Weight holders
   double* rawweights = new double[scanparset_vals.size()];
   double* splweights = new double[scanparset_vals.size()];
   double* difweights = new double[scanparset_vals.size()];
   int nweights = scanparset_vals.size();
   // int NParSets = scanparset_vals.size();
 
   // Loop over all event I/O
   std::vector<nuiskey> eventkeys = Config::QueryKeys("events");
   for (size_t i = 0; i < eventkeys.size(); i++) {
     nuiskey key = eventkeys.at(i);
 
     // Get I/O
     std::string inputfilename  = key.GetS("input");
     if (inputfilename.empty()) {
       ERR(FTL) << "No input given for set of input events!" << std::endl;
       throw;
     }
 
     std::string outputfilename = key.GetS("output");
     if (outputfilename.empty()) {
       outputfilename = inputfilename + ".nuisance.root";
       ERR(FTL) << "No output give for set of output events! Saving to "
                << outputfilename << std::endl;
     }
 
     // Make a new input handler
     std::vector<std::string> file_descriptor =
       GeneralUtils::ParseToStr(inputfilename, ":");
     if (file_descriptor.size() != 2) {
       ERR(FTL) << "File descriptor had no filetype declaration: \"" << inputfilename
                << "\". expected \"FILETYPE:file.root\"" << std::endl;
       throw;
     }
     InputUtils::InputType inptype =
       InputUtils::ParseInputType(file_descriptor[0]);
 
 
     // Make handlers for input and output
     InputHandlerBase* input  = InputUtils::CreateInputHandler("rawevents", inptype, file_descriptor[1]);
     InputHandlerBase* output =  InputUtils::CreateInputHandler("splineevents", InputUtils::kEVSPLN_Input, outputfilename);
 
     // Get Base Events for each case.
     FitEvent* rawevent = input->FirstNuisanceEvent();
     FitEvent* splevent = output->FirstNuisanceEvent();
 
 
     // Setup outputfile
     std::string outputtest = outputfilename + ".splinetest.NDEventThrow.root";
     TFile* outputtestfile = new TFile(outputtest.c_str(), "RECREATE");
     outputtestfile->cd();
 
     // Save Parameter Sets
     for (size_t i = 0; i < scanparset_hists.size(); i++) {
       scanparset_hists[i]->Write(Form("Paramater_Set_%i", (int)i));
     }
 
     // Save a TTree of weights and differences.
     TTree* weighttree = new TTree("weightscan", "weightscan");
 
     // Make a branch for each weight set
     for (size_t i = 0; i < scanparset_hists.size(); i++) {
       weighttree->Branch(Form("RawWeights_Set_%i", (int)i), &rawweights[i], Form("RawWeights_Set_%i/D", (int)i) );
       weighttree->Branch(Form("SplineWeights_Set_%i", (int)i), &splweights[i], Form("SplineWeights_Set_%i/D", (int)i) );
       weighttree->Branch(Form("DifWeights_Set_%i", (int)i), &difweights[i], Form("DifWeights_Set_%i/D", (int)i) );
 
     }
 
     // Count
     // int i = 0;
     int nevents = input->GetNEvents();
     int lasttime = time(NULL);
 
     // Load N Chunks of the Weights into Memory
     // Split into N processing chunks
     int nchunks = FitPar::Config().GetParI("spline_chunks");
     if (nchunks <= 0) nchunks = 1;
     if (nchunks >= nevents / 2) nchunks = nevents / 2;
     
     std::cout << "Starting NChunks " << nchunks << std::endl;
     for (int ichunk = 0; ichunk < nchunks; ichunk++) {
 
       // Skip to only do one processing chunk
       //      if (procchunk != -1 and procchunk != ichunk) continue;
 
       LOG(FIT) << "On Processing Chunk " << ichunk << std::endl;
       int neventsinchunk   = nevents / nchunks;
       int loweventinchunk  = neventsinchunk * ichunk;
       // int higheventinchunk = neventsinchunk * (ichunk + 1);
 
       double** allrawweights = new double*[neventsinchunk];
       double** allsplweights = new double*[neventsinchunk];
       double** alldifweights = new double*[neventsinchunk];
       for (int k = 0; k < neventsinchunk; k++){
         allrawweights[k] = new double[nweights];
 	allsplweights[k] = new double[nweights];
 	alldifweights[k] = new double[nweights];
       }
 
       // Start Set Processing Here.
       for (int iset = 0; iset < nweights; iset++) {
 
 	// Reconfigure
         fRW->SetAllDials(&scanparset_vals[iset][0], scanparset_vals[iset].size());
         fRW->Reconfigure();
 
         // Reconfigure spline RW
         splweight->SetAllDials(&scanparset_vals[iset][0], scanparset_vals[iset].size());
         splweight->Reconfigure();
 
         splevent->fSplineRead->SetNeedsReconfigure(true);
 
         // Could reorder this to save the weightconts in order instead of reconfiguring per event.
         // Loop over all events and fill the TTree
         for (int i = 0; i < neventsinchunk; i++){
 
 	  rawevent = input->GetNuisanceEvent(i+loweventinchunk);
 	  splevent = output->GetNuisanceEvent(i+loweventinchunk);
 
 	  allrawweights[i][iset] = fRW->CalcWeight(rawevent);
 	  allsplweights[i][iset] = splweight->CalcWeight(splevent);
 	  alldifweights[i][iset] = allsplweights[i][iset] - allrawweights[i][iset];
         }
 	
 	std::ostringstream timestring;
         int timeelapsed = time(NULL) - lasttime;
         if  (timeelapsed) {
           lasttime = time(NULL);
 
           int setsleft = (nweights-iset-1) + (nweights * (nchunks - ichunk - 1));
           float proj = (float(setsleft) *timeelapsed) / 60 / 60;
           timestring << setsleft << " sets remaining. Last one took " << timeelapsed << ". " << proj << " hours remaining.";
 
         }
 
 	LOG(REC) << "Processed Set " << iset << "/" << nweights <<" in chunk " << ichunk << "/" << nchunks << " " << timestring.str() << std::endl;
 
       }
 
       // Fill weights for this chunk into the TTree
       for (int k = 0; k < neventsinchunk; k++){
 	for (int l = 0; l < nweights; l++){
 	  rawweights[l] = allrawweights[k][l];
 	  splweights[l] = allsplweights[k][l];
 	  difweights[l] = alldifweights[k][l];
 	}
         weighttree->Fill();
       }
     }
 
 
     // Loop over nchunks
 
     // Loop over parameter sets
     // Set All Dials and reconfigure
 
     // Loop over events in chunk
     // Fill Chunkweightcontainers
     
     // Once all dials are done, fill the weight tree
     
     // Iterator to next chunk
     
 
     outputtestfile->cd();
     weighttree->Write();
     outputtestfile->Close();
   }
 }
 
 
 void SplineRoutines::SaveSplinePlots() {
 
   if (fRW) delete fRW;
   SetupRWEngine();
 
   // Setup the spline reader
   SplineWriter* splwrite = new SplineWriter(fRW);
   std::vector<nuiskey> splinekeys = Config::QueryKeys("spline");
 
   // Add splines to splinewriter
   for (std::vector<nuiskey>::iterator iter = splinekeys.begin();
        iter != splinekeys.end(); iter++) {
     nuiskey splkey = (*iter);
 
     // Add Spline Info To Reader
     splwrite->AddSpline(splkey);
   }
   splwrite->SetupSplineSet();
 
 
 
   // Event Loop
   // Loop over all events and calculate weights for each parameter set.
 
   // Generate a set of nominal events
   // Method, Loop over inputs, create input handler, then create a ttree
   std::vector<nuiskey> eventkeys = Config::QueryKeys("events");
   for (size_t i = 0; i < eventkeys.size(); i++) {
     nuiskey key = eventkeys.at(i);
 
     // Get I/O
     std::string inputfilename  = key.GetS("input");
     if (inputfilename.empty()) {
       ERR(FTL) << "No input given for set of input events!" << std::endl;
       throw;
     }
 
     std::string outputfilename = key.GetS("output");
     if (outputfilename.empty()) {
       outputfilename = inputfilename + ".nuisance.root";
       ERR(FTL) << "No output give for set of output events! Saving to "
                << outputfilename << std::endl;
     }
 
     // Make new outputfile
     outputfilename += ".SplinePlots.root";
     TFile* outputfile = new TFile(outputfilename.c_str(), "RECREATE");
     outputfile->cd();
 
     // Make a new input handler
     std::vector<std::string> file_descriptor =
       GeneralUtils::ParseToStr(inputfilename, ":");
     if (file_descriptor.size() != 2) {
       ERR(FTL) << "File descriptor had no filetype declaration: \"" << inputfilename
                << "\". expected \"FILETYPE:file.root\"" << std::endl;
       throw;
     }
     InputUtils::InputType inptype =
       InputUtils::ParseInputType(file_descriptor[0]);
 
     InputHandlerBase* input = InputUtils::CreateInputHandler("eventsaver", inptype, file_descriptor[1]);
 
     // Get info from inputhandler
     int nevents = input->GetNEvents();
     int countwidth = (nevents / 1000);
     FitEvent* nuisevent = input->FirstNuisanceEvent();
 
     outputfile->cd();
 
     // int lasttime = time(NULL);
     TCanvas* fitcanvas = NULL;
 
 
 
 
     // Loop over all events and fill the TTree
     while (nuisevent) {
 
       // std::cout << "Fitting event " << i << std::endl;
       // Calculate the weights for each parameter set
       splwrite->GetWeightsForEvent(nuisevent);
       splwrite->FitSplinesForEvent(fitcanvas, true);
 
       if (fitcanvas) {
         outputfile->cd();
         fitcanvas->Write(Form("Event_SplineCanvas_%i", (int)i));
       }
 
       // Logging
       if (i % countwidth == 0) {
         LOG(REC) << "Saved " << i << "/" << nevents << " nuisance spline plots. " << std::endl;
       }
 
       // Iterate
       i++;
       nuisevent = input->NextNuisanceEvent();
     }
     // Save flux and close file
     outputfile->cd();
 
     // Close Output
     outputfile->Close();
 
     // Delete Inputs
     delete input;
   }
 
   // remove Keys
   eventkeys.clear();
 
 }
 
 void SplineRoutines::TestSplines_NDLikelihoodThrow() {
 
   // Setup RW Engine
   if (fRW) delete fRW;
   SetupRWEngine();
 
   // Make a spline RW Engine too.
   FitWeight* splweight = new FitWeight("splinerwaweight");
   std::vector<nuiskey> parameterkeys = Config::QueryKeys("parameter");
   TH1D* parhisttemplate = new TH1D("parhist", "parhist", parameterkeys.size(), 0.0, float(parameterkeys.size()));
 
   // Add Parameters
   for (size_t i = 0; i < parameterkeys.size(); i++) {
     nuiskey key = parameterkeys[i];
 
     std::string parname = key.GetS("name");
     std::string partype = key.GetS("type");
     double nom = key.GetD("nominal");
 
     parhisttemplate->SetBinContent(i + 1, nom);
     parhisttemplate->GetXaxis()->SetBinLabel(i + 1, parname.c_str());
 
     splweight->IncludeDial( key.GetS("name"),
                             kSPLINEPARAMETER, nom);
     splweight->SetDialValue( key.GetS("name"), key.GetD("nominal") );
 
   }
   splweight->Reconfigure();
 
   // Make a high resolution spline set.
   std::vector<double> nomvals = fRW->GetDialValues();
   // int testres = FitPar::Config().GetParI("spline_test_resolution");
 
   std::vector< std::string > scanparset_names;
   std::vector< std::vector<double> > scanparset_vals;
   std::vector< TH1D* > scanparset_hists;
 
   // Loop over all params
   // Add Parameters
   int nthrows = FitPar::Config().GetParI("spline_test_throws");
   for (int i = 0; i < nthrows; i++) {
 
     std::vector<double> newvals = nomvals;
 
     for (size_t j = 0; j < parameterkeys.size(); j++) {
       nuiskey key = parameterkeys[j];
 
       if (!key.Has("low") or !key.Has("high") or !key.Has("step")) {
         continue;
       }
 
       // Push Back Scan
       double low  = key.GetD("low");
       double high = key.GetD("high");
       newvals[j] =  gRandom->Uniform(low, high);
 
     }
     // Add to vects
     scanparset_vals.push_back(newvals);
 
     TH1D* parhist = (TH1D*)parhisttemplate->Clone();
     for (size_t j = 0; j < newvals.size(); j++) {
       parhist->SetBinContent(j + 1, newvals[j]);
     }
     scanparset_hists.push_back(parhist);
   }
 
   // Print out the parameter set to test
   for (uint i = 0; i < scanparset_vals.size(); i++) {
     std::cout << "Parset " << i;
     for (uint j = 0 ; j < scanparset_vals[i].size(); j++) {
       std::cout << " " << scanparset_vals[i][j];
     }
     std::cout << std::endl;
   }
 
   // Make a new set of Raw/Spline Sample Keys
   std::vector<nuiskey> eventkeys = Config::QueryKeys("events");
   std::vector<nuiskey> testkeys  = Config::QueryKeys("sampletest");
 
   std::vector<nuiskey> rawkeys;
   std::vector<nuiskey> splkeys;
 
 
   for (std::vector<nuiskey>::iterator iter = testkeys.begin();
        iter != testkeys.end(); iter++) {
     nuiskey key = (*iter);
 
     std::string samplename = key.GetS("name");
     std::string eventsid = key.GetS("inputid");
     nuiskey eventskey = Config::QueryLastKey("events", "id=" + eventsid);
     std::string rawfile = eventskey.GetS("input");
     std::string splfile = eventskey.GetS("output");
 
     nuiskey rawkeytemp = Config::CreateKey("sample");
     rawkeytemp.SetS("name", samplename);
     rawkeytemp.SetS("input", rawfile);
 
     nuiskey splkeytemp = Config::CreateKey("sample");
     splkeytemp.SetS("name", samplename);
     splkeytemp.SetS("input", "EVSPLN:" + splfile);
 
     rawkeys.push_back(rawkeytemp);
     splkeys.push_back(splkeytemp);
   }
 
   if (fOutputRootFile) delete fOutputRootFile;
   fOutputRootFile = new TFile(fOutputFile.c_str(), "RECREATE");
 
   fOutputRootFile->ls();
   // Make two new JointFCN
   JointFCN* rawfcn = new JointFCN(rawkeys, fOutputRootFile);
   JointFCN* splfcn = new JointFCN(splkeys, fOutputRootFile);
 
   // Create iteration tree in output file
   fOutputRootFile->cd();
   rawfcn->CreateIterationTree("raw_iterations", fRW);
   splfcn->CreateIterationTree("spl_iterations", splweight);
 
   // Loop over parameter sets.
   for (size_t j = 0; j < scanparset_vals.size(); j++) {
 
     FitBase::SetRW(fRW);
     double rawtotal = rawfcn->DoEval(&scanparset_vals[j][0]);
 
     FitBase::SetRW(splweight);
     double spltotal = splfcn->DoEval(&scanparset_vals[j][0]);
 
     LOG(FIT) << "RAW SPLINE DIF = " << rawtotal << " " << spltotal << " " << spltotal - rawtotal << std::endl;
   }
 
   fOutputRootFile->cd();
 
   rawfcn->WriteIterationTree();
   splfcn->WriteIterationTree();
 
 }
 
 
 void SplineRoutines::TestSplines_1DLikelihoodScan() {
 
   // Setup RW Engine.
   if (fRW) delete fRW;
   SetupRWEngine();
 
   // Setup Parameter Set.
   // Make a spline RW Engine too.
   FitWeight* splweight = new FitWeight("splinerwaweight");
   // std::vector<nuiskey> splinekeys    = Config::QueryKeys("spline");
   std::vector<nuiskey> parameterkeys = Config::QueryKeys("parameter");
   TH1D* parhisttemplate = new TH1D("parhist", "parhist", parameterkeys.size(), 0.0, float(parameterkeys.size()));
 
   // Add Parameters
   for (size_t i = 0; i < parameterkeys.size(); i++) {
     nuiskey key = parameterkeys[i];
 
     std::string parname = key.GetS("name");
     std::string partype = key.GetS("type");
     double nom = key.GetD("nominal");
 
     parhisttemplate->SetBinContent(i + 1, nom);
     parhisttemplate->GetXaxis()->SetBinLabel(i + 1, parname.c_str());
 
     splweight->IncludeDial( key.GetS("name"),
                             kSPLINEPARAMETER, nom);
     splweight->SetDialValue( key.GetS("name"), key.GetD("nominal") );
 
   }
   splweight->Reconfigure();
 
   // Make a high resolution spline set.
   std::vector<double> nomvals = fRW->GetDialValues();
   // int testres = FitPar::Config().GetParI("spline_test_resolution");
 
   std::vector< std::vector<double> > scanparset_vals;
   std::vector< TH1D* > scanparset_hists;
 
   // Loop over all params
   // Add Parameters
   for (size_t i = 0; i < parameterkeys.size(); i++) {
     nuiskey key = parameterkeys[i];
 
     // Get Par Name
     std::string name = key.GetS("name");
 
     if (!key.Has("low") or !key.Has("high") or !key.Has("step")) {
       continue;
     }
 
     // Push Back Scan
     double low  = key.GetD("low");
     double high = key.GetD("high");
     double cur = low;
     double step = key.GetD("step");
 
     while (cur <= high) {
 
       // Make new set
       std::vector<double> newvals = nomvals;
       newvals[i] = cur;
 
       // Add to vects
       scanparset_vals.push_back(newvals);
 
       TH1D* parhist = (TH1D*)parhisttemplate->Clone();
       for (size_t j = 0; j < newvals.size(); j++) {
         parhist->SetBinContent(j + 1, newvals[j]);
       }
       scanparset_hists.push_back(parhist);
 
 
       // Move to next one
       cur += step;
     }
   }
 
   // Print out the parameter set to test
   for (uint i = 0; i < scanparset_vals.size(); i++) {
     std::cout << "Parset " << i;
     for (uint j = 0 ; j < scanparset_vals[i].size(); j++) {
       std::cout << " " << scanparset_vals[i][j];
     }
     std::cout << std::endl;
   }
 
   // Make a new set of Raw/Spline Sample Keys
   std::vector<nuiskey> eventkeys = Config::QueryKeys("events");
   std::vector<nuiskey> testkeys  = Config::QueryKeys("sampletest");
 
   std::vector<nuiskey> rawkeys;
   std::vector<nuiskey> splkeys;
 
 
   for (std::vector<nuiskey>::iterator iter = testkeys.begin();
        iter != testkeys.end(); iter++) {
     nuiskey key = (*iter);
 
     std::string samplename = key.GetS("name");
     std::string eventsid = key.GetS("inputid");
     nuiskey eventskey = Config::QueryLastKey("events", "id=" + eventsid);
     std::string rawfile = eventskey.GetS("input");
     std::string splfile = eventskey.GetS("output");
 
     nuiskey rawkeytemp = Config::CreateKey("sample");
     rawkeytemp.SetS("name", samplename);
     rawkeytemp.SetS("input", rawfile);
 
     nuiskey splkeytemp = Config::CreateKey("sample");
     splkeytemp.SetS("name", samplename);
     splkeytemp.SetS("input", "EVSPLN:" + splfile);
 
     rawkeys.push_back(rawkeytemp);
     splkeys.push_back(splkeytemp);
   }
 
   if (fOutputRootFile) delete fOutputRootFile;
   fOutputRootFile = new TFile(fOutputFile.c_str(), "RECREATE");
 
   fOutputRootFile->ls();
   // Make two new JointFCN
   JointFCN* rawfcn = new JointFCN(rawkeys, fOutputRootFile);
   JointFCN* splfcn = new JointFCN(splkeys, fOutputRootFile);
 
   // Create iteration tree in output file
   fOutputRootFile->cd();
   rawfcn->CreateIterationTree("raw_iterations", fRW);
   splfcn->CreateIterationTree("spl_iterations", splweight);
 
   // Loop over parameter sets.
   for (size_t j = 0; j < scanparset_vals.size(); j++) {
 
     FitBase::SetRW(fRW);
     double rawtotal = rawfcn->DoEval(&scanparset_vals[j][0]);
 
     FitBase::SetRW(splweight);
     double spltotal = splfcn->DoEval(&scanparset_vals[j][0]);
 
     LOG(FIT) << "RAW SPLINE DIF = " << rawtotal << " " << spltotal << " " << spltotal - rawtotal << std::endl;
   }
 
   fOutputRootFile->cd();
 
   rawfcn->WriteIterationTree();
   splfcn->WriteIterationTree();
 
 }
 
 
 /*
   MISC Functions
 */
 //*************************************
 int SplineRoutines::GetStatus() {
   //*************************************
 
   return 0;
 }
diff --git a/src/Routines/SplineRoutines.h b/src/Routines/SplineRoutines.h
index a56f692..5cedfd2 100755
--- a/src/Routines/SplineRoutines.h
+++ b/src/Routines/SplineRoutines.h
@@ -1,197 +1,197 @@
 // Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret
 
 /*******************************************************************************
 *    This file is part of NUISANCE.
 *
 *    NUISANCE is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    NUISANCE is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with NUISANCE.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
 
 #ifndef SPLINE_ROUTINES_H
 #define SPLINE_ROUTINES_H
 
 /*!
  *  \addtogroup Minimizer
  *  @{
  */
 
 #include "TH1.h"
 #include "TF1.h"
 #include "TMatrixD.h"
 #include "TVectorD.h"
 #include "TSystem.h"
 #include "TFile.h"
 #include "TProfile.h"
 
 
 #include <vector>
 #include <string>
 #include <iostream>
 #include <sstream>
 #include <cstring>
 
 #include "FitEvent.h"
 #include "JointFCN.h"
-#include "FitParameters.h"
+
 #include "FitLogger.h"
 #include "BaseFitEvt.h"
 #include "NuisConfig.h"
 #include "NuisKey.h"
 #include "SplineReader.h"
 #include "SplineWriter.h"
 #include "SplineMerger.h"
 #include "ParserUtils.h"
 #include "OpenMPWrapper.h"
 enum minstate {
   kErrorStatus = -1,
   kGoodStatus,
   kFitError,
   kNoChange,
   kFitFinished,
   kFitUnfinished,
   kStateChange,
 };
 
 //*************************************
 //! Collects all possible fit routines into a single class to avoid repeated code
 class SplineRoutines{
 //*************************************
 
 public:
 
   /*
     Constructor/Destructor
   */
 
   //! Constructor reads in arguments given at the command line for the fit here.
   SplineRoutines(int argc, char* argv[]);
     
   //! Default destructor
   ~SplineRoutines();
 
   //! Reset everything to default/NULL
   void Init();
   
   /*
     Input Functions
   */
 
   //! Splits the arguments ready for initial setup
   void ParseArgs(int argc, char* argv[]);
   
   /*
     Setup Functions
   */
 
   //! Setup the configuration given the arguments passed at the commandline and card file
   void SetupConfig();
 
   //! Setups up our custom RW engine with all the parameters passed in the card file
   void SetupRWEngine();
 
   void Run();
   void SaveEvents();
   void TestEvents();
   void GenerateEventSplines();
   void GenerateEventWeights();
   void GenerateEventWeightChunks(int procchunk = -1);
   void BuildEventSplines(int procchunk = -1);
   void MergeEventSplinesChunks();
   /* 
     Testing Functions
   */
   
   /// Scan parameter space in 1D at finer resolution than points. Compare Raw/Spline on an event by event basis.
   void TestSplines_1DEventScan();
 
   /// Scan parameter space in 1D at finer resolution than points. Compare likelihoods for all testsamples.
   void TestSplines_1DLikelihoodScan();
 
   /// Randomly throw in parameter space. For each throw, calc average weight difference.
   void TestSplines_NDEventThrow();
 
   /// Randomly thow in parameter space. For each throw, calc likelihood difference for each sample.
   void TestSplines_NDLikelihoodThrow();
 
 
   /// Generate a set of spline vs weight canvases and save to file
   void SaveSplinePlots();
 
   /*
     Fitting Functions
   */
 
   //! Given a new map change the values that the RW engine is currently set to
   void UpdateRWEngine(std::map<std::string,double>& updateVals);
 
   /*
     MISC Functions
   */
 
   //! Get previous fit status from a file
   Int_t GetStatus();
 
   void MergeSplines();
 
 protected:
 
   //! Our Custom ReWeight Object
   FitWeight* rw;
   FitWeight* fRW;
   
   std::string fOutputFile;
   std::string fInputFile;
 
   TFile* fInputRootFile;
   TFile* fOutputRootFile;
   
   JointFCN* fSampleFCN;
   std::list<MeasurementBase*> fSamples;
   
   std::string fCardFile;
 
   std::string fStrategy;
   std::vector<std::string> fRoutines;
   std::string fAllowedRoutines;
   
   // Input Dial Vals
   //! Vector of dial names
   std::vector<std::string> fParams;
   std::map<std::string, std::string> fStateVals;
   std::map<std::string, double>      fStartVals;
   std::map<std::string, double>      fCurVals;
   std::map<std::string, double>      fErrorVals;
   std::map<std::string, double>      fMinVals;
   std::map<std::string, double>      fMaxVals;
   std::map<std::string, double>      fStepVals;
   std::map<std::string, int>         fTypeVals;
   std::map<std::string, bool>        fFixVals;
   std::map<std::string, bool>        fStartFixVals;
 
   std::vector<std::string> fGenericInputNames;
   std::map<std::string, std::string> fGenericInputFiles;
   std::map<std::string, std::string> fGenericOutputFiles;
   std::map<std::string, std::string> fGenericOutputTypes;
   std::map<std::string, InputHandlerBase*> fGenericInputs;
 
 
   std::vector<std::string> fSplineNames;
   std::map<std::string, std::string> fSplineTypes;
   std::map<std::string, std::string> fSplinePoints;
     nuiskey fCompKey;
   
   
 };
 
 /*! @} */
 #endif
diff --git a/src/Routines/SystematicRoutines.cxx b/src/Routines/SystematicRoutines.cxx
index 1afc9bd..dd13fda 100755
--- a/src/Routines/SystematicRoutines.cxx
+++ b/src/Routines/SystematicRoutines.cxx
@@ -1,1517 +1,1206 @@
 // Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret
 
 /*******************************************************************************
 *    This file is part of NUISANCE.
 *
 *    NUISANCE is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    NUISANCE is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with NUISANCE.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
 #include "SystematicRoutines.h"
 
 void SystematicRoutines::Init(){
 
   fInputFile = "";
   fInputRootFile = NULL;
 
   fOutputFile = "";
   fOutputRootFile = NULL;
 
   fCovar  = fCovarFree  = NULL;
   fCorrel = fCorrelFree = NULL;
   fDecomp = fDecompFree = NULL;
 
   fStrategy = "ErrorBands";
   fRoutines.clear();
   fRoutines.push_back("ErrorBands");
 
   fCardFile = "";
 
   fFakeDataInput = "";
 
   fSampleFCN    = NULL;
 
   fAllowedRoutines = ("ErrorBands,PlotLimits");
 
 };
 
 SystematicRoutines::~SystematicRoutines(){
 };
 
 SystematicRoutines::SystematicRoutines(int argc, char* argv[]){
 
   // Initialise Defaults
   Init();
   nuisconfig configuration = Config::Get();
 
   // Default containers
   std::string cardfile = "";
   std::string maxevents = "-1";
   int errorcount = 0;
   int verbocount = 0;
   std::vector<std::string> xmlcmds;
   std::vector<std::string> configargs;
   fNThrows = 250;
   fStartThrows = 0;
   fThrowString = "";
   // Make easier to handle arguments.
   std::vector<std::string> args = GeneralUtils::LoadCharToVectStr(argc, argv);
   ParserUtils::ParseArgument(args, "-c", fCardFile, true);
   ParserUtils::ParseArgument(args, "-o", fOutputFile, false, false);
   ParserUtils::ParseArgument(args, "-n", maxevents, false, false);
   ParserUtils::ParseArgument(args, "-f", fStrategy, false, false);
   ParserUtils::ParseArgument(args, "-d", fFakeDataInput, false, false);
   ParserUtils::ParseArgument(args, "-s", fStartThrows, false, false);
   ParserUtils::ParseArgument(args, "-t", fNThrows, false, false);
   ParserUtils::ParseArgument(args, "-p", fThrowString, false, false);
   ParserUtils::ParseArgument(args, "-i", xmlcmds);
   ParserUtils::ParseArgument(args, "-q", configargs);
   ParserUtils::ParseCounter(args, "e", errorcount);
   ParserUtils::ParseCounter(args, "v", verbocount);
   ParserUtils::CheckBadArguments(args);
 
   // Add extra defaults if none given
   if (fCardFile.empty() and xmlcmds.empty()) {
     ERR(FTL) << "No input supplied!" << std::endl;
     throw;
   }
 
   if (fOutputFile.empty() and !fCardFile.empty()) {
     fOutputFile = fCardFile + ".root";
     ERR(WRN) << "No output supplied so saving it to: " << fOutputFile << std::endl;
 
   } else if (fOutputFile.empty()) {
     ERR(FTL) << "No output file or cardfile supplied!" << std::endl;
     throw;
   }
 
   // Configuration Setup =============================
 
   // Check no comp key is available
   if (Config::Get().GetNodes("nuiscomp").empty()) {
     fCompKey = Config::Get().CreateNode("nuiscomp");
   } else {
     fCompKey = Config::Get().GetNodes("nuiscomp")[0];
   }
 
-  if (!fCardFile.empty())   fCompKey.AddS("cardfile", fCardFile);
-  if (!fOutputFile.empty()) fCompKey.AddS("outputfile", fOutputFile);
-  if (!fStrategy.empty())   fCompKey.AddS("strategy", fStrategy);
+  if (!fCardFile.empty())   fCompKey.Set("cardfile", fCardFile);
+  if (!fOutputFile.empty()) fCompKey.Set("outputfile", fOutputFile);
+  if (!fStrategy.empty())   fCompKey.Set("strategy", fStrategy);
 
   // Load XML Cardfile
-  configuration.LoadConfig( fCompKey.GetS("cardfile"), "");
-
-  // Add CMD XML Structs
-  for (size_t i = 0; i < xmlcmds.size(); i++) {
-    configuration.AddXMLLine(xmlcmds[i]);
-  }
+  configuration.LoadSettings( fCompKey.GetS("cardfile"), "");
 
   // Add Config Args
   for (size_t i = 0; i < configargs.size(); i++) {
     configuration.OverrideConfig(configargs[i]);
   }
   if (maxevents.compare("-1")){
     configuration.OverrideConfig("MAXEVENTS=" + maxevents);
   }
 
   // Finish configuration XML
-  configuration.FinaliseConfig(fCompKey.GetS("outputfile") + ".xml");
+  configuration.FinaliseSettings(fCompKey.GetS("outputfile") + ".xml");
 
   // Add Error Verbo Lines
-  verbocount += Config::Get().GetParI("VERBOSITY");
-  errorcount += Config::Get().GetParI("ERROR");
+  verbocount += Config::GetParI("VERBOSITY");
+  errorcount += Config::GetParI("ERROR");
   std::cout << "[ NUISANCE ]: Setting VERBOSITY=" << verbocount << std::endl;
   std::cout << "[ NUISANCE ]: Setting ERROR=" << errorcount << std::endl;
   SETVERBOSITY(verbocount);
   
   // Proper Setup
   if (fStrategy.find("ErrorBands") != std::string::npos ||
       fStrategy.find("MergeErrors") != std::string::npos){
     fOutputRootFile = new TFile(fCompKey.GetS("outputfile").c_str(), "RECREATE");    
   }
 
   //  fOutputRootFile = new TFile(fCompKey.GetS("outputfile").c_str(), "RECREATE");
   SetupSystematicsFromXML();
 
   SetupCovariance();
   SetupRWEngine();
   SetupFCN();
   GetCovarFromFCN();
 
   //  Run();
 
   return;
 };
 
 void SystematicRoutines::SetupSystematicsFromXML(){
 
   LOG(FIT) << "Setting up nuismin" << std::endl;
 
   // Setup Parameters ------------------------------------------
   std::vector<nuiskey> parkeys = Config::QueryKeys("parameter");
   if (!parkeys.empty()) {
     LOG(FIT) << "Number of parameters :  " << parkeys.size() << std::endl;
   }
 
   for (size_t i = 0; i < parkeys.size(); i++) {
     nuiskey key = parkeys.at(i);
 
     // Check for type,name,nom
     if (!key.Has("type")) {
       ERR(FTL) << "No type given for parameter " << i << std::endl;
       throw;
     } else if (!key.Has("name")) {
       ERR(FTL) << "No name given for parameter " << i << std::endl;
       throw;
     } else if (!key.Has("nominal")) {
       ERR(FTL) << "No nominal given for parameter " << i << std::endl;
       throw;
     }
 
     // Get Inputs
     std::string partype = key.GetS("type");
     std::string parname = key.GetS("name");
     double parnom  = key.GetD("nominal");
     double parlow  = parnom - 1;
     double parhigh = parnom + 1;
     double parstep = 1;
 
 
     // Override if state not given
     if (!key.Has("state")){
       key.SetS("state","FIX");
     }
 
     std::string parstate = key.GetS("state");
 
     // Extra limits
     if (key.Has("low")) {
       parlow  = key.GetD("low");
       parhigh = key.GetD("high");
       parstep = key.GetD("step");
 
       LOG(FIT) << "Read " << partype << " : "
                << parname << " = "
                << parnom << " : "
                << parlow << " < p < " << parhigh
                << " : " << parstate << std::endl;
     } else {
       LOG(FIT) << "Read " << partype << " : "
                << parname << " = "
                << parnom << " : "
                << parstate << std::endl;
     }
 
     // Run Parameter Conversion if needed
     if (parstate.find("ABS") != std::string::npos) {
       parnom  = FitBase::RWAbsToSigma( partype, parname, parnom  );
       parlow  = FitBase::RWAbsToSigma( partype, parname, parlow  );
       parhigh = FitBase::RWAbsToSigma( partype, parname, parhigh );
       parstep = FitBase::RWAbsToSigma( partype, parname, parstep );
     } else if (parstate.find("FRAC") != std::string::npos) {
       parnom  = FitBase::RWFracToSigma( partype, parname, parnom  );
       parlow  = FitBase::RWFracToSigma( partype, parname, parlow  );
       parhigh = FitBase::RWFracToSigma( partype, parname, parhigh );
       parstep = FitBase::RWFracToSigma( partype, parname, parstep );
     }
 
     // Push into vectors
     fParams.push_back(parname);
 
     fTypeVals[parname]  = FitBase::ConvDialType(partype);;
     fStartVals[parname] = parnom;
     fCurVals[parname]   = parnom;
 
     fErrorVals[parname] = 0.0;
 
     fStateVals[parname]    = parstate;
     bool fixstate = parstate.find("FIX") != std::string::npos;
     fFixVals[parname]      = fixstate;
     fStartFixVals[parname] = fFixVals[parname];
 
     fMinVals[parname]  = parlow;
     fMaxVals[parname]  = parhigh;
     fStepVals[parname] = parstep;
 
   }
 
   // Setup Samples ----------------------------------------------
   std::vector<nuiskey> samplekeys =  Config::QueryKeys("sample");
   if (!samplekeys.empty()) {
     LOG(FIT) << "Number of samples : " << samplekeys.size() << std::endl;
   }
 
   for (size_t i = 0; i < samplekeys.size(); i++) {
     nuiskey key = samplekeys.at(i);
 
     // Get Sample Options
     std::string samplename = key.GetS("name");
     std::string samplefile = key.GetS("input");
 
     std::string sampletype =
       key.Has("type") ? key.GetS("type") : "DEFAULT";
 
     double samplenorm =
       key.Has("norm") ? key.GetD("norm") : 1.0;
 
     // Print out
     LOG(FIT) << "Read sample info " << i << " : "
              << samplename << std::endl
              << "\t\t input -> " << samplefile  << std::endl
              << "\t\t state -> " << sampletype << std::endl
              << "\t\t norm  -> " << samplenorm << std::endl;
 
     // If FREE add to parameters otherwise continue
     if (sampletype.find("FREE") == std::string::npos) {
       continue;
     }
 
     // Form norm dial from samplename + sampletype + "_norm";
     std::string normname = samplename + "_norm";
 
     // Check normname not already present
     if (fTypeVals.find(normname) != fTypeVals.end()) {
       continue;
     }
 
     // Add new norm dial to list if its passed above checks
     fParams.push_back(normname);
 
     fTypeVals[normname] = kNORM;
     fStateVals[normname] = sampletype;
     fCurVals[normname] = samplenorm;
 
     fErrorVals[normname] = 0.0;
 
     fMinVals[normname]  = 0.1;
     fMaxVals[normname]  = 10.0;
     fStepVals[normname] = 0.5;
 
     bool state = sampletype.find("FREE") == std::string::npos;
     fFixVals[normname]      = state;
     fStartFixVals[normname] = state;
   }
 
   // Setup Fake Parameters -----------------------------
   std::vector<nuiskey> fakekeys = Config::QueryKeys("fakeparameter");
   if (!fakekeys.empty()) {
     LOG(FIT) << "Number of fake parameters : " << fakekeys.size() << std::endl;
   }
 
   for (size_t i = 0; i < fakekeys.size(); i++) {
     nuiskey key = fakekeys.at(i);
 
     // Check for type,name,nom
     if (!key.Has("name")) {
       ERR(FTL) << "No name given for fakeparameter " << i << std::endl;
       throw;
     } else if (!key.Has("nom")) {
       ERR(FTL) << "No nominal given for fakeparameter " << i << std::endl;
       throw;
     }
 
     // Get Inputs
     std::string parname = key.GetS("name");
     double parnom  = key.GetD("nom");
 
     // Push into vectors
     fFakeVals[parname] = parnom;
   }
 }
 
 
-void SystematicRoutines::ReadCard(std::string cardfile){
-
-  // Read cardlines into vector
-  std::vector<std::string> cardlines = GeneralUtils::ParseFileToStr(cardfile,"\n");
-  FitPar::Config().cardLines = cardlines;
-
-  // Read Samples first (norm params can be overridden)
-  int linecount = 0;
-  for (std::vector<std::string>::iterator iter = cardlines.begin();
-       iter != cardlines.end(); iter++){
-    std::string line = (*iter);
-    linecount++;
-
-    // Skip Empties
-    if (line.empty()) continue;
-    if (line.c_str()[0] == '#') continue;
-
-    // Read Valid Samples
-    int samstatus = ReadSamples(line);
-
-    // Show line if bad to help user
-    if (samstatus == kErrorStatus) {
-      ERR(FTL) << "Bad Input in cardfile " << fCardFile
-	       << " at line " << linecount << "!" << std::endl;
-      LOG(FIT) << line << std::endl;
-      throw;
-    }
-  }
-
-  // Read Parameters second
-  linecount = 0;
-  for (std::vector<std::string>::iterator iter = cardlines.begin();
-       iter != cardlines.end(); iter++){
-    std::string line = (*iter);
-    linecount++;
-
-    // Skip Empties
-    if (line.empty()) continue;
-    if (line.c_str()[0] == '#') continue;
-
-    // Try Parameter Reads
-    int parstatus = ReadParameters(line);
-    int fakstatus = ReadFakeDataPars(line);
-
-    // Show line if bad to help user
-    if (parstatus == kErrorStatus ||
-	fakstatus == kErrorStatus ){
-      ERR(FTL) << "Bad Parameter Input in cardfile " << fCardFile
-	       << " at line " << linecount << "!" << std::endl;
-      LOG(FIT) << line << std::endl;
-      throw;
-    }
-  }
-
-  return;
-};
-
-int SystematicRoutines::ReadParameters(std::string parstring){
-
-  std::string inputspec = "RW Dial Inputs Syntax \n"
-    "free input w/ limits: TYPE  NAME  START  MIN  MAX  STEP  [STATE] \n"
-    "fix  input: TYPE  NAME  VALUE  [STATE] \n"
-    "free input w/o limits: TYPE  NAME  START  FREE,[STATE] \n"
-    "Allowed Types: \n"
-    "neut_parameter,niwg_parameter,t2k_parameter,"
-    "nuwro_parameter,gibuu_parameter";
-
-  // Check sample input
-  if (parstring.find("parameter") == std::string::npos) return kGoodStatus;
-
-  // Parse inputs
-  std::vector<std::string> strvct = GeneralUtils::ParseToStr(parstring, " ");
-
-  // Skip if comment or parameter somewhere later in line
-  if (strvct[0].c_str()[0] == '#' ||
-      strvct[0].find("parameter") == std::string::npos){
-    return kGoodStatus;
-  }
-
-  // Check length
-  if (strvct.size() < 3){
-    ERR(FTL) << "Input rw dials need to provide at least 3 inputs." << std::endl;
-    std::cout << inputspec << std::endl;
-    return kErrorStatus;
-  }
-
-  // Setup default inputs
-  std::string partype = strvct[0];
-  std::string parname = strvct[1];
-  double parval  = GeneralUtils::StrToDbl(strvct[2]);
-  double minval  = parval - 1.0;
-  double maxval  = parval + 1.0;
-  double stepval = 1.0;
-  std::string state = "FIX"; //[DEFAULT]
-
-  // Check Type
-  if (FitBase::ConvDialType(partype) == kUNKNOWN){
-    ERR(FTL) << "Unknown parameter type! " << partype << std::endl;
-    std::cout << inputspec << std::endl;
-    return kErrorStatus;
-  }
-
-  // Check Parameter Name
-  if (FitBase::GetDialEnum(partype, parname) == -1){
-    ERR(FTL) << "Bad RW parameter name! " << partype << " " << parname << std::endl;
-    std::cout << inputspec << std::endl;
-    return kErrorStatus;
-  }
-
-  // Option Extra (No Limits)
-  if (strvct.size() == 4){
-    state = strvct[3];
-  }
-
-  // Check for weirder inputs
-  if (strvct.size() > 4 && strvct.size() < 6){
-    ERR(FTL) << "Provided incomplete limits for " << parname << std::endl;
-    std::cout << inputspec << std::endl;
-    return kErrorStatus;
-  }
-
-  // Option Extra (With limits and steps)
-  if (strvct.size() >= 6){
-    minval  = GeneralUtils::StrToDbl(strvct[3]);
-    maxval  = GeneralUtils::StrToDbl(strvct[4]);
-    stepval = GeneralUtils::StrToDbl(strvct[5]);
-  }
-
-  // Option Extra (dial state after limits)
-  if (strvct.size() == 7){
-    state = strvct[6];
-  }
-
-  // Run Parameter Conversion if needed
-  if (state.find("ABS") != std::string::npos){
-    parval  = FitBase::RWAbsToSigma( partype, parname, parval  );
-    minval  = FitBase::RWAbsToSigma( partype, parname, minval  );
-    maxval  = FitBase::RWAbsToSigma( partype, parname, maxval  );
-    stepval = FitBase::RWAbsToSigma( partype, parname, stepval );
-  } else if (state.find("FRAC") != std::string::npos){
-    parval  = FitBase::RWFracToSigma( partype, parname, parval  );
-    minval  = FitBase::RWFracToSigma( partype, parname, minval  );
-    maxval  = FitBase::RWFracToSigma( partype, parname, maxval  );
-    stepval = FitBase::RWFracToSigma( partype, parname, stepval );
-  }
-
-  // Check no repeat params
-  if (std::find(fParams.begin(), fParams.end(), parname) != fParams.end()){
-    ERR(FTL) << "Duplicate parameter names given for " << parname << std::endl;
-    throw;
-  }
-
-  // Setup Containers
-  fParams.push_back(parname);
-
-  fTypeVals[parname]  = FitBase::ConvDialType(partype);
-
-  fStartVals[parname] = parval;
-  fCurVals[parname]   = fStartVals[parname];
-
-  fErrorVals[parname] = 0.0;
-
-  fStateVals[parname] = state;
-
-  bool fixstate = state.find("FIX") != std::string::npos;
-  fFixVals[parname]      = fixstate;
-  fStartFixVals[parname] = fFixVals[parname];
-
-  fMinVals[parname]  = minval;
-  fMaxVals[parname]  = maxval;
-  fStepVals[parname] = stepval;
-
-  // Print the parameter
-  LOG(MIN) << "Read Parameter " << parname << " " << parval << " "
-	   << minval << " " << maxval << " "
-	   << stepval << " " << state << std::endl;
-
-  // Tell reader its all good
-  return kGoodStatus;
-}
-
-//*******************************************
-int SystematicRoutines::ReadFakeDataPars(std::string parstring){
-//******************************************
-
-  std::string inputspec = "Fake Data Dial Inputs Syntax \n"
-    "fake value: fake_parameter  NAME  VALUE  \n"
-    "Name should match dialnames given in actual dial specification.";
-
-  // Check sample input
-  if (parstring.find("fake_parameter") == std::string::npos)
-    return kGoodStatus;
-
-  // Parse inputs
-  std::vector<std::string> strvct = GeneralUtils::ParseToStr(parstring, " ");
-
-  // Skip if comment or parameter somewhere later in line
-  if (strvct[0].c_str()[0] == '#' ||
-      strvct[0] == "fake_parameter"){
-    return kGoodStatus;
-  }
-
-  // Check length
-  if (strvct.size() < 3){
-    ERR(FTL) << "Fake dials need to provide at least 3 inputs." << std::endl;
-    std::cout << inputspec << std::endl;
-    return kErrorStatus;
-  }
-
-  // Read Inputs
-  std::string parname = strvct[1];
-  double      parval  = GeneralUtils::StrToDbl(strvct[2]);
-
-  // Setup Container
-  fFakeVals[parname] = parval;
-
-  // Print the fake parameter
-  LOG(MIN) << "Read Fake Parameter " << parname << " " << parval << std::endl;
-
-  // Tell reader its all good
-  return kGoodStatus;
-}
-
-//******************************************
-int SystematicRoutines::ReadSamples(std::string samstring){
-//******************************************
-  const static std::string inputspec =
-      "\tsample <sample_name> <input_type>:inputfile.root [OPTS] "
-      "[norm]\nsample_name: Name "
-      "of sample to include. e.g. MiniBooNE_CCQE_XSec_1DQ2_nu\ninput_type: The "
-      "input event format. e.g. NEUT, GENIE, EVSPLN, ...\nOPTS: Additional, "
-      "optional sample options.\nnorm: Additional, optional sample "
-      "normalisation factor.";
-
-  // Check sample input
-  if (samstring.find("sample") == std::string::npos)
-    return kGoodStatus;
-
-  // Parse inputs
-  std::vector<std::string> strvct = GeneralUtils::ParseToStr(samstring, " ");
-
-  // Skip if comment or parameter somewhere later in line
-  if (strvct[0].c_str()[0] == '#' ||
-      strvct[0] != "sample"){
-    return kGoodStatus;
-  }
-
-  // Check length
-  if (strvct.size() < 3){
-    ERR(FTL) << "Sample need to provide at least 3 inputs." << std::endl;
-    return kErrorStatus;
-  }
-
-  // Setup default inputs
-  std::string samname = strvct[1];
-  std::string samfile = strvct[2];
-
-  if (samfile == "FIX") {
-    ERR(FTL) << "Input filename was \"FIX\", this line is probably malformed "
-                "in the input card file. Line:\'"
-             << samstring << "\'" << std::endl;
-    ERR(FTL) << "Expect sample lines to look like:\n\t" << inputspec
-             << std::endl;
-
-    throw;
-  }
-
-  std::string samtype = "DEFAULT";
-  double      samnorm = 1.0;
-
-  // Optional Type
-  if (strvct.size() > 3) {
-    samtype = strvct[3];
-    //    samname += "_"+samtype;
-    // Also get rid of the / and replace it with underscore because it might not be supported character
-    //    while (samname.find("/") != std::string::npos) {
-    //      samname.replace(samname.find("/"), 1, std::string("_"));
-    //    }
-  }
-
-  // Optional Norm
-  if (strvct.size() > 4) samnorm = GeneralUtils::StrToDbl(strvct[4]);
-
-  // Add Sample Names as Norm Dials
-  std::string normname = samname + "_norm";
-
-  // Check no repeat params
-  if (std::find(fParams.begin(), fParams.end(), normname) != fParams.end()){
-    ERR(FTL) << "Duplicate samples given for " << samname << std::endl;
-    throw;
-  }
-
-  fParams.push_back(normname);
-
-  fTypeVals[normname]  = kNORM;
-  fStartVals[normname] = samnorm;
-  fCurVals[normname]   = fStartVals[normname];
-  fErrorVals[normname] = 0.0;
-
-  fMinVals[normname]  = 0.1;
-  fMaxVals[normname]  = 10.0;
-  fStepVals[normname] = 0.5;
-
-  bool state = samtype.find("FREE") == std::string::npos;
-  fFixVals[normname]      = state;
-  fStartFixVals[normname] = state;
-
-  // Print read in
-  LOG(MIN) << "Read sample " << samname << " "
-	   << samfile << " " << samtype << " "
-	   << samnorm << std::endl;
-
-  // Tell reader its all good
-  return kGoodStatus;
-}
-
 /*
   Setup Functions
 */
 //*************************************
 void SystematicRoutines::SetupRWEngine(){
 //*************************************
 
   for (UInt_t i = 0; i < fParams.size(); i++){
     std::string name = fParams[i];
     FitBase::GetRW() -> IncludeDial(name, fTypeVals.at(name) );
   }
   UpdateRWEngine(fStartVals);
 
   return;
 }
 
 //*************************************
 void SystematicRoutines::SetupFCN(){
 //*************************************
 
   LOG(FIT)<<"Making the jointFCN"<<std::endl;
   if (fSampleFCN) delete fSampleFCN;
   fSampleFCN = new JointFCN(fOutputRootFile);
   SetFakeData();
 
   return;
 }
 
 
 //*************************************
 void SystematicRoutines::SetFakeData(){
 //*************************************
 
   if (fFakeDataInput.empty()) return;
 
   if (fFakeDataInput.compare("MC") == 0){
 
     LOG(FIT)<<"Setting fake data from MC starting prediction." <<std::endl;
     UpdateRWEngine(fFakeVals);
 
     FitBase::GetRW()->Reconfigure();
     fSampleFCN->ReconfigureAllEvents();
     fSampleFCN->SetFakeData("MC");
 
     UpdateRWEngine(fCurVals);
 
     LOG(FIT)<<"Set all data to fake MC predictions."<<std::endl;
   } else {
     fSampleFCN->SetFakeData(fFakeDataInput);
   }
 
   return;
 }
 
 //*****************************************
 void SystematicRoutines::GetCovarFromFCN(){
 //*****************************************
   LOG(FIT) << "Loading ParamPull objects from FCN to build covar" << std::endl;
 
   // Make helperstring
   std::ostringstream helperstr;
 
   // Keep track of what is being thrown
   std::map<std::string, std::string> dialthrowhandle;
 
   // Get Covariance Objects from FCN
   std::list<ParamPull*> inputpulls = fSampleFCN->GetPullList();
   for (PullListConstIter iter = inputpulls.begin();
        iter != inputpulls.end(); iter++){
 
     ParamPull* pull = (*iter);
 
     if (pull->GetType().find("THROW")){
       fInputThrows.push_back(pull);
       fInputCovar.push_back(pull->GetFullCovarMatrix());
       fInputDials.push_back(pull->GetDataHist());
 
       LOG(FIT) << "Read ParamPull: " << pull->GetName() << " " << pull->GetType() << std::endl;
     }
 
     TH1D dialhist = pull->GetDataHist();
     TH1D minhist  = pull->GetMinHist();
     TH1D maxhist  = pull->GetMaxHist();
     TH1I typehist = pull->GetDialTypes();
 
     for (int i = 0; i < dialhist.GetNbinsX(); i++){
       std::string name = std::string(dialhist.GetXaxis()->GetBinLabel(i+1));
       dialthrowhandle[name] = pull->GetName();
 
       if (fCurVals.find(name) == fCurVals.end()){
 
       	// Add to Containers
       	fParams.push_back(name);
       	fCurVals[name]      = dialhist.GetBinContent(i+1);
       	fStartVals[name]    = dialhist.GetBinContent(i+1);
       	fMinVals[name]      = minhist.GetBinContent(i+1);
       	fMaxVals[name]      = maxhist.GetBinContent(i+1);
       	fStepVals[name]     = 1.0;
       	fFixVals[name]      = false;
       	fStartFixVals[name] = false;
       	fTypeVals[name]     = typehist.GetBinContent(i+1);
       	fStateVals[name]    = "FREE" + pull->GetType();
 
       	// Maker Helper
       	helperstr << std::string(16, ' ' ) << FitBase::ConvDialType(fTypeVals[name]) << " "
       		  << name << " " << fMinVals[name] << " "
       		  << fMaxVals[name] << " " << fStepVals[name] << " " << fStateVals[name]
 		  << std::endl;
       }
     }
   }
 
   // Check if no throws given
   if (fInputThrows.empty()){
 
     ERR(WRN) << "No covariances given to nuissyst" << std::endl;
     ERR(WRN) << "Pushing back an uncorrelated gaussian throw error for each free parameter using step size" << std::endl;
 
     for (UInt_t i = 0; i < fParams.size(); i++){
       std::string syst     = fParams[i];
       if (fFixVals[syst]) continue;
 
       // Make Terms
       std::string name     = syst + "_pull";
 
       std::ostringstream pullterm;
       pullterm << "DIAL:" << syst << ";"
 	       << fStartVals[syst] << ";"
 	       << fStepVals[syst];
 
       std::string type = "GAUSTHROW/NEUT";
 
       // Push Back Pulls
       ParamPull* pull = new ParamPull( name, pullterm.str(), type );
       fInputThrows.push_back(pull);
       fInputCovar.push_back(pull->GetFullCovarMatrix());
       fInputDials.push_back(pull->GetDataHist());
 
       // Print Whats added
       ERR(WRN) << "Added ParamPull : " << name << " " << pullterm.str() << " " << type << std::endl;
 
       // Add helper string for future fits
       helperstr << std::string(16, ' ' ) << "covar " << name << " " << pullterm.str() << " " << type << std::endl;
 
       // Keep Track of Throws
       dialthrowhandle[syst] = pull->GetName();
     }
   }
 
   // Print Helper String
   if (!helperstr.str().empty()){
     LOG(FIT) << "To remove these statements in future studies, add the lines below to your card:" << std::endl;
     // Can't use the logger properly because this can be multi-line. Use cout and added spaces to look better!
     std::cout << helperstr.str();
     sleep(2);
   }
 
 
 
   // Print Throw State
   for (UInt_t i = 0; i < fParams.size(); i++){
     std::string syst = fParams[i];
     if (dialthrowhandle.find(syst) != dialthrowhandle.end()){
       LOG(FIT) << "Dial " << i << ". " << setw(40) << syst << " = THROWING with " << dialthrowhandle[syst] << std::endl;
     } else {
       LOG(FIT) << "Dial " << i << ". " << setw(40) << syst << " = FIXED" << std::endl;
     }
   }
 
   // Pause anyway
   sleep(1);
   return;
 }
 
 
 
 
 /*
   Fitting Functions
 */
 //*************************************
 void SystematicRoutines::UpdateRWEngine(std::map<std::string,double>& updateVals){
 //*************************************
 
   for (UInt_t i = 0; i < fParams.size(); i++){
     std::string name = fParams[i];
 
     if (updateVals.find(name) == updateVals.end()) continue;
     FitBase::GetRW()->SetDialValue(name,updateVals.at(name));
   }
 
   FitBase::GetRW()->Reconfigure();
   return;
 }
 
 //*************************************
 void SystematicRoutines::PrintState(){
 //*************************************
   LOG(FIT)<<"------------"<<std::endl;
 
   // Count max size
   int maxcount = 0;
   for (UInt_t i = 0; i < fParams.size(); i++){
     maxcount = max(int(fParams[i].size()), maxcount);
   }
 
   // Header
   LOG(FIT) << " #    " << left << setw(maxcount) << "Parameter "
 	   << " = "
 	   << setw(10) << "Value"     << " +- "
 	   << setw(10) << "Error"     << " "
 	   << setw(8)  << "(Units)"   << " "
 	   << setw(10) << "Conv. Val" << " +- "
 	   << setw(10) << "Conv. Err" << " "
 	   << setw(8)  << "(Units)"   << std::endl;
 
   // Parameters
   for (UInt_t i = 0; i < fParams.size(); i++){
     std::string syst = fParams.at(i);
 
     std::string typestr  = FitBase::ConvDialType(fTypeVals[syst]);
     std::string curunits = "(sig.)";
     double      curval   = fCurVals[syst];
     double      curerr   = fErrorVals[syst];
 
     if (fStateVals[syst].find("ABS") != std::string::npos){
       curval = FitBase::RWSigmaToAbs(typestr, syst, curval);
       curerr = (FitBase::RWSigmaToAbs(typestr, syst, curerr) -
 		FitBase::RWSigmaToAbs(typestr, syst, 0.0));
       curunits = "(Abs.)";
     } else if (fStateVals[syst].find("FRAC") != std::string::npos){
       curval = FitBase::RWSigmaToFrac(typestr, syst, curval);
       curerr = (FitBase::RWSigmaToFrac(typestr, syst, curerr) -
 		FitBase::RWSigmaToFrac(typestr, syst, 0.0));
       curunits = "(Frac)";
     }
 
     std::string convunits = "(" + FitBase::GetRWUnits(typestr, syst) + ")";
     double      convval   = FitBase::RWSigmaToAbs(typestr, syst, curval);
     double      converr   = (FitBase::RWSigmaToAbs(typestr, syst, curerr) -
 			     FitBase::RWSigmaToAbs(typestr, syst, 0.0));
 
     std::ostringstream curparstring;
 
     curparstring << " " << setw(3) << left
 		 << i << ". "
 		 << setw(maxcount) << syst << " = "
 		 << setw(10) << curval     << " +- "
 		 << setw(10) << curerr     << " "
 		 << setw(8)  << curunits   << " "
                  << setw(10) << convval    << " +- "
                  << setw(10) << converr    << " "
                  << setw(8)  << convunits;
 
 
     LOG(FIT) << curparstring.str() << std::endl;
   }
 
   LOG(FIT)<<"------------"<<std::endl;
   double like = fSampleFCN->GetLikelihood();
   LOG(FIT) << std::left << std::setw(46) << "Likelihood for JointFCN: " << like << std::endl;
   LOG(FIT)<<"------------"<<std::endl;
 }
 
 
 
 /*
   Write Functions
 */
 //*************************************
 void SystematicRoutines::SaveResults(){
 //*************************************
   if (!fOutputRootFile)
     fOutputRootFile = new TFile(fCompKey.GetS("outputfile").c_str(), "RECREATE");  
 
   fOutputRootFile->cd();
 
   SaveCurrentState();
 
 }
 
 //*************************************
 void SystematicRoutines::SaveCurrentState(std::string subdir){
 //*************************************
 
   LOG(FIT)<<"Saving current full FCN predictions" <<std::endl;
 
   // Setup DIRS
   TDirectory* curdir = gDirectory;
   if (!subdir.empty()){
     TDirectory* newdir =(TDirectory*) gDirectory->mkdir(subdir.c_str());
     newdir->cd();
   }
 
   FitBase::GetRW()->Reconfigure();
   fSampleFCN->ReconfigureAllEvents();
   fSampleFCN->Write();
 
   // Change back to current DIR
   curdir->cd();
 
   return;
 }
 
 //*************************************
 void SystematicRoutines::SaveNominal(){
 //*************************************
   if (!fOutputRootFile)
     fOutputRootFile = new TFile(fCompKey.GetS("outputfile").c_str(), "RECREATE");
 
   fOutputRootFile->cd();
 
   LOG(FIT)<<"Saving Nominal Predictions (be cautious with this)" <<std::endl;
   FitBase::GetRW()->Reconfigure();
   SaveCurrentState("nominal");
 
 };
 
 //*************************************
 void SystematicRoutines::SavePrefit(){
 //*************************************
   if (!fOutputRootFile)
     fOutputRootFile = new TFile(fCompKey.GetS("outputfile").c_str(), "RECREATE");
 
   fOutputRootFile->cd();
 
   LOG(FIT)<<"Saving Prefit Predictions"<<std::endl;
   UpdateRWEngine(fStartVals);
   SaveCurrentState("prefit");
   UpdateRWEngine(fCurVals);
 
 };
 
 
 /*
   MISC Functions
 */
 //*************************************
 int SystematicRoutines::GetStatus(){
 //*************************************
 
   return 0;
 }
 
 //*************************************
 void SystematicRoutines::SetupCovariance(){
 //*************************************
 
   // Remove covares if they exist
   if (fCovar) delete fCovar;
   if (fCovarFree) delete fCovarFree;
   if (fCorrel) delete fCorrel;
   if (fCorrelFree) delete fCorrelFree;
   if (fDecomp) delete fDecomp;
   if (fDecompFree) delete fDecompFree;
 
   int NFREE = 0;
   int NDIM = 0;
 
   // Get NFREE from min or from vals (for cases when doing throws)
   NDIM = fParams.size();
   for (UInt_t i = 0; i < fParams.size(); i++){
     if (!fFixVals[fParams[i]]) NFREE++;
   }
 
   if (NDIM == 0) return;
 
   fCovar = new TH2D("covariance","covariance",NDIM,0,NDIM,NDIM,0,NDIM);
   if (NFREE > 0){
     fCovarFree = new TH2D("covariance_free",
 			      "covariance_free",
 			      NFREE,0,NFREE,
 			      NFREE,0,NFREE);
   }
 
   // Set Bin Labels
   int countall = 0;
   int countfree = 0;
   for (UInt_t i = 0; i < fParams.size(); i++){
 
     fCovar->GetXaxis()->SetBinLabel(countall+1,fParams[i].c_str());
     fCovar->GetYaxis()->SetBinLabel(countall+1,fParams[i].c_str());
     countall++;
 
     if (!fFixVals[fParams[i]] and NFREE > 0){
       fCovarFree->GetXaxis()->SetBinLabel(countfree+1,fParams[i].c_str());
       fCovarFree->GetYaxis()->SetBinLabel(countfree+1,fParams[i].c_str());
       countfree++;
     }
   }
 
   fCorrel = PlotUtils::GetCorrelationPlot(fCovar,"correlation");
   fDecomp = PlotUtils::GetDecompPlot(fCovar,"decomposition");
 
   if (NFREE > 0)fCorrelFree = PlotUtils::GetCorrelationPlot(fCovarFree, "correlation_free");
   if (NFREE > 0)fDecompFree = PlotUtils::GetDecompPlot(fCovarFree,"decomposition_free");
 
   return;
 };
 
 //*************************************
 void SystematicRoutines::ThrowCovariance(bool uniformly){
 //*************************************
 
   // Set fThrownVals to all values in currentVals
   for (UInt_t i = 0; i < fParams.size(); i++){
     std::string name = fParams.at(i);
     fThrownVals[name] = fCurVals[name];
   }
 
   for (PullListConstIter iter = fInputThrows.begin();
        iter != fInputThrows.end(); iter++){
     ParamPull* pull = *iter;
 
     pull->ThrowCovariance();
     TH1D dialhist = pull->GetDataHist();
 
     for (int i = 0; i < dialhist.GetNbinsX(); i++){
       std::string name = std::string(dialhist.GetXaxis()->GetBinLabel(i+1));
       if (fCurVals.find(name) != fCurVals.end()){
 	fThrownVals[name] = dialhist.GetBinContent(i+1);
       }
     }
 
     // Reset throw incase pulls are calculated.
     pull->ResetToy();
 
   }
 
   return;
 };
 
 //*************************************
 void SystematicRoutines::PlotLimits(){
 //*************************************
   std::cout << "Plotting Limits" << std::endl;
   if (!fOutputRootFile)
     fOutputRootFile = new TFile(fCompKey.GetS("outputfile").c_str(), "RECREATE");
 
   TDirectory* limfolder = (TDirectory*) fOutputRootFile->mkdir("Limits");
   limfolder->cd();
 
   // Set all parameters at their starting values
   for (UInt_t i = 0; i < fParams.size(); i++){
     fCurVals[fParams[i]] = fStartVals[fParams[i]];
   }
 
   TDirectory* nomfolder = (TDirectory*) limfolder->mkdir("nominal");
   nomfolder->cd();
 
   UpdateRWEngine(fCurVals);
   fSampleFCN->ReconfigureAllEvents();
   fSampleFCN->Write();
 
   limfolder->cd();
   std::vector<std::string> allfolders;
 
 
   // Loop through each parameter
   for (UInt_t i = 0; i < fParams.size(); i++){
     std::string syst = fParams[i];
     std::cout << "Starting Param " << syst << std::endl;
     if (fFixVals[syst]) continue;
 
     // Loop Downwards
     while (fCurVals[syst] > fMinVals[syst]){
       fCurVals[syst] = fCurVals[syst] - fStepVals[syst];
 
       // Check Limit
       if (fCurVals[syst] < fMinVals[syst])
 	fCurVals[syst] = fMinVals[syst];
 
       // Check folder exists
       std::string curvalstring = std::string( Form( (syst + "_%f").c_str(), fCurVals[syst] ) );
       if (std::find(allfolders.begin(), allfolders.end(), curvalstring) != allfolders.end())
 	break;
 
       // Make new folder for variation
       TDirectory* minfolder = (TDirectory*) limfolder->mkdir(Form( (syst + "_%f").c_str(), fCurVals[syst] ) );
       minfolder->cd();
 
       allfolders.push_back(curvalstring);
 
       // Update Iterations
       double *vals = FitUtils::GetArrayFromMap( fParams, fCurVals );
       fSampleFCN->DoEval( vals );
       delete vals;
 
       // Save to folder
       fSampleFCN->Write();
     }
 
     // Reset before next loop
     fCurVals[syst] = fStartVals[syst];
 
     // Loop Upwards now
     while (fCurVals[syst] < fMaxVals[syst]){
       fCurVals[syst] = fCurVals[syst] + fStepVals[syst];
 
       // Check Limit
       if (fCurVals[syst] > fMaxVals[syst])
 	fCurVals[syst] = fMaxVals[syst];
 
       // Check folder exists
       std::string curvalstring = std::string( Form( (syst + "_%f").c_str(), fCurVals[syst] ) );
       if (std::find(allfolders.begin(), allfolders.end(), curvalstring) != allfolders.end())
 	break;
 
       // Make new folder
       TDirectory* maxfolder = (TDirectory*) limfolder->mkdir(Form( (syst + "_%f").c_str(), fCurVals[syst] ) );
       maxfolder->cd();
 
       allfolders.push_back(curvalstring);
 
       // Update Iterations
       double *vals = FitUtils::GetArrayFromMap( fParams, fCurVals );
       fSampleFCN->DoEval( vals );
       delete vals;
 
       // Save to file
       fSampleFCN->Write();
     }
 
     // Reset before leaving
     fCurVals[syst] = fStartVals[syst];
     UpdateRWEngine(fCurVals);
   }
 
   return;
 }
 
 //*************************************
 void SystematicRoutines::Run(){
 //*************************************
 
   std::cout << "Running routines "<< std::endl;
   fRoutines = GeneralUtils::ParseToStr(fStrategy,",");
 
   for (UInt_t i = 0; i < fRoutines.size(); i++){
 
     std::string routine = fRoutines.at(i);
     int fitstate = kFitUnfinished;
     LOG(FIT)<<"Running Routine: "<<routine<<std::endl;
 
     if (routine.compare("PlotLimits") == 0) PlotLimits();
     else if (routine.compare("ErrorBands") == 0) GenerateErrorBands();
     else if (routine.compare("ThrowErrors") == 0) GenerateThrows();
     else if (routine.compare("MergeErrors") == 0) MergeThrows();
     else {
       std::cout << "Unknown ROUTINE : " << routine << std::endl;
     }
 
     // If ending early break here
     if (fitstate == kFitFinished || fitstate == kNoChange){
       LOG(FIT) << "Ending fit routines loop." << std::endl;
       break;
     }
   }
 
   return;
 }
 
 void SystematicRoutines::GenerateErrorBands(){
   GenerateThrows();
   MergeThrows();
 }
 
 //*************************************
 void SystematicRoutines::GenerateThrows(){
 //*************************************
 
 
   TFile* tempfile = new TFile((fOutputFile + ".throws.root").c_str(),"RECREATE");
   tempfile->cd();
 
   int nthrows = fNThrows;
   int startthrows = fStartThrows;
   int endthrows = startthrows + nthrows;
 
   if (nthrows < 0) nthrows = endthrows;
   if (startthrows < 0) startthrows = 0;
   if (endthrows < 0) endthrows = startthrows + nthrows;
 
-  int seed = (gRandom->Uniform(0.0,1.0)*100000 + 100000000*(startthrows + endthrows) + time(NULL) + int(getpid()) );
+  // Setting Seed
+  // Matteo Mazzanti's Fix
+  struct timeval mytime;
+  gettimeofday(&mytime, NULL);
+  Double_t seed = time(NULL) + int(getpid())+ (mytime.tv_sec * 1000.) + (mytime.tv_usec / 1000.);
   gRandom->SetSeed(seed);
+
+  //  int seed = (gRandom->Uniform(0.0,1.0)*100000 + 100000000*(startthrows + endthrows) + time(NULL) + int(getpid()) );
+  //  gRandom->SetSeed(seed);
   LOG(FIT) << "Using Seed : " << seed << std::endl;
   LOG(FIT) << "nthrows = " << nthrows << std::endl;
   LOG(FIT) << "startthrows = " << startthrows << std::endl;
   LOG(FIT) << "endthrows = " << endthrows << std::endl;
 
 
 
   UpdateRWEngine(fCurVals);
   fSampleFCN->ReconfigureAllEvents();
 
   if (startthrows == 0){
     LOG(FIT) << "Making nominal " << std::endl;
     TDirectory* nominal = (TDirectory*) tempfile->mkdir("nominal");
     nominal->cd();
     fSampleFCN->Write();
   }
 
   LOG(SAM) << "nthrows = " << nthrows << std::endl;
   LOG(SAM) << "startthrows = " << startthrows << std::endl;
   LOG(SAM) << "endthrows = " << endthrows << std::endl;
 
   TTree* parameterTree = new TTree("throws","throws");
   double chi2;
   for (UInt_t i = 0; i < fParams.size(); i++)
     parameterTree->Branch(fParams[i].c_str(), &fThrownVals[fParams[i]], (fParams[i] + "/D").c_str());
   parameterTree->Branch("chi2",&chi2,"chi2/D");
   fSampleFCN->CreateIterationTree("error_iterations", FitBase::GetRW());
 
   // Would anybody actually want to do uniform throws of any parameter??
   bool uniformly = FitPar::Config().GetParB("error_uniform");
 
   // Run Throws and save
   for (Int_t i = 0; i < endthrows+1; i++){
 
     LOG(FIT) << "Loop " << i << std::endl;
     ThrowCovariance(uniformly);
     if (i < startthrows) continue;
     if (i == 0) continue;
     LOG(FIT) << "Throw " << i << " ================================" << std::endl;
     // Generate Random Parameter Throw
     //    ThrowCovariance(uniformly);
 
     TDirectory* throwfolder = (TDirectory*)tempfile->mkdir(Form("throw_%i",i));
     throwfolder->cd();
 
     // Run Eval
     double *vals = FitUtils::GetArrayFromMap( fParams, fThrownVals );
     chi2 = fSampleFCN->DoEval( vals );
     delete vals;
 
     // Save the FCN
     fSampleFCN->Write();
 
     parameterTree->Fill();
   }
 
   tempfile->cd();
   fSampleFCN->WriteIterationTree();
 
   tempfile->Close();
 }
 
 void SystematicRoutines::MergeThrows(){
 
 
     fOutputRootFile = new TFile(fCompKey.GetS("outputfile").c_str(), "RECREATE");
     fOutputRootFile->cd();
 
 
   // Make a container folder
   TDirectory* errorDIR = (TDirectory*) fOutputRootFile->mkdir("error_bands");
   errorDIR->cd();
 
   TDirectory* outnominal = (TDirectory*) fOutputRootFile->mkdir("nominal_throw");
   outnominal->cd();
 
   // Split Input Files
   if (!fThrowString.empty()) fThrowList = GeneralUtils::ParseToStr(fThrowString,",");
 
   // Add default if no throwlist given
   if (fThrowList.size() < 1) fThrowList.push_back( fOutputFile + ".throws.root" ); 
 
   /// Save location of file containing nominal
   std::string nominalfile;
   bool nominalfound;
 
   // Loop over files and check they exist.
   for (uint i = 0; i < fThrowList.size(); i++){
     std::string file = fThrowList[i];
     bool found = false;
 
     // normal
     std::string newfile = file;
     TFile* throwfile = new TFile(file.c_str(),"READ");
     if (throwfile and !throwfile->IsZombie()){ 
         found = true;
     }
 
     // normal.throws.root
     if (!found){
       newfile = file + ".throws.root";
       throwfile = new TFile((file + ".throws.root").c_str(),"READ");
       if (throwfile and !throwfile->IsZombie()) {
         found = true;
       }
     }
 
     // If its found save to throwlist, else save empty.
     // Also search for nominal
     if (found){
       fThrowList[i] = newfile;
       
       LOG(FIT) << "Throws File :" << newfile << std::endl;
 
       // Find input which contains nominal
       if (throwfile->Get("nominal")){
         nominalfound = true;
         nominalfile = newfile;
       }
 
       throwfile->Close();
 
     } else {
       fThrowList[i] = "";
     }
 
     delete throwfile;
   }
 
   // Make sure we have a nominal file
   if (!nominalfound or nominalfile.empty()){
     ERR(FTL) << "No nominal found when mergining! Exiting!" << std::endl;
     throw;  
   }
 
   
 
     // Get the nominal throws file
   TFile* tempfile = new TFile((nominalfile).c_str(),"READ");
   tempfile->cd();
   TDirectory* nominal = (TDirectory*)tempfile->Get("nominal");
   // int nthrows = FitPar::Config().GetParI("error_throws");
   bool uniformly = FitPar::Config().GetParB("error_uniform");
 
   // Check percentage of bad files is okay.
   int badfilecount = 0;
   for (uint i = 0; i < fThrowList.size(); i++){
     if (!fThrowList[i].empty()){
       LOG(FIT) << "Loading Throws From File " << i << " : " 
 	       << fThrowList[i] << std::endl;
     } else {
       badfilecount++;
     }
   }
 
   // Check we have at least one good file
   if ((uint)badfilecount == fThrowList.size()){
     ERR(FTL) << "Found no good throw files for MergeThrows" << std::endl;
     throw;
   } else if (badfilecount > fThrowList.size()*0.25){
     ERR(WRN) << "Over 25% of your throw files are dodgy. Please check this is okay!" << std::endl;
     ERR(WRN) << "Will continue for the time being..." << std::endl;
     sleep(5);
   }
 
   // Now go through the keys in the temporary file and look for TH1D, and TH2D plots
   TIter next(nominal->GetListOfKeys());
   TKey *key;
   while ((key = (TKey*)next())) {
     TClass *cl = gROOT->GetClass(key->GetClassName());
     if (!cl->InheritsFrom("TH1D") and !cl->InheritsFrom("TH2D")) continue;
     TH1* baseplot = (TH1D*)key->ReadObj();
     std::string plotname = std::string(baseplot->GetName());
     LOG(FIT) << "Creating error bands for " << plotname;
     if (LOG_LEVEL(FIT)){
       if (!uniformly) std::cout << " : Using COVARIANCE Throws! " << std::endl;
       else std::cout << " : Using UNIFORM THROWS!!! " << std::endl;
     }
 
     int nbins = 0;
     if (cl->InheritsFrom("TH1D")) nbins = ((TH1D*)baseplot)->GetNbinsX();
     else nbins = ((TH1D*)baseplot)->GetNbinsX()* ((TH1D*)baseplot)->GetNbinsY();
 
     // Setup TProfile with RMS option
     TProfile* tprof = new TProfile((plotname + "_prof").c_str(),(plotname + "_prof").c_str(),nbins, 0, nbins, "S");
 
     // Setup The TTREE
     double* bincontents;
     bincontents = new double[nbins];
 
     double* binlowest;
     binlowest = new double[nbins];
 
     double* binhighest;
     binhighest = new double[nbins];
 
     errorDIR->cd();
     TTree* bintree = new TTree((plotname + "_tree").c_str(), (plotname + "_tree").c_str());
     for (Int_t i = 0; i < nbins; i++){
       bincontents[i] = 0.0;
       binhighest[i] = 0.0;
       binlowest[i] = 0.0;
       bintree->Branch(Form("content_%i",i),&bincontents[i],Form("content_%i/D",i));
     }
 
     // Make new throw plot
     TH1* newplot;
 
     // Run Throw Merging.
     for (UInt_t i = 0; i < fThrowList.size(); i++){
 
       TFile* throwfile = new TFile(fThrowList[i].c_str(), "READ");
 
       // Loop over all throws in a folder
       TIter nextthrow(throwfile->GetListOfKeys());
       TKey *throwkey;
       while ((throwkey = (TKey*)nextthrow())) {
         
         // Skip non throw folders
         if (std::string(throwkey->GetName()).find("throw_") == std::string::npos) continue;
 
         // Get Throw DIR
         TDirectory* throwdir = (TDirectory*)throwkey->ReadObj();
 
         // Get Plot From Throw
         newplot = (TH1*)throwdir->Get(plotname.c_str());
         if (!newplot) continue;
 
         // Loop Over Plot
         for (Int_t j = 0; j < nbins; j++){
           tprof->Fill(j+0.5, newplot->GetBinContent(j+1));
           bincontents[j] = newplot->GetBinContent(j+1);
 
           if (bincontents[j] < binlowest[j] or i == 0) binlowest[j] = bincontents[j];
           if (bincontents[j] > binhighest[j] or i == 0) binhighest[j] = bincontents[j];
         }
 
         errorDIR->cd();
         bintree->Fill();
       }
+
+      throwfile->Close();
+      delete throwfile;
     }
 
     errorDIR->cd();
 
     if (uniformly){
       LOG(FIT) << "Uniformly Calculating Plot Errors!" << std::endl;
     }
 
     TH1* statplot = (TH1*) baseplot->Clone();
 
     for (Int_t j = 0; j < nbins; j++){
 
       if (!uniformly){
 //	if ((baseplot->GetBinError(j+1)/baseplot->GetBinContent(j+1)) < 1.0) {
 	  //	  baseplot->SetBinError(j+1,sqrt(pow(tprof->GetBinError(j+1),2) + pow(baseplot->GetBinError(j+1),2)));
 	//	} else {
 	baseplot->SetBinContent(j+1,tprof->GetBinContent(j+1));
 	baseplot->SetBinError(j+1,tprof->GetBinError(j+1));
 	  //	}
       } else {
       	baseplot->SetBinContent(j+1, 0.0);//(binlowest[j] + binhighest[j]) / 2.0);
         baseplot->SetBinError(j+1, 0.0); //(binhighest[j] - binlowest[j])/2.0);
       }
     }
 
     errorDIR->cd();
     baseplot->Write();
     tprof->Write();
     bintree->Write();
 
     outnominal->cd();
     for (int i = 0; i < nbins; i++){
       baseplot->SetBinError(i+1, sqrt(pow(statplot->GetBinError(i+1),2) + pow(baseplot->GetBinError(i+1),2)));
     }
     baseplot->Write();
     
     delete statplot;
     delete baseplot;
     delete tprof;
     delete bintree;
     delete [] bincontents;
   }
 
   return;
 };
diff --git a/src/Routines/SystematicRoutines.h b/src/Routines/SystematicRoutines.h
index 97737aa..f726e07 100755
--- a/src/Routines/SystematicRoutines.h
+++ b/src/Routines/SystematicRoutines.h
@@ -1,267 +1,267 @@
 // Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret
 
 /*******************************************************************************
 *    This file is part of NUISANCE.
 *
 *    NUISANCE is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    NUISANCE is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with NUISANCE.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
 
 #ifndef SYSTEMATIC_ROUTINES_H
 #define SYSTEMATIC_ROUTINES_H
 
 /*!
  *  \addtogroup Minimizer
  *  @{
  */
 
 #include "TH1.h"
 #include "TF1.h"
 #include "TMatrixD.h"
 #include "TVectorD.h"
 #include "TSystem.h"
 #include "TFile.h"
 #include "TProfile.h"
 
-
+#include <sys/time.h>
 #include <vector>
 #include <string>
 #include <iostream>
 #include <sstream>
 #include <cstring>
 
 #include "FitEvent.h"
 #include "JointFCN.h"
-#include "FitParameters.h"
+
 #include "ParserUtils.h"
 
 enum minstate {
   kErrorStatus = -1,
   kGoodStatus,
   kFitError,
   kNoChange,
   kFitFinished,
   kFitUnfinished,
   kStateChange,
 };
 
 //*************************************
 //! Collects all possible fit routines into a single class to avoid repeated code
 class SystematicRoutines{
 //*************************************
 
 public:
 
   /*
     Constructor/Destructor
   */
 
   //! Constructor reads in arguments given at the command line for the fit here.
   SystematicRoutines(int argc, char* argv[]);
     
   //! Default destructor
   ~SystematicRoutines();
 
   //! Reset everything to default/NULL
   void Init();
   
   /*
     Input Functions
   */
 
   //! Splits the arguments ready for initial setup
   void ParseArgs(int argc, char* argv[]);
 
   //! Sorts out configuration and verbosity right at the very start.
   //! Calls readCard to set everything else up.
   void InitialSetup();
 
   //! Loops through each line of the card file and passes it to other read functions
   void ReadCard(std::string cardfile);
 
   //! Check for parameter string in the line and assign the correct type.
   //! Fills maps for each of the parameters
   int ReadParameters(std::string parstring);
 
   //! Reads in fake parameters and assigns them (Requires the parameter to be included as a normal parameter as well)
   int ReadFakeDataPars(std::string parstring);
 
   //! Read in the samples so we can set up the free normalisation dials if required
   int ReadSamples(std::string sampleString);
 
   /*
     Setup Functions
   */
 void SetupSystematicsFromXML();
 
   //! Setup the configuration given the arguments passed at the commandline and card file
   void SetupConfig();
 
   //! Setups up our custom RW engine with all the parameters passed in the card file
   void SetupRWEngine();
 
   //! Setups up the jointFCN.
   void SetupFCN();
 
   //! Sets up the minimizerObj for ROOT. there are cases where this is called repeatedly, e.g. If you are using a brute force scan before using Migrad.
   void SetupFitter(std::string routine);
 
   //! Set the current data histograms in each sample to the fake data.
   void SetFakeData();
 
   //! Setup the covariances with the correct dimensions. At the start this is either uncorrelated or merged given all the input covariances.
   //! At the end of the fit this produces the blank covariances which can then be filled by the minimizerObj with best fit covariances.
   void SetupCovariance();
 
   void GetCovarFromFCN();
   /*
     Fitting Functions
   */
 
   //! Main function to actually start iterating over the different required fit routines
   void Run();
 
   //! Given a new map change the values that the RW engine is currently set to
   void UpdateRWEngine(std::map<std::string,double>& updateVals);
 
   //! Given a single routine (see tutorial for options) run that fit routine now.
   int RunFitRoutine(std::string routine);
 
   //! Print current value
   void PrintState();
   
   //! Performs a fit routine where the input.maxevents is set to a much lower value to try and move closer to the best fit minimum.
   void LowStatRoutine(std::string routine);
 
   //! Perform a chi2 scan in 1D around the current point
   void Create1DScans();
 
   //! Perform a chi2 scan in 2D around the current point
   void Chi2Scan2D();
 
   //! Currently a placeholder NEEDS UPDATING
   void CreateContours();
 
   //! If any currentVals are close to the limits set them to the limit and fix them
   int FixAtLimit();
 
   //! Throw the current covariance of dial values we have, and fill the thrownVals and thrownNorms maps.
   //! If uniformly is true parameters will be thrown uniformly between their upper and lower limits.
   void ThrowCovariance(bool uniformly);
 
   //! Given the covariance we currently have generate error bands by throwing the covariance.
   //! The FitPar config "error_uniform" defines whether to throw using the covariance or uniformly.
   //! The FitPar config "error_throws" defines how many throws are needed.
   //! Currently only supports TH1D plots.
   void GenerateErrorBands();
   
   void GenerateThrows();
   void MergeThrows();
   //! Step through each parameter one by one and create folders containing the MC predictions at each step.
   //! Doesn't handle correlated parameters well
   void PlotLimits();
   
   /*
     Write Functions
   */
 
   //! Save the sample plots for current MC
   //! dir if not empty forces plots to be saved in a subdirectory of outputfile
   void SaveCurrentState(std::string subdir="");
 
   //! Save starting predictions into a seperate folder
   void SaveNominal();
 
   //! Save predictions before the main study is ran into a seperate folder
   void SavePrefit();
 
   //! Save final outputs
   void SaveResults();
   /*
     MISC Functions
   */
 
   //! Get previous fit status from a file
   Int_t GetStatus();
 
 protected:
 
   //! Our Custom ReWeight Object
   FitWeight* rw;
 
   std::string fOutputFile;
   std::string fInputFile;
 
   TFile* fInputRootFile;
   TFile* fOutputRootFile;
 
   //! Flag for whether the fit should be continued if an output file is already found.
   bool fitContinue;
 
   //! Minimizer Object for handling roots different minimizer methods
   JointFCN* fSampleFCN;
 
   int nfreepars;
 
   std::string fCardFile;
 
   std::string fStrategy;
   std::vector<std::string> fRoutines;
   std::string fAllowedRoutines;
   
   std::string fFakeDataInput;
 
   // Input Dial Vals
   //! Vector of dial names
   std::vector<std::string> fParams;
   std::map<std::string, std::string> fStateVals;
   std::map<std::string, double>      fStartVals;
   std::map<std::string, double>      fCurVals;
   std::map<std::string, double>      fErrorVals;
   std::map<std::string, double>      fMinVals;
   std::map<std::string, double>      fMaxVals;
   std::map<std::string, double>      fStepVals;
   std::map<std::string, int>         fTypeVals;
   std::map<std::string, bool>        fFixVals;
   std::map<std::string, bool>        fStartFixVals;
 
   //! Vector of fake parameter names
   std::map<std::string,double> fFakeVals;
 
   //! Map of thrown parameter names and values (After ThrowCovariance)
   std::map<std::string,double> fThrownVals;
 
   TH2D* fCorrel;
   TH2D* fDecomp;
   TH2D* fCovar;
   
   TH2D* fCorrelFree;
   TH2D* fDecompFree;
   TH2D* fCovarFree;
 
   std::list   <ParamPull*>  fInputThrows; //!< Pointers to pull terms
   std::vector <TH1D>        fInputDials; //!< Vector of Input Histograms
   std::vector <TMatrixDSym> fInputCovar; //!< Vector of Input Covariances  
 
   nuiskey fCompKey;
   std::vector<std::string> fThrowList;
   std::string fThrowString;
 
   int fNThrows;
   int fStartThrows;
 
 
 };
 
 /*! @} */
 #endif
diff --git a/src/SciBooNE/SciBooNEUtils.cxx b/src/SciBooNE/SciBooNEUtils.cxx
index 90ad1cf..0a40a65 100644
--- a/src/SciBooNE/SciBooNEUtils.cxx
+++ b/src/SciBooNE/SciBooNEUtils.cxx
@@ -1,278 +1,278 @@
 // Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret
 
 /*******************************************************************************
 *    This file is part of NUISANCE.
 *
 *    NUISANCE is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    NUISANCE is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with NUISANCE.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
 
 #include "SciBooNEUtils.h"
-#include "FitParameters.h"
+
 #include "FitUtils.h"
 
 namespace FitPar{
   double SciBarDensity    = FitPar::Config().GetParD("SciBarDensity");
   double SciBarRecoDist   = FitPar::Config().GetParD("SciBarRecoDist");
   double PenetratingMuonE = FitPar::Config().GetParD("PenetratingMuonEnergy");
   double NumRangeSteps    = FitPar::Config().GetParI("NumRangeSteps");
 }
 
 double SciBooNEUtils::StoppedEfficiency(TH2D *effHist, FitParticle *nu, FitParticle *muon){
 
   double eff = 0.;
 
   if (!effHist) return eff;
   // For Morgan's efficiencies
   // eff = effHist->GetBinContent(effHist->FindBin(FitUtils::p(muon), FitUtils::th(nu, muon)/TMath::Pi()*180.));
   // For Zack's efficiencies
   eff = effHist->GetBinContent(effHist->FindBin(FitUtils::th(nu, muon)/TMath::Pi()*180., FitUtils::p(muon)*1000.));
 
   return eff;
 }
 
 double SciBooNEUtils::PenetratedEfficiency(FitParticle *nu, FitParticle *muon){
 
   double eff = 0.;
 
   if (FitUtils::th(nu, muon)/TMath::Pi()*180. > 50) eff = 0.;
   if (FitUtils::p(muon) < 1.4) eff = 0.;
 
   return eff;
 }
 
 double SciBooNEUtils::BetheBlochCH(double E, double mass){
 
   double beta2 = 1 - mass*mass/E/E;
   double gamma = 1./sqrt(1-beta2);
   double mass_ratio = PhysConst::mass_electron*1000./mass;
   // Argh, have to remember to convert to MeV or you'll hate yourself!
   double I2 = 68.7e-6*68.7e-6;
 
   double w_max = 2*PhysConst::mass_electron*1000.*beta2*gamma*gamma;
   w_max /= 1 + 2*gamma*mass_ratio + mass_ratio*mass_ratio;
 
 
   // Values taken from the PDG for K = 0.307075 MeV mol-1 cm2, mean ionization energy I = 68.7 eV (Polystyrene)
   // <Z/A> = 0.53768 (pdg.lbl.gov/AtomicNuclearProperties)
   double log_term = log(2*PhysConst::mass_electron*1000.*beta2*gamma*gamma*w_max/I2);
   double dedx = 0.307075*0.53768/beta2*(0.5*log_term - beta2);
 
   return dedx;
 }
 
 
 // This function returns an estimate of the range of the particle in scintillator.
 // It uses crude integration and Bethe-Bloch to approximate the range.
 double SciBooNEUtils::RangeInScintillator(FitParticle* particle, int nsteps){
 
   // The particle energy
   double E  = particle->fP.E();
   double M  = particle->fP.M();
   double Ek = E - M;
 
   double step_size = Ek/float(nsteps+1);
   double range = 0;
 
   // Add an offset to make the integral a touch more accurate
   Ek -= step_size/2.;
   for (int i = 0; i < nsteps; ++i){
     
     double dEdx = SciBooNEUtils::BetheBlochCH(Ek+M, M);
     
     Ek -= step_size;
     // dEdx is -ve
     range -= step_size/dEdx;
   }
 
   // Account for density of polystyrene
   range /= FitPar::SciBarDensity;
 
   // Range estimate is in cm
   return range;
 }
 
 
 // Function to calculate the distance the particle travels in scintillator
 bool SciBooNEUtils::PassesDistanceCut(FitParticle* beam, FitParticle* particle){
 
   double dist  = SciBooNEUtils::RangeInScintillator(particle, FitPar::NumRangeSteps);
   double zdist = dist*cos(FitUtils::th(beam, particle));
 
   if (abs(zdist) < FitPar::SciBarRecoDist) return false;
   return true;
 }
 
 
 // Function to return the MainTrk
 int SciBooNEUtils::GetMainTrack(FitEvent *event, TH2D *effHist, FitParticle*& mainTrk, double& weight, bool penetrated){
 
   FitParticle *nu   = event->GetNeutrinoIn();
   int index = 0;
   double thisWeight = 0;
   double highWeight = 0;
   mainTrk = NULL;
 
   // Loop over particles
   for (uint j = 2; j < event->Npart(); ++j){
 
     // Final state only!
     if (!(event->PartInfo(j))->fIsAlive) continue;
     if (event->PartInfo(j)->fNEUTStatusCode != 0) continue;
 
     int PID = event->PartInfo(j)->fPID;
 
     // Only consider pions, muons for now
     if (abs(PID) != 211 && abs(PID) != 13) continue;
 
     // Get the track with the highest weight
     thisWeight = SciBooNEUtils::StoppedEfficiency(effHist, nu, event->PartInfo(j));
     if (thisWeight < highWeight) continue;
     highWeight = thisWeight;
     index      = j;
     mainTrk    = event->PartInfo(j);
   } // end loop over particle stack
   
   // Pass the weight back (don't want to apply a weight twice by accident)
   weight *= highWeight;
 
   return index;
 }
 
 
 void SciBooNEUtils::GetOtherTrackInfo(FitEvent *event, int mainIndex, int& nProtons, int& nPiMus, int& nVertex, FitParticle*& secondTrk){
 
   // Reset everything
   nPiMus      = 0;
   nProtons    = 0;
   nVertex     = 0;
   secondTrk   = NULL;
 
   double highestMom  = 0.;
 
   // Loop over particles
   for (uint j = 2; j < event->Npart(); ++j){
 
     // Don't re-count the main track
     if (j == (uint)mainIndex) continue;
 
     // Final state only!
     if (!(event->PartInfo(j))->fIsAlive) continue;
     if (event->PartInfo(j)->fNEUTStatusCode != 0) continue;
 
     int PID = event->PartInfo(j)->fPID;
 
     // Only consider pions, muons, protons
     if (abs(PID) != 211 && PID != 2212 && abs(PID) != 13) continue;
 
     // Must be reconstructed as a track in SciBooNE
     if (SciBooNEUtils::PassesDistanceCut(event->PartInfo(0), event->PartInfo(j))){
 
       // Keep track of the second highest momentum track
       if (FitUtils::p(event->PartInfo(j)) > highestMom){
 	highestMom = FitUtils::p(event->PartInfo(j));
 	secondTrk  = event->PartInfo(j);
       }
 
       if (PID == 2212) nProtons += 1;
       else nPiMus += 1;
     } else nVertex += 1;
 
   } // end loop over particle stack
 
   return;
 }
 
 
 // NOTE: need to adapt this to allow for penetrating events...
 // Simpler, but gives the same results as in Hirade-san's thesis
 double SciBooNEUtils::CalcThetaPr(FitEvent *event, FitParticle *main, FitParticle *second, bool penetrated){
   
   FitParticle *nu   = event->GetNeutrinoIn();
 
   if (!main || !nu || !second) return -999;
 
   // Construct the vector p_pr = (-p_mux, -p_muy, Enurec - pmucosthetamu)
   // where p_mux, p_muy are the projections of the candidate muon momentum onto the x and y dimension respectively
   double pmu   = main->fP.Vect().Mag();
   double pmu_x = main->fP.Vect().X();
   double pmu_y = main->fP.Vect().Y();
 
   if (penetrated){
     pmu = 1400.;
     double ratio = 1.4/main->fP.Vect().Mag();
     TVector3 mod_mu = main->fP.Vect()*ratio;
     pmu_x = mod_mu.X();
     pmu_y = mod_mu.Y();
   }
 
   double Enuqe = FitUtils::EnuQErec(pmu/1000.,cos(FitUtils::th(nu, main)), 27., true)*1000.;
   double p_pr_z = Enuqe - pmu*cos(FitUtils::th(nu, main));
 
   TVector3 p_pr  = TVector3(-pmu_x, -pmu_y, p_pr_z);
   double thetapr = p_pr.Angle(second->fP.Vect())/TMath::Pi()*180.;
 
   return thetapr;
 }
 
 double SciBooNEUtils::CalcThetaPi(FitEvent *event, FitParticle *second){
 
   FitParticle *nu   = event->GetNeutrinoIn();
 
   if (!second || !nu) return -999;
 
   double thetapi = FitUtils::th(nu, second)/TMath::Pi()*180.;
   return thetapi;
 }
 
 /// Functions to deal with the SB mode stacks
 SciBooNEUtils::ModeStack::ModeStack(std::string name, std::string title, TH1* hist) {
   fName = name;
   fTitle = title;
 
   AddMode(0, "CCCOH",  "CCCOH", kGreen+2, 2, 3244);
   AddMode(1, "CCRES",  "CCRES", kRed,     2, 3304);
   AddMode(2, "CCQE",   "CCQE",  kGray+2,  2, 1001);
   AddMode(3, "2p2h",   "2p2h",  kMagenta, 2, 1001);
   AddMode(4, "Other",  "Other", kAzure+1, 2, 1001);
   
   StackBase::SetupStack(hist);
 };
 
 
 
 int SciBooNEUtils::ModeStack::ConvertModeToIndex(int mode){
   switch (abs(mode)){
   case 16: return 0; // CCCOH
   case 11:
   case 12:
   case 13: return 1; // CCRES
   case  1: return 2; // CCQE
   case  2: return 3; // 2p2h
   default: return 4; // Other
   }
 };
 
 
 void SciBooNEUtils::ModeStack::Fill(int mode, double x, double y, double z, double weight) {
   StackBase::FillStack(SciBooNEUtils::ModeStack::ConvertModeToIndex(mode), x, y, z, weight);
 };
 
 void SciBooNEUtils::ModeStack::Fill(FitEvent* evt, double x, double y, double z, double weight) {
   StackBase::FillStack(SciBooNEUtils::ModeStack::ConvertModeToIndex(evt->Mode), x, y, z, weight);
 };
 
 void SciBooNEUtils::ModeStack::Fill(BaseFitEvt* evt, double x, double y, double z, double weight) {
   StackBase::FillStack(SciBooNEUtils::ModeStack::ConvertModeToIndex(evt->Mode), x, y, z, weight);
 };
 
diff --git a/src/Splines/FitSpline.h b/src/Splines/FitSpline.h
index 0c8a975..8185ccd 100644
--- a/src/Splines/FitSpline.h
+++ b/src/Splines/FitSpline.h
@@ -1,99 +1,99 @@
 // Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret
 
 /*******************************************************************************
 *    This file is part of NUISANCE.
 *
 *    NUISANCE is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    NUISANCE is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with NUISANCE.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
 
 #ifndef FIT_SPLINE_H
 #define FIT_SPLINE_H
 
 #include "TObject.h"
-#include "FitParameters.h"
+
 
 #include "PlotUtils.h"
 #include "FitUtils.h"
 #include "stdint.h"
 #include "stdlib.h"
 #include <list>
 
 class FitSpline{
 
  public:
 
   // Constructors
   FitSpline();
   ~FitSpline(){};
   FitSpline(std::string ident, std::string dist,
 	    std::vector<int> list_enums, std::string points_def );
 
   void ReconfigureSpline(std::vector<int> dial_enums, std::vector<double> dial_values);
 
   double operator()(const Double_t* x, const Double_t* par) const;
   double DoEval(const double* par) const;
   double DoEval(const double* x, const double* par, const bool use_offset=true) const;
 
   void SetType(std::string type);
   void SetType(int t, int p, int d, bool f=true);
   void SetOffset(int i){ offset = i; };
 
   inline std::string GetIdent(){return id;};
   inline std::string GetDist(){return form;};
   inline std::string GetPoints(){return points;};
   inline std::vector<int> GetEnums(){return var_enums;};
   
   std::vector<double> GetSplineCoeff(double* weights);
 
   // Public Access Spline Variables
   std::vector<int> var_enums;
   std::vector<double> x;
 
   mutable  std::vector< std::vector<double> > x_vals;
   std::vector<double> x_low;
   std::vector<double> x_high;
 
   bool needs_fit;
 
   UInt_t offset;
   UInt_t npar;
   UInt_t ndim;
   UInt_t spline;
 
   std::string id;
   std::string form;
   std::string points;
 
   enum spline_types {
     k1DPol1 = 1,
     k1DPol2,
     k1DPol3,
     k1DPol4,
     k1DPol5,
     k1DPol6,
     k1DPol1C,
     k1DPol2C,
     k1DPol3C,
     k1DPol4C,
     k1DPol5C,
     k1DPol5C_LX,
     k1DPol10,
     k1DTSpline3,
     k1DPol25,
     k2DPol6
   };
 
 };
 
 #endif
diff --git a/src/Splines/FitSplineHead.h b/src/Splines/FitSplineHead.h
index 64b039d..ca43c8c 100644
--- a/src/Splines/FitSplineHead.h
+++ b/src/Splines/FitSplineHead.h
@@ -1,54 +1,54 @@
 // Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret
 
 /*******************************************************************************
 *    This file is part of NUISANCE.
 *
 *    NUISANCE is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    NUISANCE is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with NUISANCE.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
 
 #ifndef SPLINES_HEAD_H
 #define SPLINES_HEAD_H
 
 #include "TObject.h"
-#include "FitParameters.h"
+
 #include "PlotUtils.h"
 #include "FitUtils.h"
 #include "stdint.h"
 #include "stdlib.h"
 #include "FitSpline.h"
 #include <list>
 
 class FitSplineHead {
  public:
 
   FitSplineHead(){current_offset = 1;};
   ~FitSplineHead(){};
 
   // Function Reconf (Given current dial values and names set the values for each function)
   double CalcWeight(const Double_t* incoeff);
   void Reconfigure(std::vector<int> dial_enums, std::vector<double> dial_values);
   void SetupEventWeights(BaseFitEvt* event);
   void AddSpline(FitSpline* spl);
 
   void Write(std::string name="FitSplineHead");
   FitSplineHead(TFile* infile, std::string name);
   void Read(TTree* tn);
   
   int GetCurrentOffset();
 
   int ngen_events; // Number of events in the tree these were generated with (needed for scaling)
   int current_offset;
   std::list<FitSpline*> SplineObjects;
 };
 #endif
diff --git a/src/Splines/Spline.h b/src/Splines/Spline.h
index 269ba3a..9966f6f 100644
--- a/src/Splines/Spline.h
+++ b/src/Splines/Spline.h
@@ -1,168 +1,168 @@
 #ifndef SPLINE_H
 #define SPLINE_H
 #include <vector>
 #include "TObject.h"
-#include "FitParameters.h"
+
 #include "stdint.h"
 #include "stdlib.h"
 #include "TCanvas.h"
 #include <list>
 #include "TF1.h"
 #include "TSpline.h"
 #include "SplineUtils.h"
 #include "TGraph2D.h"
 #include "TF2.h"
 
 #include "Math/Minimizer.h"
 #include "Math/Factory.h"
 #include "Math/Functor.h"
 #include "TH1D.h"
 #include "Math/IFunction.h"
 #include "Math/IParamFunction.h"
 #include "FitLogger.h"
 
 // Spline Class
 class Spline : public  ROOT::Math::ParamFunctor { 
 private:
 
    const double* pars;
  
 public:
    double DoEvalPar(const double* x, const double* p) const ;
  
    unsigned int NDim() const{
       return fNDim;
    }
    // ROOT::Math::IParametricFunctionMultiDim* Clone() const{
    //    return new Spline(this->fName, this->fForm, this->fPoints);
    // }
  
    const double* Parameters() const{
       return pars;
    }
  
    void SetParameters(const double* p){
       pars = p;
    }
  
    unsigned int NPar() const{
       return fNPar;
    }
  
   Spline(std::string splname, std::string form, std::string points);
   ~Spline() {};
 
   void Setup(int type, int ndim, int npar);
 
   double operator()(const Double_t* x, const Double_t* par);
   float operator()(const Float_t* x, const Float_t* par) const;
 
   float DoEval(const Float_t* x, const Float_t* par) const;
   float DoEval(const Float_t* par, bool checkresponse = true) const;
 
   //  void FitCoeff(int n, double* x, double* y, double* par, bool draw);
   void FitCoeff(std::vector< std::vector<double> > v, std::vector<double> w, float* coeff, bool draw);
 
   inline std::string GetName(void) { return fName; };
   inline int GetNDim(void) { return fNDim; };
   inline int GetType(void) { return fType; };
   inline int GetNPar(void) { return fNPar;  };
   inline std::string GetForm() {return fForm;};
 
   //void Reconfigure(double x);
   void Reconfigure(float x, int index = 0);
   void Reconfigure(std::string name, float x);
 
    // Available Spline Functions
   float Spline1DPol1(const Float_t* par) const;
   float Spline1DPol2(const Float_t* par) const;
   float Spline1DPol3(const Float_t* par) const;
   float Spline1DPol4(const Float_t* par) const;
   float Spline1DPol5(const Float_t* par) const;
   float Spline1DPol6(const Float_t* par) const;
   float Spline2DPol(const Float_t* par, int n) const;
   float Spline2DGaus(const Float_t* par) const;
 
   float Spline1DTSpline3(const Float_t* par) const;
   float Spline2DTSpline3(const Float_t* par) const;
 
 
   std::string fName;
   int fType;
   int fNDim;
   int fNPar;
   std::string fForm;
   std::string fPoints;
   bool fOutsideLimits;
 
   std::vector<std::string> fSplitNames;
   std::vector<std::string> fSplitPoints;
 
   mutable std::vector<float> fVal;
   mutable std::vector<float> fValMin;
   mutable std::vector<float> fValMax;
 
   mutable std::vector< std::vector<float> > fSplitScan;
 
   mutable std::vector<float> fXScan;
   mutable float fX;
   mutable float fXMin;
   mutable float fXMax;
 
   mutable std::vector<float> fYScan;
   mutable float fY;
   mutable float fYMin;
   mutable float fYMax;
 
   int  fSplineOffset;
 
   // TSpline3 Objects.
   mutable std::vector<float>::iterator iter_low;
   mutable std::vector<float>::iterator iter_high;
   mutable int off;
 
   // Create a new function for fitting.
   ROOT::Math::Minimizer* minimizer;
 
   TF1* fROOTFunction;
   TF1* GetFunction();
 
 };
 
 
 namespace SplineUtils {
 
   double Func2DWrapper(double* x, double* p);
   extern Spline* gSpline;
 
 }
 
 
 
 namespace SplineUtils {
 
 // Spline List
 enum spline_types {
   k1DPol1 = 1,
   k1DPol2,
   k1DPol3,
   k1DPol4,
   k1DPol5,
   k1DPol6,
   k1DPol1C,
   k1DPol2C,
   k1DPol3C,
   k1DPol4C,
   k1DPol5C,
   k1DPol5C_LX,
   k1DPol10,
   k1DTSpline3,
   k1DPol25,
   k2DPol6,
   k2DGaus,
   k2DTSpline3
 };
 
 }
 
 #endif
diff --git a/src/Splines/SplineMerger.h b/src/Splines/SplineMerger.h
index 34dff97..0fee6b8 100644
--- a/src/Splines/SplineMerger.h
+++ b/src/Splines/SplineMerger.h
@@ -1,38 +1,38 @@
 #ifndef SPLINEMerger_H
 #define SPLINEMerger_H
 
 #include "FitWeight.h"
 #include "Spline.h"
-#include "FitParameters.h"
+
 #include "SplineReader.h"
 
 class SplineMerger : public SplineReader {
  public:
   SplineMerger(){};
   ~SplineMerger(){};
 
   void AddSplineSetFromFile(TFile* file); 
   void SetupSplineSet();
 
   void Write(std::string name);
   void AddCoefficientsToTree(TTree* tree);
   void GetEntry(int entry);
 
   void FillMergedSplines(int entry);
 
   float* fCoEffStorer;
   int fNCoEff;
 
   std::vector< float[1000] > fSplineAddressList;
   std::vector< int > fSplineSizeList;
   std::vector< TTree* > fSplineTreeList;
 
   std::vector< std::vector<double> > fParVect;
   std::vector< int > fSetIndex;
   std::vector< double > fWeightList;
   std::vector< double > fValList;
 
   
 };
 
 #endif
diff --git a/src/Splines/SplineReader.h b/src/Splines/SplineReader.h
index cc8ae28..bb7d685 100644
--- a/src/Splines/SplineReader.h
+++ b/src/Splines/SplineReader.h
@@ -1,39 +1,42 @@
 #ifndef SPLINEREADER_H
 #define SPLINEREADER_H
 // #include "FitWeight.h"
 #include "Spline.h"
 #include "TTree.h"
 #include "FitLogger.h"
+#include "NuisConfig.h"
+#include "NuisKey.h"
+
 // #include "GeneralUtils.h"
 
 class SplineReader {
 public:
   SplineReader() {};
   ~SplineReader() {};
 
   void AddSpline(nuiskey splkey);
   void Read(TTree* tr);
 
   void Reconfigure(std::map< std::string, double >& vals);
   bool NeedsReconfigure();
   void SetNeedsReconfigure(bool val = true);
 
   int GetNPar();
   double CalcWeight(float* coeffs);
 
   std::vector<Spline> fAllSplines;
   std::vector<std::string> fSpline;
   std::vector<std::string> fType;
   std::vector<std::string> fForm;
   std::vector<std::string> fPoints;
 
   std::vector<double> fDialValues;
   std::vector<double> fParValues;
 
   bool fNeedsReconfigure;
 
 
 
 };
 
 #endif
diff --git a/src/Splines/SplineWriter.h b/src/Splines/SplineWriter.h
index b761f1d..ffc0655 100644
--- a/src/Splines/SplineWriter.h
+++ b/src/Splines/SplineWriter.h
@@ -1,92 +1,92 @@
 #ifndef SPLINEWRITER_H
 #define SPLINEWRITER_H
 #include "FitWeight.h"
 #include "Spline.h"
-#include "FitParameters.h"
+
 #include "SplineUtils.h"
 #ifdef __MINUIT2_ENABLED__
 #include "TFitterMinuit.h"
 #endif
 
 class SplineFCN {
 public:
 
   SplineFCN(Spline* spl, std::vector<std::vector<double> > v, std::vector<double> w) { fSpl = spl; fVal = v; fWeight = w; };
   ~SplineFCN() {};
 
   double operator()(const double* x) const;
   double DoEval(const double *x) const;
   void SaveAs(std::string name, const float* fx);
   void UpdateWeights(std::vector<double>& w);
   void SetCorrelated(bool state = true);
 
   bool uncorrelated;
   std::vector< std::vector<double> > fVal;
   std::vector< double > fWeight;
   Spline* fSpl;
 
 };
 
 
 class SplineWriter : public SplineReader {
 public:
   SplineWriter(FitWeight* fw) {
     fRW = fw;
     fDrawSplines = FitPar::Config().GetParB("drawsplines");
   };
   ~SplineWriter() {};
 
   void SetupSplineSet();
   void Write(std::string name);
   void AddCoefficientsToTree(TTree* tree);
   void FitSplinesForEvent(TCanvas* fitcanvas = NULL, bool saveplot = false);
   void AddWeightsToTree(TTree* tr);
   void ReadWeightsFromTree(TTree* tr);
   void FitSplinesForEvent(double* weightvals, float* coeff);
 
   void GetWeightsForEvent(FitEvent* event, double* weights);
   void GetWeightsForEvent(FitEvent* event);
   void ReconfigureSet(int iset);
   double GetWeightForThisSet(FitEvent* event, int iset=-1);
   void SetWeights(double* weights);
 
   inline int GetNWeights(){return fParVect.size();};
   inline int GetNPars(){ return fNCoEff;};
 
   int fNCoEff;
   //  double* fCoEffStorer;
   float* fCoEffStorer;
 
   std::vector< std::vector<double> > fParVect;
   std::vector< int > fSetIndex;
   double* fWeightList;
   std::vector< std::vector<double> > fValList;
   int fCurrentSet;
   FitWeight* fRW;
   bool fDrawSplines;
 
   std::vector<TH1D*> fAllDrawnHists;
   std::vector<TGraph*> fAllDrawnGraphs;
 
 #ifdef __MINUIT2_ENABLED__
   std::map<Spline*, SplineFCN*> fSplineFCNs;
   std::map<Spline*, ROOT::Math::Functor*> fSplineFunctors;
   std::map<Spline*, ROOT::Math::Minimizer*> fSplineMinimizers;
 #endif
 
   //  Spline* gSpline;
 
   // Available Fitting Functions
   void FitCoeff(Spline* spl, std::vector< std::vector<double> >& v, std::vector<double>& w, float* coeff, bool draw);
   void FitCoeff1DGraph(Spline* spl, int n, double* x, double* y, float* coeff, bool draw);
   void GetCoeff1DTSpline3(Spline* spl, int n, double* x, double* y, float* coeff, bool draw);
   // void FitCoeff2DGraph(Spline* spl, std::vector< std::vector<double> >& v, std::vector<double>& w, float* coeff, bool draw);
   void FitCoeffNDGraph(Spline* spl, std::vector< std::vector<double> >& v, std::vector<double>& w, float* coeff, bool draw);
   void FitCoeff2DGraph(Spline* spl,  int n,  double* x,  double* y,  double* w, float* coeff, bool draw);
   //double Func2DWrapper(double* x, double* p);
 
 };
 
 
 
 #endif
diff --git a/src/Routines/CMakeLists.txt b/src/Statistical/CMakeLists.txt
similarity index 79%
copy from src/Routines/CMakeLists.txt
copy to src/Statistical/CMakeLists.txt
index 2c5cf1c..7512473 100644
--- a/src/Routines/CMakeLists.txt
+++ b/src/Statistical/CMakeLists.txt
@@ -1,66 +1,50 @@
 # Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret
 
 ################################################################################
 #    This file is part of NUISANCE.
 #
 #    NUISANCE is free software: you can redistribute it and/or modify
 #    it under the terms of the GNU General Public License as published by
 #    the Free Software Foundation, either version 3 of the License, or
 #    (at your option) any later version.
 #
 #    NUISANCE is distributed in the hope that it will be useful,
 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 #    GNU General Public License for more details.
 #
 #    You should have received a copy of the GNU General Public License
 #    along with NUISANCE.  If not, see <http://www.gnu.org/licenses/>.
 ################################################################################
-set(IMPLFILES
-ComparisonRoutines.cxx
-SystematicRoutines.cxx
-SplineRoutines.cxx
-)
-
-if(USE_MINIMIZER)
-  set(IMPLFILES ${IMPLFILES};MinimizerRoutines.cxx)
-endif()
-
 set(HEADERFILES
-ComparisonRoutines.h
-SystematicRoutines.h
-SplineRoutines.h
+StatUtils.h
 )
 
-if(USE_MINIMIZER)
-  set(HEADERFILES ${HEADERFILES};MinimizerRoutines.h)
-endif()
+set(IMPLFILES
+StatUtils.cxx
+)
 
-set(LIBNAME Routines)
+set(LIBNAME Statistical)
 
 if(CMAKE_BUILD_TYPE MATCHES DEBUG)
   add_library(${LIBNAME} STATIC ${IMPLFILES})
 else(CMAKE_BUILD_TYPE MATCHES RELEASE)
   add_library(${LIBNAME} SHARED ${IMPLFILES})
 endif()
 
-include_directories(${EXP_INCLUDE_DIRECTORIES})
-
 include_directories(${MINIMUM_INCLUDE_DIRECTORIES})
 
-include_directories(${CMAKE_SOURCE_DIR}/src/FCN)
-include_directories(${CMAKE_SOURCE_DIR}/src/MCStudies)
-
 set_target_properties(${LIBNAME} PROPERTIES VERSION
   "${NUISANCE_VERSION_MAJOR}.${NUISANCE_VERSION_MINOR}.${NUISANCE_VERSION_REVISION}")
+
 #set_target_properties(${LIBNAME} PROPERTIES LINK_FLAGS ${ROOT_LD_FLAGS})
 
 if(DEFINED PROJECTWIDE_EXTRA_DEPENDENCIES)
   add_dependencies(${LIBNAME} ${PROJECTWIDE_EXTRA_DEPENDENCIES})
 endif()
 
 install(TARGETS ${LIBNAME} DESTINATION lib)
 #Can uncomment this to install the headers... but is it really neccessary?
 #install(FILES ${HEADERFILES} DESTINATION include)
 
 set(MODULETargets ${MODULETargets} ${LIBNAME} PARENT_SCOPE)
diff --git a/src/Utils/StatUtils.cxx b/src/Statistical/StatUtils.cxx
similarity index 99%
rename from src/Utils/StatUtils.cxx
rename to src/Statistical/StatUtils.cxx
index 24a458a..2648470 100644
--- a/src/Utils/StatUtils.cxx
+++ b/src/Statistical/StatUtils.cxx
@@ -1,1300 +1,1303 @@
 // Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret
 
 /*******************************************************************************
 *    This file is part of NUISANCE.
 *
 *    NUISANCE is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    NUISANCE is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with NUISANCE.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
 
 #include "TH1D.h"
 #include "StatUtils.h"
+#include "NuisConfig.h"
+#include "GeneralUtils.h"
 
 //*******************************************************************
 Double_t StatUtils::GetChi2FromDiag(TH1D* data, TH1D* mc, TH1I* mask) {
 //*******************************************************************
 
   Double_t Chi2 = 0.0;
   TH1D* calc_data = (TH1D*)data->Clone();
   TH1D* calc_mc   = (TH1D*)mc->Clone();
 
   // Add MC Error to data if required
   if (FitPar::Config().GetParB("statutils.addmcerror")) {
     for (int i = 0; i < calc_data->GetNbinsX(); i++) {
 
       double dterr = calc_data->GetBinError(i + 1);
       double mcerr = calc_mc->GetBinError(i + 1);
 
       if (dterr > 0.0) {
         calc_data->SetBinError(i + 1, sqrt(dterr * dterr + mcerr * mcerr));
       }
     }
   }
 
   // Apply masking if required
   if (mask) {
     calc_data = ApplyHistogramMasking(data, mask);
     calc_mc   = ApplyHistogramMasking(mc, mask);
   }
 
   // Iterate over bins in X
   for (int i = 0; i < calc_data->GetNbinsX(); i++) {
 
     // Ignore bins with zero data or zero bin error
     if (calc_data->GetBinError(i + 1) <= 0.0 ||
         calc_data->GetBinContent(i + 1) == 0.0) continue;
 
     // Take mc data difference
     double diff = calc_data->GetBinContent(i + 1) - calc_mc->GetBinContent(i + 1);
     double err = calc_data->GetBinError(i + 1);
     Chi2 += (diff * diff) / (err * err);
 
   }
 
   // cleanup
   delete calc_data;
   delete calc_mc;
 
   return Chi2;
 };
 
 //*******************************************************************
 Double_t StatUtils::GetChi2FromDiag(TH2D* data, TH2D* mc,
                                     TH2I* map, TH2I* mask) {
 //*******************************************************************
 
   // Generate a simple map
   if (!map)  map = GenerateMap(data);
 
   // Convert to 1D Histograms
   TH1D* data_1D = MapToTH1D(data, map);
   TH1D* mc_1D   = MapToTH1D(mc,   map);
   TH1I* mask_1D = MapToMask(mask, map);
 
   // Calculate 1D chi2 from 1D Plots
   Double_t Chi2 = StatUtils:: GetChi2FromDiag(data_1D, mc_1D,  mask_1D);
 
   // CleanUp
   delete data_1D;
   delete mc_1D;
   delete mask_1D;
 
   return Chi2;
 };
 
 //*******************************************************************
 Double_t StatUtils::GetChi2FromCov(TH1D* data, TH1D* mc,
                                    TMatrixDSym* invcov, TH1I* mask,
 				   double data_scale, double covar_scale) {
 //*******************************************************************
 
   Double_t Chi2 = 0.0;
   TMatrixDSym* calc_cov = (TMatrixDSym*) invcov->Clone();
   TH1D* calc_data = (TH1D*) data->Clone();
   TH1D* calc_mc   = (TH1D*) mc->Clone();
 
-  calc_data->Scale(data_scale);
-  calc_mc  ->Scale(data_scale);
-  (*calc_cov) *= covar_scale;
-
   // If a mask if applied we need to apply it before the matrix is inverted
   if (mask) {
     calc_cov  = ApplyInvertedMatrixMasking(invcov, mask);
     calc_data = ApplyHistogramMasking(data, mask);
     calc_mc   = ApplyHistogramMasking(mc, mask);
   }
 
   // Add MC Error to data if required
   if (FitPar::Config().GetParB("statutils.addmcerror")) {
 
     // Make temp cov
     TMatrixDSym* newcov = StatUtils::GetInvert(calc_cov);
 
     // Add MC err to diag
     for (int i = 0; i < calc_data->GetNbinsX(); i++) {
 
       double mcerr = calc_mc->GetBinError(i + 1) * sqrt(covar_scale);
       double oldval = (*newcov)(i, i);
 
+      std::cout << "Adding cov stat " << mcerr*mcerr << " to " << (*newcov)(i,i) << std::endl;
       (*newcov)(i, i) = oldval + mcerr * mcerr;
     }
 
     // Reset the calc_cov to new invert
     delete calc_cov;
     calc_cov = GetInvert(newcov);
 
     // Delete the tempcov
     delete newcov;
   }
 
+  calc_data->Scale(data_scale);
+  calc_mc  ->Scale(data_scale);
+  (*calc_cov) *= covar_scale;
+
   // iterate over bins in X (i,j)
   for (int i = 0; i < calc_data->GetNbinsX(); i++) {
 
     for (int j = 0; j < calc_data->GetNbinsX(); j++) {
 
       if (calc_data->GetBinContent(i + 1) != 0 || calc_mc->GetBinContent(i + 1) != 0) {
 
         LOG(DEB) << "i j = " << i << " " << j << std::endl;
         LOG(DEB) << "Calc_data mc i = " << calc_data->GetBinContent(i + 1)
                  << " " << calc_mc->GetBinContent(i + 1)
                  << "  Dif = "
                  << ( calc_data->GetBinContent(i + 1) - calc_mc->GetBinContent(i + 1) )
                  << std::endl;
 
         LOG(DEB) << "Calc_data mc i = " << calc_data->GetBinContent(j + 1)
                  << " " << calc_mc->GetBinContent(j + 1)
                  << "  Dif = "
                  << ( calc_data->GetBinContent(j + 1) - calc_mc->GetBinContent(j + 1) )
                  << std::endl;
 
         LOG(DEB) << "Covar = " <<    (*calc_cov)(i, j) << std::endl;
 
         LOG(DEB) << "Cont chi2 = " \
                  << ( ( calc_data->GetBinContent(i + 1) - calc_mc->GetBinContent(i + 1) ) \
                       * (*calc_cov)(i, j) \
                       *   ( calc_data->GetBinContent(j + 1) - calc_mc->GetBinContent(j + 1)))
                  << " " << Chi2 << std::endl;
 
         Chi2 += ( ( calc_data->GetBinContent(i + 1) - calc_mc->GetBinContent(i + 1) ) \
 		  * (*calc_cov)(i, j)					\
 		  * ( calc_data->GetBinContent(j + 1) - calc_mc->GetBinContent(j + 1) ) );
 
       } else {
 
         LOG(DEB) << "Error on bin (i,j) = (" << i << "," << j << ")" << std::endl;
         LOG(DEB) << "data->GetBinContent(i+1) = " << calc_data->GetBinContent(i + 1) << std::endl;
         LOG(DEB) << "mc->GetBinContent(i+1) = " << calc_mc->GetBinContent(i + 1) << std::endl;
         LOG(DEB) << "Adding zero to chi2 instead of dying horrifically " << std::endl;
 
         Chi2 += 0.;
       }
     }
   }
 
   // Cleanup
   delete calc_cov;
   delete calc_data;
   delete calc_mc;
 
   return Chi2;
 }
 
 
 //*******************************************************************
 Double_t StatUtils::GetChi2FromCov( TH2D* data, TH2D* mc,
                                     TMatrixDSym* invcov, TH2I* map, TH2I* mask) {
 //*******************************************************************
 
   // Generate a simple map
   if (!map) {
     map = StatUtils::GenerateMap(data);
   }
 
   // Convert to 1D Histograms
   TH1D* data_1D = MapToTH1D(data, map);
   TH1D* mc_1D   = MapToTH1D(mc,   map);
   TH1I* mask_1D = MapToMask(mask, map);
 
   // Calculate 1D chi2 from 1D Plots
   Double_t Chi2 = StatUtils::GetChi2FromCov(data_1D, mc_1D,  invcov, mask_1D);
 
   // CleanUp
   delete data_1D;
   delete mc_1D;
   delete mask_1D;
 
   return Chi2;
 }
 
 //*******************************************************************
 Double_t StatUtils::GetChi2FromSVD( TH1D* data, TH1D* mc,
                                     TMatrixDSym* cov,  TH1I* mask) {
 //*******************************************************************
 
   Double_t Chi2 = 0.0;
   TMatrixDSym* calc_cov = (TMatrixDSym*) cov->Clone();
   TH1D* calc_data = (TH1D*) data->Clone();
   TH1D* calc_mc   = (TH1D*) mc->Clone();
 
   // If a mask if applied we need to apply it before the matrix is inverted
   if (mask) {
     calc_cov  = StatUtils::ApplyMatrixMasking(cov, mask);
     calc_data = StatUtils::ApplyHistogramMasking(data, mask);
     calc_mc   = StatUtils::ApplyHistogramMasking(mc, mask);
   }
 
   // Decompose matrix
   TDecompSVD LU = TDecompSVD((*calc_cov));
   LU.Decompose();
   TMatrixDSym* cov_U = new TMatrixDSym(calc_data->GetNbinsX(), LU .GetU().GetMatrixArray(), "");
   TVectorD*    cov_S = new TVectorD( LU.GetSig() );
 
   // Apply basis rotation before adding up chi2
   Double_t rotated_difference = 0.0;
 
   for (int i = 0; i < calc_data->GetNbinsX(); i++) {
     rotated_difference = 0.0;
 
     // Rotate basis of Data - MC
     for (int j = 0; j < calc_data->GetNbinsY(); j++)
       rotated_difference += ( calc_data->GetBinContent(j + 1) - calc_mc  ->GetBinContent(j + 1) ) * (*cov_U)(j, i) ;
 
     // Divide by rotated error cov_S
     Chi2 += rotated_difference * rotated_difference * 1E76 / (*cov_S)(i);
 
   }
 
   // Cleanup
   delete calc_cov;
   delete calc_data;
   delete calc_mc;
   delete cov_U;
   delete cov_S;
 
   return Chi2;
 }
 
 
 //*******************************************************************
 Double_t StatUtils::GetChi2FromSVD( TH2D* data, TH2D* mc,
                                     TMatrixDSym* cov,    TH2I* map, TH2I* mask) {
 //*******************************************************************
 
   // Generate a simple map
   if (!map)
     map = StatUtils::GenerateMap(data);
 
   // Convert to 1D Histograms
   TH1D* data_1D = MapToTH1D(data, map);
   TH1D* mc_1D   = MapToTH1D(mc,   map);
   TH1I* mask_1D = MapToMask(mask, map);
 
   // Calculate from 1D
   Double_t Chi2 = StatUtils::GetChi2FromSVD(data_1D, mc_1D, cov, mask_1D);
 
   // CleanUp
   delete data_1D;
   delete mc_1D;
   delete mask_1D;
 
   return Chi2;
 }
 
 //*******************************************************************
 double StatUtils::GetChi2FromEventRate(TH1D* data, TH1D* mc, TH1I* mask) {
 //*******************************************************************
 
   // If just an event rate, for chi2 just use Poission Likelihood to calculate the chi2 component
   double chi2 = 0.0;
   TH1D* calc_data = (TH1D*)data->Clone();
   TH1D* calc_mc   = (TH1D*)mc->Clone();
 
   // Apply masking if required
   if (mask) {
     calc_data = ApplyHistogramMasking(data, mask);
     calc_mc   = ApplyHistogramMasking(mc, mask);
   }
 
   // Iterate over bins in X
   for (int i = 0; i < calc_data->GetNbinsX(); i++) {
 
     double dt = calc_data->GetBinContent(i + 1);
     double mc = calc_mc->GetBinContent(i + 1);
 
     if (mc <= 0) continue;
 
     if (dt <= 0) {
       // Only add difference
       chi2 += 2 * (mc - dt);
     } else {
       // Do the chi2 for Poisson distributions
       chi2 +=  2 * (mc - dt + (dt * log(dt / mc)));
     }
 
     /*
         LOG(REC)<<"Evt Chi2 cont = "<<i<<" "
           <<mc<<" "<<dt<<" "
           <<2 * (mc - dt + (dt+0.) * log((dt+0.) / (mc+0.)))
           <<" "<<Chi2<<std::endl;
     */
   }
 
   // cleanup
   delete calc_data;
   delete calc_mc;
 
   return chi2;
 }
 
 //*******************************************************************
 Double_t StatUtils::GetChi2FromEventRate(TH2D* data, TH2D* mc, TH2I* map, TH2I* mask) {
 //*******************************************************************
 
   // Generate a simple map
   if (!map)
     map = StatUtils::GenerateMap(data);
 
   // Convert to 1D Histograms
   TH1D* data_1D = MapToTH1D(data, map);
   TH1D* mc_1D   = MapToTH1D(mc,   map);
   TH1I* mask_1D = MapToMask(mask, map);
 
   // Calculate from 1D
   Double_t Chi2 = StatUtils::GetChi2FromEventRate(data_1D, mc_1D, mask_1D);
 
   // CleanUp
   delete data_1D;
   delete mc_1D;
   delete mask_1D;
 
   return Chi2;
 }
 
 
 
 
 //*******************************************************************
 Double_t StatUtils::GetLikelihoodFromDiag(TH1D* data, TH1D* mc, TH1I* mask) {
 //*******************************************************************
   // Currently just a placeholder!
   (void) data;
   (void) mc;
   (void) mask;
   return 0.0;
 };
 
 //*******************************************************************
 Double_t StatUtils::GetLikelihoodFromDiag(TH2D* data, TH2D* mc, TH2I* map, TH2I* mask) {
 //*******************************************************************
 
   // Generate a simple map
   if (!map)
     map = StatUtils::GenerateMap(data);
 
   // Convert to 1D Histograms
   TH1D* data_1D = MapToTH1D(data, map);
   TH1D* mc_1D   = MapToTH1D(mc,   map);
   TH1I* mask_1D = MapToMask(mask, map);
 
   // Calculate from 1D
   Double_t MLE = StatUtils::GetLikelihoodFromDiag(data_1D, mc_1D, mask_1D);
 
   // CleanUp
   delete data_1D;
   delete mc_1D;
   delete mask_1D;
 
   return MLE;
 };
 
 
 //*******************************************************************
 Double_t StatUtils::GetLikelihoodFromCov( TH1D* data, TH1D* mc, TMatrixDSym* invcov, TH1I* mask) {
 //*******************************************************************
   // Currently just a placeholder !
   (void) data;
   (void) mc;
   (void) invcov;
   (void) mask;
 
   return 0.0;
 };
 
 //*******************************************************************
 Double_t StatUtils::GetLikelihoodFromCov( TH2D* data, TH2D* mc, TMatrixDSym* invcov, TH2I* map, TH2I* mask) {
 //*******************************************************************
 
   // Generate a simple map
   if (!map)
     map = StatUtils::GenerateMap(data);
 
   // Convert to 1D Histograms
   TH1D* data_1D = MapToTH1D(data, map);
   TH1D* mc_1D   = MapToTH1D(mc,   map);
   TH1I* mask_1D = MapToMask(mask, map);
 
   // Calculate from 1D
   Double_t MLE = StatUtils::GetLikelihoodFromCov(data_1D, mc_1D, invcov, mask_1D);
 
   // CleanUp
   delete data_1D;
   delete mc_1D;
   delete mask_1D;
 
   return MLE;
 };
 
 //*******************************************************************
 Double_t StatUtils::GetLikelihoodFromSVD( TH1D* data, TH1D* mc, TMatrixDSym* cov,    TH1I* mask) {
 //*******************************************************************
   // Currently just a placeholder!
   (void) data;
   (void) mc;
   (void) cov;
   (void) mask;
 
   return 0.0;
 };
 
 //*******************************************************************
 Double_t StatUtils::GetLikelihoodFromSVD( TH2D* data, TH2D* mc, TMatrixDSym* cov,    TH2I* map, TH2I* mask) {
 //*******************************************************************
 
   // Generate a simple map
   if (!map)
     map = StatUtils::GenerateMap(data);
 
   // Convert to 1D Histograms
   TH1D* data_1D = MapToTH1D(data, map);
   TH1D* mc_1D   = MapToTH1D(mc,   map);
   TH1I* mask_1D = MapToMask(mask, map);
 
   // Calculate from 1D
   Double_t MLE = StatUtils::GetLikelihoodFromSVD(data_1D, mc_1D, cov, mask_1D);
 
   // CleanUp
   delete data_1D;
   delete mc_1D;
   delete mask_1D;
 
   return MLE;
 };
 
 //*******************************************************************
 Double_t StatUtils::GetLikelihoodFromEventRate(TH1D* data, TH1D* mc, TH1I* mask) {
 //*******************************************************************
   // Currently just a placeholder!
   (void) data;
   (void) mc;
   (void) mask;
 
   return 0.0;
 };
 
 
 //*******************************************************************
 Double_t StatUtils::GetLikelihoodFromEventRate(TH2D* data, TH2D* mc, TH2I* map, TH2I* mask) {
 //*******************************************************************
 
   // Generate a simple map
   if (!map)
     map = StatUtils::GenerateMap(data);
 
   // Convert to 1D Histograms
   TH1D* data_1D = MapToTH1D(data, map);
   TH1D* mc_1D   = MapToTH1D(mc,   map);
   TH1I* mask_1D = MapToMask(mask, map);
 
   // Calculate from 1D
   Double_t MLE = StatUtils::GetChi2FromEventRate(data_1D, mc_1D, mask_1D);
 
   // CleanUp
   delete data_1D;
   delete mc_1D;
   delete mask_1D;
 
   return MLE;
 };
 
 
 
 //*******************************************************************
 Int_t StatUtils::GetNDOF(TH1D* hist, TH1I* mask) {
 //*******************************************************************
 
   TH1D* calc_hist = (TH1D*)hist->Clone();
 
   // If a mask is provided we need to apply it before getting NDOF
   if (mask) {
     calc_hist = StatUtils::ApplyHistogramMasking(hist, mask);
   }
 
   // NDOF is defined as total number of bins with non-zero errors
   Int_t NDOF = 0;
   for (int i = 0; i < calc_hist->GetNbinsX(); i++) {
     if (calc_hist->GetBinError(i + 1) > 0.0) NDOF++;
   }
 
   delete calc_hist;
 
   return NDOF;
 };
 
 
 //*******************************************************************
 Int_t StatUtils::GetNDOF(TH2D* hist, TH2I* map, TH2I* mask) {
 //*******************************************************************
 
   Int_t NDOF = 0;
   if (!map) map = StatUtils::GenerateMap(hist);
 
   for (int i = 0; i < hist->GetNbinsX(); i++) {
     for (int j = 0; j < hist->GetNbinsY(); j++) {
 
       if (mask->GetBinContent(i + 1, j + 1)) continue;
       if (map->GetBinContent(i + 1, j + 1) <= 0) continue;
 
       NDOF++;
 
     }
   }
 
   return NDOF;
 };
 
 
 
 //*******************************************************************
 TH1D* StatUtils::ThrowHistogram(TH1D* hist, TMatrixDSym* cov, bool throwdiag, TH1I* mask) {
 //*******************************************************************
 
   TH1D* calc_hist = (TH1D*) hist->Clone( (std::string(hist->GetName()) + "_THROW" ).c_str() );
   TMatrixDSym* calc_cov = (TMatrixDSym*) cov->Clone();
   Double_t correl_val = 0.0;
 
   // If a mask if applied we need to apply it before the matrix is decomposed
   if (mask) {
     calc_cov  = ApplyMatrixMasking(cov, mask);
     calc_hist = ApplyHistogramMasking(calc_hist, mask);
   }
 
   // If a covariance is provided we need a preset random vector and a decomp
   std::vector<Double_t> rand_val;
   TMatrixDSym* decomp_cov;
 
   if (cov) {
     for (int i = 0; i < hist->GetNbinsX(); i++) {
       rand_val.push_back(gRandom->Gaus(0.0, 1.0));
     }
 
     // Decomp the matrix
     decomp_cov = StatUtils::GetDecomp(calc_cov);
   }
 
   // iterate over bins
   for (int i = 0; i < hist->GetNbinsX(); i++) {
 
     // By Default the errors on the histogram are thrown uncorrelated to the other errors
     //    if (throwdiag) {
     //      calc_hist->SetBinContent(i + 1, (calc_hist->GetBinContent(i + 1) + \
     //				       gRandom->Gaus(0.0, 1.0) * calc_hist->GetBinError(i + 1)) );
     //    }
 
     // If a covariance is provided that is also thrown
     if (cov) {
       correl_val = 0.0;
 
       for (int j = 0; j < hist->GetNbinsX(); j++) {
         correl_val += rand_val[j] * (*decomp_cov)(j, i) ;
       }
       calc_hist->SetBinContent(i + 1, (calc_hist->GetBinContent(i + 1) + correl_val * 1E-38));
     }
   }
 
   delete calc_cov;
   delete decomp_cov;
 
   // return this new thrown data
   return calc_hist;
 };
 
 //*******************************************************************
 TH2D* StatUtils::ThrowHistogram(TH2D* hist, TMatrixDSym* cov, TH2I* map, bool throwdiag, TH2I* mask) {
 //*******************************************************************
 
   // PLACEHOLDER!!!!!!!!!
   // Currently no support for throwing 2D Histograms from a covariance
   (void) hist;
   (void) cov;
   (void) map;
   (void) throwdiag;
   (void) mask;
 
   // /todo
   // Sort maps if required
   // Throw the covariance for a 1D plot
   // Unmap back to 2D Histogram
 
   return hist;
 }
 
 
 
 
 
 
 //*******************************************************************
 TH1D* StatUtils::ApplyHistogramMasking(TH1D* hist, TH1I* mask) {
 //*******************************************************************
 
   if (!mask) return ( (TH1D*)hist->Clone() );
 
   // This masking is only sufficient for chi2 calculations, and will have dodgy bin edges.
 
   // Get New Bin Count
   Int_t NBins = 0;
   for (int i = 0; i < hist->GetNbinsX(); i++) {
     if (mask->GetBinContent(i + 1)) continue;
     NBins++;
   }
 
   // Make new hist
   std::string newmaskname = std::string(hist->GetName()) + "_MSKD";
   TH1D* calc_hist = new TH1D( newmaskname.c_str(), newmaskname.c_str(), NBins, 0, NBins);
 
   // fill new hist
   int binindex = 0;
   for (int i = 0; i < hist->GetNbinsX(); i++) {
     if (mask->GetBinContent(i + 1)) {
       LOG(REC) << "Applying mask to bin " << i + 1 << " " << hist->GetName() << std::endl;
       continue;
     }
     calc_hist->SetBinContent(binindex + 1, hist->GetBinContent(i + 1));
     calc_hist->SetBinError(binindex + 1, hist->GetBinError(i + 1));
     binindex++;
   }
 
   return calc_hist;
 };
 
 //*******************************************************************
 TH2D* StatUtils::ApplyHistogramMasking(TH2D* hist, TH2I* mask) {
 //*******************************************************************
 
   TH2D* newhist = (TH2D*) hist->Clone();
 
   if (!mask) return newhist;
 
   for (int i = 0; i < hist->GetNbinsX(); i++) {
     for (int j = 0; j < hist->GetNbinsY(); j++) {
 
       if (mask->GetBinContent(i + 1, j + 1) > 0) {
         newhist->SetBinContent(i + 1, j + 1, 0.0);
         newhist->SetBinContent(i + 1, j + 1, 0.0);
       }
     }
   }
 
   return newhist;
 }
 
 //*******************************************************************
 TMatrixDSym* StatUtils::ApplyMatrixMasking(TMatrixDSym* mat, TH1I* mask) {
 //*******************************************************************
 
   if (!mask) return (TMatrixDSym*)(mat->Clone());
 
   // Get New Bin Count
   Int_t NBins = 0;
   for (int i = 0; i < mask->GetNbinsX(); i++) {
     if (mask->GetBinContent(i + 1)) continue;
     NBins++;
   }
 
   // make new matrix
   TMatrixDSym* calc_mat = new TMatrixDSym(NBins);
   int col, row;
 
   // Need to mask out bins in the current matrix
   row = 0;
   for (int i = 0; i < mask->GetNbinsX(); i++) {
     col = 0;
 
     // skip if masked
     if (mask->GetBinContent(i + 1) > 0.5) continue;
 
     for (int j = 0; j < mask->GetNbinsX(); j++) {
 
       // skip if masked
       if (mask->GetBinContent(j + 1) > 0.5) continue;
 
       (*calc_mat)(row, col) = (*mat)(i, j);
       col++;
     }
     row++;
   }
 
   return calc_mat;
 };
 
 //*******************************************************************
 TMatrixDSym* StatUtils::ApplyMatrixMasking(TMatrixDSym* mat, TH2D* data, TH2I* mask, TH2I* map) {
 //*******************************************************************
 
   if (!map) map = StatUtils::GenerateMap(data);
   TH1I* mask_1D = StatUtils::MapToMask(mask, map);
 
   TMatrixDSym* newmat = StatUtils::ApplyMatrixMasking(mat,  mask_1D);
 
   delete mask_1D;
   return newmat;
 }
 
 
 
 //*******************************************************************
 TMatrixDSym* StatUtils::ApplyInvertedMatrixMasking(TMatrixDSym* mat, TH1I* mask) {
 //*******************************************************************
 
   TMatrixDSym* new_mat = GetInvert(mat);
   TMatrixDSym* masked_mat = ApplyMatrixMasking(new_mat, mask);
 
   TMatrixDSym* inverted_mat = GetInvert(masked_mat);
 
   delete masked_mat;
   delete new_mat;
 
   return inverted_mat;
 };
 
 
 
 //*******************************************************************
 TMatrixDSym* StatUtils::ApplyInvertedMatrixMasking(TMatrixDSym* mat, TH2D* data, TH2I* mask, TH2I* map) {
 //*******************************************************************
 
   if (!map) map = StatUtils::GenerateMap(data);
   TH1I* mask_1D = StatUtils::MapToMask(mask, map);
 
   TMatrixDSym* newmat = ApplyInvertedMatrixMasking(mat, mask_1D);
 
   delete mask_1D;
   return newmat;
 }
 
 
 
 
 //*******************************************************************
 TMatrixDSym* StatUtils::GetInvert(TMatrixDSym* mat) {
 //*******************************************************************
 
   TMatrixDSym* new_mat = (TMatrixDSym*)mat->Clone();
 
   // Check for diagonal
   bool non_diagonal = false;
   for (int i = 0; i < new_mat->GetNrows(); i++) {
     for (int j = 0; j < new_mat->GetNrows(); j++) {
       if (i == j) continue;
 
       if ((*new_mat)(i, j) != 0.0) {
         non_diagonal = true;
         break;
       }
     }
   }
 
   // If diag, just flip the diag
   if (!non_diagonal or new_mat->GetNrows() == 1) {
     for (int i = 0; i < new_mat->GetNrows(); i++) {
       if ((*new_mat)(i, i) != 0.0)
         (*new_mat)(i, i) = 1.0 / (*new_mat)(i, i);
       else
         (*new_mat)(i, i) = 0.0;
     }
     return new_mat;
   }
 
 
   // Invert full matrix
   TDecompSVD LU = TDecompSVD((*new_mat));
   new_mat = new TMatrixDSym(new_mat->GetNrows(), LU.Invert().GetMatrixArray(), "");
 
   return new_mat;
 }
 
 //*******************************************************************
 TMatrixDSym* StatUtils::GetDecomp(TMatrixDSym* mat) {
 //*******************************************************************
 
   TMatrixDSym* new_mat = (TMatrixDSym*)mat->Clone();
   int nrows = new_mat->GetNrows();
 
   // Check for diagonal
   bool diagonal = true;
   for (int i = 0; i < nrows; i++) {
     for (int j = 0; j < nrows; j++) {
       if (i == j) continue;
 
       if ((*new_mat)(i, j) != 0.0) {
         diagonal = false;
         break;
       }
     }
   }
 
   // If diag, just flip the diag
   if (diagonal or nrows == 1) {
     for (int i = 0; i < nrows; i++) {
       if ((*new_mat)(i, i) > 0.0)
         (*new_mat)(i, i) = sqrt((*new_mat)(i, i));
       else
         (*new_mat)(i, i) = 0.0;
     }
     return new_mat;
   }
 
   TDecompChol LU = TDecompChol(*new_mat);
   LU.Decompose();
   delete new_mat;
 
   TMatrixDSym* dec_mat = new TMatrixDSym(nrows, LU.GetU().GetMatrixArray(), "");
 
   return dec_mat;
 }
 
 
 
 
 
 //*******************************************************************
 void StatUtils::ForceNormIntoCovar(TMatrixDSym* mat, TH1D* hist, double norm) {
 //*******************************************************************
 
   if (!mat) mat = MakeDiagonalCovarMatrix(hist);
 
   int nbins = mat->GetNrows();
   TMatrixDSym* new_mat = new TMatrixDSym(nbins);
 
   for (int i = 0; i < nbins; i++) {
     for (int j = 0; j < nbins; j++) {
 
       double valx = hist->GetBinContent(i + 1) * 1E38;
       double valy = hist->GetBinContent(j + 1) * 1E38;
 
       (*new_mat)(i, j) = (*mat)(i, j) + norm * norm * valx * valy;
 
     }
   }
 
   // Swap the two
   delete mat;
   mat = new_mat;
 
   return;
 };
 
 //*******************************************************************
 void StatUtils::ForceNormIntoCovar(TMatrixDSym* mat, TH2D* data, double norm, TH2I* map ) {
 //*******************************************************************
 
   if (!map) map = StatUtils::GenerateMap(data);
   TH1D* data_1D = MapToTH1D(data, map);
 
   StatUtils::ForceNormIntoCovar(mat, data_1D, norm);
   delete data_1D;
 
   return;
 }
 
 //*******************************************************************
 TMatrixDSym* StatUtils::MakeDiagonalCovarMatrix(TH1D* data, double scaleF) {
 //*******************************************************************
 
   TMatrixDSym* newmat = new TMatrixDSym(data->GetNbinsX());
 
   for (int i = 0; i < data->GetNbinsX(); i++) {
     (*newmat)(i, i) = data->GetBinError(i + 1) * data->GetBinError(i + 1) * scaleF * scaleF;
   }
 
   return newmat;
 }
 
 
 
 //*******************************************************************
 TMatrixDSym* StatUtils::MakeDiagonalCovarMatrix(TH2D* data, TH2I* map, double scaleF) {
 //*******************************************************************
 
   if (!map) map = StatUtils::GenerateMap(data);
   TH1D* data_1D = MapToTH1D(data, map);
 
   return StatUtils::MakeDiagonalCovarMatrix(data_1D, scaleF);
 };
 
 
 //*******************************************************************
 void StatUtils::SetDataErrorFromCov(TH1D* data, TMatrixDSym* cov, double scale) {
 //*******************************************************************
 
   // Check
   if (cov->GetNrows() != data->GetNbinsX()) {
     ERR(WRN) << "Nrows in cov don't match nbins in data for SetDataErrorFromCov" << std::endl;
   }
 
   // Set bin errors form cov diag
   for (int i = 0; i < data->GetNbinsX(); i++) {
     data->SetBinError(i + 1, sqrt((*cov)(i, i)) * scale );
   }
 
   return;
 }
 
 //*******************************************************************
 void StatUtils::SetDataErrorFromCov(TH2D* data, TMatrixDSym* cov, TH2I* map, double scale) {
 //*******************************************************************
 
   // Create map if required
   if (!map) map = StatUtils::GenerateMap(data);
 
   // Set Bin Errors from cov diag
   int count = 0;
   for (int i = 0; i < data->GetNbinsX(); i++) {
     for (int j = 0; j < data->GetNbinsY(); j++) {
 
       if (data->GetBinContent(i + 1, j + 1) == 0.0) continue;
 
       count = map->GetBinContent(i + 1, j + 1) - 1;
       data->SetBinError(i + 1, j + 1,  sqrt((*cov)(count, count)) * scale );
 
     }
   }
 
   return;
 }
 
 
 TMatrixDSym* StatUtils::ExtractShapeOnlyCovar(TMatrixDSym* full_covar, TH1* data_hist, double data_scale){
 
   int nbins = full_covar->GetNrows();
   TMatrixDSym* shape_covar = new TMatrixDSym(nbins);
 
   // Check nobody is being silly
   if (data_hist->GetNbinsX() != nbins){
     ERR(WRN) << "Inconsistent matrix and data histogram passed to StatUtils::ExtractShapeOnlyCovar!" << std::endl;
     ERR(WRN) << "data_hist has " << data_hist->GetNbinsX() << " matrix has " << nbins << std::endl;
     int err_bins = data_hist->GetNbinsX();
     if (nbins > err_bins) err_bins = nbins;
     for (int i = 0; i < err_bins; ++i){
       ERR(WRN) << "Matrix diag. = " << (*full_covar)(i, i) << " data = " << data_hist->GetBinContent(i+1) << std::endl;
     }
     return NULL;
   }
 
   double total_data  = 0;
   double total_covar = 0;
   
   // Initial loop to calculate some constants
   for (int i = 0; i < nbins; ++i) {
     total_data += data_hist->GetBinContent(i+1)*data_scale;
     for (int j = 0; j < nbins; ++j) {
       total_covar += (*full_covar)(i,j);
     }
   }
   
   if (total_data == 0 || total_covar == 0){
     ERR(WRN) << "Stupid matrix or data histogram passed to StatUtils::ExtractShapeOnlyCovar! Ignoring..." << std::endl;
     return NULL;
   }
 
   LOG(SAM) << "Norm error = " << sqrt(total_covar)/total_data << std::endl;
   
   // Now loop over and calculate the shape-only matrix
   for (int i = 0; i < nbins; ++i) {
     double data_i = data_hist->GetBinContent(i+1)*data_scale;
 
     for (int j = 0; j < nbins; ++j) {
       double data_j = data_hist->GetBinContent(j+1)*data_scale;
 	
       double norm_term = data_i*data_j*total_covar/total_data/total_data;
       double mix_sum1 = 0;
       double mix_sum2 = 0;
       
       for (int k = 0; k < nbins; ++k){
 	mix_sum1 += (*full_covar)(k,j);
 	mix_sum2 += (*full_covar)(i,k);
       }
 
       double mix_term1 = data_i*(mix_sum1/total_data - total_covar*data_j/total_data/total_data);
       double mix_term2 = data_j*(mix_sum2/total_data - total_covar*data_i/total_data/total_data);
       
       (*shape_covar)(i, j) = (*full_covar)(i, j) - mix_term1 - mix_term2 - norm_term;
     }
   }
   return shape_covar;
 }
 
 
 //*******************************************************************
 TH2I* StatUtils::GenerateMap(TH2D* hist) {
 //*******************************************************************
 
   std::string maptitle = std::string(hist->GetName()) + "_MAP";
 
   TH2I* map = new TH2I( maptitle.c_str(), maptitle.c_str(),
                         hist->GetNbinsX(), 0, hist->GetNbinsX(),
                         hist->GetNbinsY(), 0, hist->GetNbinsY());
 
   Int_t index = 1;
 
   for (int i = 0; i < hist->GetNbinsX(); i++) {
     for (int j = 0; j < hist->GetNbinsY(); j++) {
 
       if (hist->GetBinContent(i + 1, j + 1) > 0 && hist->GetBinError(i + 1, j + 1) > 0) {
 
         map->SetBinContent(i + 1, j + 1, index);
         index++;
       } else {
         map->SetBinContent(i + 1, j + 1, 0);
       }
     }
   }
 
   return map;
 }
 
 //*******************************************************************
 TH1D* StatUtils::MapToTH1D(TH2D* hist, TH2I* map) {
 //*******************************************************************
 
   if (!hist) return NULL;
 
   // Get N bins for 1D plot
   Int_t Nbins = map->GetMaximum();
   std::string name1D = std::string(hist->GetName()) + "_1D";
 
   // Make new 1D Hist
   TH1D* newhist = new TH1D(name1D.c_str(), name1D.c_str(), Nbins, 0, Nbins);
 
   // map bin contents
   for (int i = 0; i < map->GetNbinsX(); i++) {
     for (int j = 0; j < map->GetNbinsY(); j++) {
 
       if (map->GetBinContent(i + 1, j + 1) == 0) continue;
 
       newhist->SetBinContent(map->GetBinContent(i + 1, j + 1), hist->GetBinContent(i + 1, j + 1));
       newhist->SetBinError(map->GetBinContent(i + 1, j + 1),   hist->GetBinError(i + 1, j + 1));
     }
   }
 
   // return
   return newhist;
 }
 
 
 //*******************************************************************
 TH1I* StatUtils::MapToMask(TH2I* hist, TH2I* map) {
 //*******************************************************************
 
   TH1I* newhist = NULL;
   if (!hist) return newhist;
 
   // Get N bins for 1D plot
   Int_t Nbins = map->GetMaximum();
   std::string name1D = std::string(hist->GetName()) + "_1D";
 
   // Make new 1D Hist
   newhist = new TH1I(name1D.c_str(), name1D.c_str(), Nbins, 0, Nbins);
 
   // map bin contents
   for (int i = 0; i < map->GetNbinsX(); i++) {
     for (int j = 0; j < map->GetNbinsY(); j++) {
 
       if (map->GetBinContent(i + 1, j + 1) == 0) continue;
 
       newhist->SetBinContent(map->GetBinContent(i + 1, j + 1), hist->GetBinContent(i + 1, j + 1));
     }
   }
 
   // return
   return newhist;
 }
 
 
 TMatrixDSym* StatUtils::GetCovarFromCorrel(TMatrixDSym* correl, TH1D* data) {
 
   int nbins = correl->GetNrows();
   TMatrixDSym* covar = new TMatrixDSym(nbins);
 
   for (int i = 0; i < nbins; i++) {
     for (int j = 0; j < nbins; j++) {
       (*covar)(i, j) = (*correl)(i, j) * data->GetBinError(i + 1) * data->GetBinError(j + 1);
     }
   }
 
   return covar;
 }
 
 
 
 //*******************************************************************
 TMatrixD* StatUtils::GetMatrixFromTextFile(std::string covfile, int dimx, int dimy) {
 //*******************************************************************
 
   // Determine dim
   if (dimx == -1 and dimy == -1) {
     std::string line;
     std::ifstream covar(covfile.c_str(), std::ifstream::in);
 
     int row = 0;
     while (std::getline(covar >> std::ws, line, '\n')) {
       int column = 0;
 
       std::vector<double> entries = GeneralUtils::ParseToDbl(line, " ");
 
       if (entries.size() <= 1) {
 	ERR(WRN) << "StatUtils::GetMatrixFromTextFile, matrix only has <= 1 "
 	  "entries on this line: " << row << std::endl;
       }
       for (std::vector<double>::iterator iter = entries.begin();
            iter != entries.end(); iter++) {
         column++;
 
         if (column > dimx) dimx = column;
       }
       row++;
       if (row > dimy) dimy = row;
     }
   }
 
   // Or assume symmetric
   if (dimx != -1 and dimy == -1) {
     dimy = dimx;
   }
   assert(dimy != -1 && " matrix dimy not set.");
 
   // Make new matrix
   TMatrixD* mat = new TMatrixD(dimx, dimy);
   std::string line;
   std::ifstream covar(covfile.c_str(), std::ifstream::in);
 
   int row = 0;
   while (std::getline(covar >> std::ws, line, '\n')) {
     int column = 0;
 
     std::vector<double> entries = GeneralUtils::ParseToDbl(line, " ");
     if (entries.size() <= 1) {
       ERR(WRN) << "StatUtils::GetMatrixFromTextFile, matrix only has <= 1 "
 	"entries on this line: " << row << std::endl;
     }
     for (std::vector<double>::iterator iter = entries.begin();
          iter != entries.end(); iter++) {
 
       // Check Rows
       //assert(row > mat->GetNrows() && " covar rows doesn't match matrix rows.");
       //assert(column > mat->GetNcols() && " covar cols doesn't match matrix cols.");
 
       // Fill Matrix
       (*mat)(row, column) = (*iter);
       column++;
     }
     row++;
   }
 
   return mat;
 }
 
 //*******************************************************************
 TMatrixD* StatUtils::GetMatrixFromRootFile(std::string covfile, std::string histname) {
 //*******************************************************************
 
   std::string inputfile = covfile + ";" + histname;
   std::vector<std::string> splitfile = GeneralUtils::ParseToStr(inputfile, ";");
 
   if (splitfile.size() < 2) {
     ERR(FTL) << "No object name given!" << std::endl;
     throw;
   }
 
   // Get file
   TFile* tempfile = new TFile(splitfile[0].c_str(), "READ");
 
   // Get Object
   TObject* obj = tempfile->Get(splitfile[1].c_str());
   if (!obj) {
     ERR(FTL) << "Object " << splitfile[1] << " doesn't exist!" << std::endl;
     throw;
   }
 
   // Try casting
   TMatrixD* mat = dynamic_cast<TMatrixD*>(obj);
   if (mat) {
 
     TMatrixD* newmat = (TMatrixD*)mat->Clone();
 
     delete mat;
     tempfile->Close();
 
     return newmat;
   }
 
   TMatrixDSym* matsym = dynamic_cast<TMatrixDSym*>(obj);
   if (matsym) {
 
     TMatrixD* newmat = new TMatrixD(matsym->GetNrows(), matsym->GetNrows());
     for (int i = 0; i < matsym->GetNrows(); i++) {
       for (int j = 0; j < matsym->GetNrows(); j++) {
         (*newmat)(i, j) = (*matsym)(i, j);
       }
     }
 
     delete matsym;
     tempfile->Close();
 
     return newmat;
   }
 
   TH2D* mathist = dynamic_cast<TH2D*>(obj);
   if (mathist) {
     TMatrixD* newmat = new TMatrixD(mathist->GetNbinsX(), mathist->GetNbinsX());
     for (int i = 0; i < mathist->GetNbinsX(); i++) {
       for (int j = 0; j < mathist->GetNbinsX(); j++) {
         (*newmat)(i, j) = mathist->GetBinContent(i + 1, j + 1);
       }
     }
 
     delete mathist;
     tempfile->Close();
 
     return newmat;
   }
 
   return NULL;
 }
 
 //*******************************************************************
 TMatrixDSym* StatUtils::GetCovarFromTextFile(std::string covfile, int dim){
 //*******************************************************************
 
   // Delete TempMat
   TMatrixD* tempmat = GetMatrixFromTextFile(covfile, dim, dim);
 
   // Make a symmetric covariance
   TMatrixDSym* newmat = new TMatrixDSym(tempmat->GetNrows());
   for (int i = 0; i < tempmat->GetNrows(); i++){
     for (int j = 0; j < tempmat->GetNrows(); j++){
       (*newmat)(i,j) = (*tempmat)(i,j);
     }
   }
 
 
   delete tempmat;
   return newmat;
 }
 
 //*******************************************************************
 TMatrixDSym* StatUtils::GetCovarFromRootFile(std::string covfile, std::string histname){
 //*******************************************************************
 
   TMatrixD* tempmat = GetMatrixFromRootFile(covfile, histname);
   TMatrixDSym* newmat = new TMatrixDSym(tempmat->GetNrows());
 
   for (int i = 0; i < tempmat->GetNrows(); i++){
     for (int j = 0; j < tempmat->GetNrows(); j++){
       (*newmat)(i,j) = (*tempmat)(i,j);
     }
   }
 
   delete tempmat;
   return newmat;
 }
diff --git a/src/Utils/StatUtils.h b/src/Statistical/StatUtils.h
similarity index 99%
rename from src/Utils/StatUtils.h
rename to src/Statistical/StatUtils.h
index bf26e90..f22e67c 100644
--- a/src/Utils/StatUtils.h
+++ b/src/Statistical/StatUtils.h
@@ -1,255 +1,255 @@
 // Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret
 
 /*******************************************************************************
 *    This file is part of NUISANCE.
 *
 *    NUISANCE is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    NUISANCE is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with NUISANCE.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
 
 #ifndef STATUTILS_H
 #define STATUTILS_H
 
 // C Includes
 #include <stdlib.h>
 #include <numeric>
 #include <math.h>
 #include <string>
 #include <iostream>
 #include <sstream>
 #include <iomanip>
 #include <deque>
 #include "assert.h"
 
 // Root Includes
 #include "TH1D.h"
 #include "TH2I.h"
 #include "TH2D.h"
 #include "TFile.h"
 #include "TMatrixDSym.h"
 #include "TDecompSVD.h"
 #include "TMath.h"
 #include "TRandom3.h"
 #include "TDecompChol.h"
 #include "TGraphErrors.h"
 
 
 // Fit Includes
-#include "FitParameters.h"
+
 #include "FitLogger.h"
 
 /*!
  *  \addtogroup Utils
  *  @{
  */
 
 //! Functions for handling statistics calculations
 namespace StatUtils{
 
   /*
     Chi2 Functions
   */
 
   //! Get Chi2 using diagonal bin errors from the histogram. Masking applied before calculation if mask provided.
   Double_t GetChi2FromDiag(TH1D* data, TH1D* mc, TH1I* mask=NULL);
 
   //! Get Chi2 using diagonal bin errors from the histogram.
   //! Plots converted to 1D histograms before using 1D calculation.
   Double_t GetChi2FromDiag(TH2D* data, TH2D* mc, TH2I* map=NULL, TH2I* mask=NULL);
 
   //! Get Chi2 using an inverted covariance for the data
   Double_t GetChi2FromCov( TH1D* data, TH1D* mc, TMatrixDSym* invcov, TH1I* mask=NULL, double data_scale=1, double covar_scale=1E76);
 
   //! Get Chi2 using an inverted covariance for the data
   //! Plots converted to 1D histograms before using 1D calculation.
   Double_t GetChi2FromCov( TH2D* data, TH2D* mc, TMatrixDSym* invcov, TH2I* map=NULL, TH2I* mask=NULL);
 
   //! Get Chi2 using an SVD method on the covariance before calculation.
   //! Method suggested by Rex at MiniBooNE. Shown that it doesn't actually work.
   Double_t GetChi2FromSVD( TH1D* data, TH1D* mc, TMatrixDSym* cov,    TH1I* mask=NULL);
 
   //! Get Chi2 using an SVD method on the covariance before calculation.
   //! Method suggested by Rex at MiniBooNE. Shown that it doesn't actually work.
   //! Plots converted to 1D histograms before using 1D calculation.
   Double_t GetChi2FromSVD( TH2D* data, TH2D* mc, TMatrixDSym* cov,    TH2I* map=NULL, TH2I* mask=NULL);
 
 
   //! Get Chi2 using only the raw event rates given in each bin using a -2LL method.
   Double_t GetChi2FromEventRate(TH1D* data, TH1D* mc, TH1I* mask=NULL);
 
   //! Get Chi2 using only the raw event rates given in each bin using a -2LL method.
   //! Plots converted to 1D histograms before using 1D calculation.
   Double_t GetChi2FromEventRate(TH2D* data, TH2D* mc, TH2I* map=NULL, TH2I* mask=NULL);
 
   // Likelihood Functions
 
   //! Placeholder for 1D binned likelihood method
   Double_t GetLikelihoodFromDiag(TH1D* data, TH1D* mc, TH1I* mask=NULL);
   //! Placeholder for 2D binned likelihood method
   Double_t GetLikelihoodFromDiag(TH2D* data, TH2D* mc, TH2I* map=NULL, TH2I* mask=NULL);
 
   //! Placeholder for 1D binned likelihood method
   Double_t GetLikelihoodFromCov( TH1D* data, TH1D* mc, TMatrixDSym* invcov, TH1I* mask=NULL);
   //! Placeholder for 2D binned likelihood method
   Double_t GetLikelihoodFromCov( TH2D* data, TH2D* mc, TMatrixDSym* invcov, TH2I* map=NULL, TH2I* mask=NULL);
 
   //! Placeholder for 1D binned likelihood method
   Double_t GetLikelihoodFromSVD( TH1D* data, TH1D* mc, TMatrixDSym* cov,    TH1I* mask=NULL);
   //! Placeholder for 2D binned likelihood method
   Double_t GetLikelihoodFromSVD( TH2D* data, TH2D* mc, TMatrixDSym* cov,    TH2I* map=NULL, TH2I* mask=NULL);
 
   //! Placeholder for 1D binned likelihood method
   Double_t GetLikelihoodFromEventRate(TH1D* data, TH1D* mc, TH1I* mask=NULL);
   //! Placeholder for 2D binned likelihood method
   Double_t GetLikelihoodFromEventRate(TH2D* data, TH2D* mc, TH2I* map=NULL, TH2I* mask=NULL);
 
   /*
      NDOF Functions
   */
 
   //! Return 1D Histogram NDOF considering masking and empty bins
   Int_t GetNDOF(TH1D* hist, TH1I* mask=NULL);
 
   //! Return 2D Histogram NDOF considering masking and empty bins
   Int_t GetNDOF(TH2D* hist, TH2I* map=NULL, TH2I* mask=NULL);
 
   /*
     Fake Data Functions
   */
 
   //! Given a full covariance for a 1D data set throw the decomposition to generate fake data.
   //! throwdiag determines whether diagonal statistical errors are thrown.
   //! If no covariance is provided only statistical errors are thrown.
   TH1D* ThrowHistogram(TH1D* hist, TMatrixDSym* cov, bool throwdiag=true, TH1I* mask=NULL);
 
   //! Given a full covariance for a 2D data set throw the decomposition to generate fake data.
   //! Plots are converted to 1D histograms and the 1D ThrowHistogram is used, before being converted back to 2D histograms.
   TH2D* ThrowHistogram(TH2D* hist, TMatrixDSym* cov, TH2I* map=NULL, bool throwdiag=true, TH2I* mask=NULL);
 
 
   /*
     Masking Functions
   */
 
   //! Given a mask histogram, mask out any bins in hist with non zero entries in mask.
   TH1D* ApplyHistogramMasking(TH1D* hist, TH1I* mask);
 
   //! Given a mask histogram, mask out any bins in hist with non zero entries in mask.
   TH2D* ApplyHistogramMasking(TH2D* hist, TH2I* mask);
 
   //! Given a mask histogram apply the masking procedure to each of the rows/columns in a covariance, before recalculating its inverse.
   TMatrixDSym* ApplyInvertedMatrixMasking(TMatrixDSym* mat, TH1I* mask);
 
   //! Given a mask histogram apply the masking procedure to each of the rows/columns in a covariance, before recalculating its inverse.
   //! Converts to 1D data before using the 1D ApplyInvertedMatrixMasking function and converting back to 2D.
   TMatrixDSym* ApplyInvertedMatrixMasking(TMatrixDSym* mat, TH2D* data, TH2I* mask, TH2I* map=NULL);
 
   //! Given a mask histogram apply the masking procedure to each of the rows/columns in a covariance
   TMatrixDSym* ApplyMatrixMasking(TMatrixDSym* mat, TH1I* mask);
 
   //! Given a mask histogram apply the masking procedure to each of the rows/columns in a covariance
   //! Converts to 1D data before using the 1D ApplyInvertedMatrixMasking function and converting back to 2D.
   TMatrixDSym* ApplyMatrixMasking(TMatrixDSym* mat, TH2D* data, TH2I* mask, TH2I* map=NULL);
 
   /*
     Covariance Handling Functions
   */
 
   //! Return inverted matrix of TMatrixDSym
   TMatrixDSym* GetInvert(TMatrixDSym* mat);
 
   //! Return Cholesky Decomposed matrix of TMatrixDSym
   TMatrixDSym* GetDecomp(TMatrixDSym* mat);
 
   //! Return full covariances
   TMatrixDSym* GetCovarFromCorrel(TMatrixDSym* correl, TH1D* data);
 
   //! Given a normalisation factor for a dataset add in a new normalisation term to the covariance.
   void ForceNormIntoCovar(TMatrixDSym* mat, TH1D* data, double norm);
 
   //! Given a normalisation factor for a dataset add in a new normalisation term to the covariance.
   //! Convertes 2D to 1D, before using 1D ForceNormIntoCovar
   void ForceNormIntoCovar(TMatrixDSym* mat, TH2D* data, double norm, TH2I* map=NULL);
 
   //! Given a dataset generate an uncorrelated covariance matrix using the bin errors.
   TMatrixDSym* MakeDiagonalCovarMatrix(TH1D* data, double scaleF=1E38);
 
   //! Given a dataset generate an uncorrelated covariance matrix using the bin errors.
   TMatrixDSym* MakeDiagonalCovarMatrix(TH2D* data, TH2I* map=NULL, double scaleF=1E38);
 
   //! Given a covariance set the errors in each bin on the data from the covariance diagonals.
   void SetDataErrorFromCov(TH1D* data, TMatrixDSym* cov, double scale=1.0);
 
   //! Given a covariance set the errors in each bin on the data from the covariance diagonals.
   void SetDataErrorFromCov(TH2D* data, TMatrixDSym* cov, TH2I* map=NULL, double scale=1.0);
 
   //! Given a covariance, extracts the shape-only matrix using the method from the MiniBooNE TN
   TMatrixDSym* ExtractShapeOnlyCovar(TMatrixDSym* full_covar, TH1* data_hist, double data_scale=1E38);
 
   /*
     Mapping Functions
   */
 
   //! If no map is provided for the 2D histogram, generate one by counting up through the bins along x and y.
   TH2I* GenerateMap(TH2D* hist);
 
   //! Apply a map to a 2D histogram converting it into a 1D histogram.
   TH1D* MapToTH1D(TH2D* hist, TH2I* map);
 
   //! Apply a map to a 2D mask convering it into a 1D mask.
   TH1I* MapToMask(TH2I* hist, TH2I* map);
 
 
   /// \brief Read TMatrixD from a text file
   ///
   /// - covfile = full path to text file
   /// - dimx = x dimensions of matrix
   /// - dimy = y dimensions of matrix
   ///
   /// Format of textfile should be: \n
   /// cov_11  cov_12 ...  cov_1N \n
   /// cov_21  cov_22 ...  cov_2N \n
   /// ...     ...    ...  ...    \n
   /// cov_N1  ...    ...  cov_NN \n
   ///
   /// If no dimensions are given, dimx and dimy are determined from rows/columns
   /// inside textfile.
   ///
   /// If only dimx is given a symmetric matrix is assumed.
   TMatrixD* GetMatrixFromTextFile(std::string covfile, int dimx=-1, int dimy=-1);
 
 
   /// \brief Read TMatrixD from a ROOT file
   ///
   /// - covfile = full path to root file (+';histogram')
   /// - histname = histogram name
   ///
   /// If no histogram name is given function assumes it has been appended
   /// covfile path as: \n
   /// 'covfile.root;histname' 
   ///
   /// histname can point to a TMatrixD object, a TMatrixDSym object, or
   /// a TH2D object.
   TMatrixD* GetMatrixFromRootFile(std::string covfile, std::string histname="");
 
   /// \brief Calls GetMatrixFromTextFile and turns it into a TMatrixDSym
   TMatrixDSym* GetCovarFromTextFile(std::string covfile, int dim);
 
   /// \brief Calls GetMatrixFromRootFile and turns it into a TMatrixDSym
   TMatrixDSym* GetCovarFromRootFile(std::string covfile, std::string histname);
 
 
 };
 
 /*! @} */
 #endif
diff --git a/src/Tests/ParserTests.cxx b/src/Tests/ParserTests.cxx
index 566a0ff..55f1f3d 100644
--- a/src/Tests/ParserTests.cxx
+++ b/src/Tests/ParserTests.cxx
@@ -1,100 +1,103 @@
 #include <cassert>
 #include <sstream>
 
 #include "FitLogger.h"
-#include "FitParameters.h"
+#include "GeneralUtils.h"
+#include "NuisConfig.h"
+#include "StatUtils.h"
 #include "InputUtils.h"
 
 int main(int argc, char const *argv[]) {
   LOG_VERB(SAM);
   LOG(FIT) << "*            Running InputUtils Tests" << std::endl;
   LOG(FIT) << "***************************************************"
            << std::endl;
 
-  Config::Get().OverrideConfig("NEUT_DIR=/var/test/NEUT");
-  Config::Get().OverrideConfig("NUWRO_DIR=/var/test/NUWRO");
-  Config::Get().OverrideConfig("GENIE_DIR=/var/test/GENIE");
-  Config::Get().OverrideConfig("GIBUU_DIR=/var/test/GIBUU");
+  Config::SetPar("NEUT_DIR","/var/test/NEUT");
+  Config::SetPar("NUWRO_DIR","/var/test/NUWRO");
+  Config::SetPar("GIBUU_DIR","/var/test/NIBUU");
+  Config::SetPar("GENIE_DIR","/var/test/GENIE");
 
   std::string NEUTInp = "NEUT:@NEUT_DIR/file.root";
   InputUtils::InputType NEUTInpt =
       InputUtils::ParseInputType(GeneralUtils::ParseToStr(NEUTInp, ":")[0]);
   std::string ExpandNEUT = InputUtils::ExpandInputDirectories(
       GeneralUtils::ParseToStr(NEUTInp, ":")[1]);
   bool IsJointNEUT_not =
       InputUtils::IsJointInput(GeneralUtils::ParseToStr(NEUTInp, ":")[1]);
 
   std::string NEUTJointInp = "NEUT:(@NEUT_DIR/file1.root,@NEUT_DIR/file2.root)";
   bool IsJointNEUT = InputUtils::IsJointInput(
       GeneralUtils::ParseToStr(NEUTJointInp, ":")[1]);
   std::string ExpandNEUTJoint = InputUtils::ExpandInputDirectories(
       GeneralUtils::ParseToStr(NEUTJointInp, ":")[1]);
 
   std::string NEUTJointInp_MissFSlash =
       "NEUT:(@NEUT_DIR/file1.root,@NEUT_DIR/file2.root)";
   std::string ExpandNEUTJoint_MissFSlash = InputUtils::ExpandInputDirectories(
       GeneralUtils::ParseToStr(NEUTJointInp_MissFSlash, ":")[1]);
 
-  Config::Get().OverrideConfig("NEUT_DIR=/var/test/NEUT/");
+  Config::SetPar("NEUT_DIR","/var/test/NEUT/");
+
   std::string NEUTJointInp_DoubleFSlash =
       "NEUT:(@NEUT_DIR/file1.root,@NEUT_DIR/file2.root)";
   std::string ExpandNEUTJoint_DoubleFSlash = InputUtils::ExpandInputDirectories(
       GeneralUtils::ParseToStr(NEUTJointInp_DoubleFSlash, ":")[1]);
 
   LOG(FIT) << "    *        Test input type parse" << std::endl;
   LOG(FIT) << "        *        Test parse 'NEUT'" << std::endl;
   if (!(NEUTInpt == InputUtils::kNEUT_Input)) {
     ERR(FTL) << GeneralUtils::ParseToStr(NEUTInp, ":")[0]
              << " parsed as type: " << NEUTInpt << std::endl;
   }
   assert(NEUTInpt == InputUtils::kNEUT_Input);
   LOG(FIT) << "    *        Test IsJoint check" << std::endl;
   LOG(FIT) << "        *        Test IsJoint on non joint" << std::endl;
   if (IsJointNEUT_not) {
     ERR(FTL) << GeneralUtils::ParseToStr(NEUTInp, ":")[1] << " parsed as Joint."
              << std::endl;
   }
   assert(!IsJointNEUT_not);
   LOG(FIT) << "        *        Test IsJoint on joint" << std::endl;
   if (!IsJointNEUT) {
     ERR(FTL) << GeneralUtils::ParseToStr(NEUTJointInp, ":")[1]
              << " parsed as not Joint." << std::endl;
   }
   assert(IsJointNEUT);
   LOG(FIT) << "    *        Test directory expansion" << std::endl;
   if ("/var/test/NEUT/file.root" != ExpandNEUT) {
     ERR(FTL) << GeneralUtils::ParseToStr(NEUTInp, ":")[1]
              << " expanded to: " << ExpandNEUT << std::endl;
   }
   assert("/var/test/NEUT/file.root" == ExpandNEUT);
   LOG(FIT) << "        *        Test joint directory expansion" << std::endl;
   if ("(/var/test/NEUT/file1.root,/var/test/NEUT/file2.root)" !=
       ExpandNEUTJoint) {
     ERR(FTL) << GeneralUtils::ParseToStr(NEUTJointInp, ":")[1]
              << " expanded to: " << ExpandNEUTJoint << std::endl;
   }
   assert("(/var/test/NEUT/file1.root,/var/test/NEUT/file2.root)" ==
          ExpandNEUTJoint);
   LOG(FIT) << "        *        Test joint directory expansion missing slash"
            << std::endl;
   if ("(/var/test/NEUT/file1.root,/var/test/NEUT/file2.root)" !=
       ExpandNEUTJoint_MissFSlash) {
     ERR(FTL) << GeneralUtils::ParseToStr(NEUTJointInp_MissFSlash, ":")[1]
              << " expanded to: " << ExpandNEUTJoint_MissFSlash << std::endl;
   }
   assert("(/var/test/NEUT/file1.root,/var/test/NEUT/file2.root)" ==
          ExpandNEUTJoint_MissFSlash);
   LOG(FIT) << "        *        Test joint directory expansion double slash"
            << std::endl;
   if ("(/var/test/NEUT/file1.root,/var/test/NEUT/file2.root)" !=
       ExpandNEUTJoint_DoubleFSlash) {
     ERR(FTL) << GeneralUtils::ParseToStr(NEUTJointInp_DoubleFSlash, ":")[1]
              << " expanded to: " << ExpandNEUTJoint_DoubleFSlash << std::endl;
   }
   assert("(/var/test/NEUT/file1.root,/var/test/NEUT/file2.root)" ==
          ExpandNEUTJoint_DoubleFSlash);
 
   LOG(FIT) << "*            Passed InputUtils Tests" << std::endl;
   LOG(FIT) << "***************************************************"
            << std::endl;
 }
diff --git a/src/Utils/CMakeLists.txt b/src/Utils/CMakeLists.txt
index d96b8c6..25a22c4 100644
--- a/src/Utils/CMakeLists.txt
+++ b/src/Utils/CMakeLists.txt
@@ -1,93 +1,77 @@
 # Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret
 
 ################################################################################
 #    This file is part of NUISANCE.
 #
 #    NUISANCE is free software: you can redistribute it and/or modify
 #    it under the terms of the GNU General Public License as published by
 #    the Free Software Foundation, either version 3 of the License, or
 #    (at your option) any later version.
 #
 #    NUISANCE is distributed in the hope that it will be useful,
 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 #    GNU General Public License for more details.
 #
 #    You should have received a copy of the GNU General Public License
 #    along with NUISANCE.  If not, see <http://www.gnu.org/licenses/>.
 ################################################################################
 set(HEADERFILES
-FitLogger.h
-FitParameters.h
 FitUtils.h
 GeneralUtils.h
 ParserUtils.h
 PlotUtils.h
-StatUtils.h
 SignalDef.h
-NuisConfig.h
-NuisKey.h
 BeamUtils.h
 TargetUtils.h
-StackBase.h
-StandardStacks.h
 OpenMPWrapper.h
 PhysConst.h
-Initialiser.h
 )
 
 set(IMPLFILES
-PythiaQuiet.f
-FitLogger.cxx
-FitParameters.cxx
 FitUtils.cxx
 GeneralUtils.cxx
 PlotUtils.cxx
-StatUtils.cxx
 SignalDef.cxx
-NuisConfig.cxx
-NuisKey.cxx
 BeamUtils.cxx
 TargetUtils.cxx
-StackBase.cxx
 ParserUtils.cxx
-StandardStacks.cxx
-Initialiser.cxx
 )
 
 set(LIBNAME Utils)
 
 if(CMAKE_BUILD_TYPE MATCHES DEBUG)
   add_library(${LIBNAME} STATIC ${IMPLFILES})
 else(CMAKE_BUILD_TYPE MATCHES RELEASE)
   add_library(${LIBNAME} SHARED ${IMPLFILES})
 endif()
 
 include_directories(${MINIMUM_INCLUDE_DIRECTORIES})
+include_directories(${CMAKE_SOURCE_DIR}/src/Logger)
+include_directories(${CMAKE_SOURCE_DIR}/src/Statistical)
 
 set_target_properties(${LIBNAME} PROPERTIES VERSION
   "${NUISANCE_VERSION_MAJOR}.${NUISANCE_VERSION_MINOR}.${NUISANCE_VERSION_REVISION}")
 
 #set_target_properties(${LIBNAME} PROPERTIES LINK_FLAGS ${ROOT_LD_FLAGS})
 
 if(DEFINED PROJECTWIDE_EXTRA_DEPENDENCIES)
   add_dependencies(${LIBNAME} ${PROJECTWIDE_EXTRA_DEPENDENCIES})
 endif()
 
 install(TARGETS ${LIBNAME} DESTINATION lib)
 #Can uncomment this to install the headers... but is it really neccessary?
 #install(FILES ${HEADERFILES} DESTINATION include)
 
 set(MODULETargets ${MODULETargets} ${LIBNAME} PARENT_SCOPE)
 
-add_executable(DumpROOTClassesFromVector DumpROOTClassesFromVector.cxx GeneralUtils.cxx FitLogger.cxx PythiaQuiet.f)
-
-  #Strip out -lNuWro_event1
-  string(REPLACE "-lNuWro_event1" "" NWEVSTRIPPED_CDF ${CMAKE_DEPENDLIB_FLAGS})
-  cmessage(DEBUG "Attempted to strip out nuwro library: \"${CMAKE_DEPENDLIB_FLAGS}\" -> \"${NWEVSTRIPPED_CDF}\"")
-  target_link_libraries(DumpROOTClassesFromVector ${NWEVSTRIPPED_CDF})
-  if(NOT CMAKE_LINK_FLAGS STREQUAL "")
-    set_target_properties(DumpROOTClassesFromVector PROPERTIES LINK_FLAGS ${CMAKE_LINK_FLAGS})
-  endif()
-
-install(TARGETS DumpROOTClassesFromVector DESTINATION bin)
+#add_executable(DumpROOTClassesFromVector DumpROOTClassesFromVector.cxx GeneralUtils.cxx FitLogger.cxx PythiaQuiet.f)
+#
+#  #Strip out -lNuWro_event1
+#  string(REPLACE "-lNuWro_event1" "" NWEVSTRIPPED_CDF ${CMAKE_DEPENDLIB_FLAGS})
+#  cmessage(DEBUG "Attempted to strip out nuwro library: \"${CMAKE_DEPENDLIB_FLAGS}\" -> \"${NWEVSTRIPPED_CDF}\"")
+#  target_link_libraries(DumpROOTClassesFromVector ${NWEVSTRIPPED_CDF})
+#  if(NOT CMAKE_LINK_FLAGS STREQUAL "")
+#    set_target_properties(DumpROOTClassesFromVector PROPERTIES LINK_FLAGS ${CMAKE_LINK_FLAGS})
+#  endif()
+#install(TARGETS DumpROOTClassesFromVector DESTINATION bin)
diff --git a/src/Utils/FitParameters.cxx b/src/Utils/FitParameters.cxx
deleted file mode 100644
index 38271bf..0000000
--- a/src/Utils/FitParameters.cxx
+++ /dev/null
@@ -1,225 +0,0 @@
-// Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret
-
-/*******************************************************************************
-*    This file is part of NUISANCE.
-*
-*    NUISANCE is free software: you can redistribute it and/or modify
-*    it under the terms of the GNU General Public License as published by
-*    the Free Software Foundation, either version 3 of the License, or
-*    (at your option) any later version.
-*
-*    NUISANCE is distributed in the hope that it will be useful,
-*    but WITHOUT ANY WARRANTY; without even the implied warranty of
-*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-*    GNU General Public License for more details.
-*
-*    You should have received a copy of the GNU General Public License
-*    along with NUISANCE.  If not, see <http://www.gnu.org/licenses/>.
-*******************************************************************************/
-
-#include "FitParameters.h"
-
-// Initialise the static members for the parameters class
-FitParameters* FitParameters::m_fitparameterInstance = NULL;
-
-FitParameters& FitParameters::GetParams(void) {
-  if (!m_fitparameterInstance) {
-    m_fitparameterInstance = new FitParameters;
-  }
-
-  return *m_fitparameterInstance;
-};
-
-FitParameters::~FitParameters() { parameterMap_all.clear(); };
-
-FitParameters::FitParameters() {
-  this->iteration = 0;
-
-  std::string NUISANCE_dir = GeneralUtils::GetTopLevelDir();
-  this->ReadParamFile(NUISANCE_dir + "/parameters/fitter.config.dat");
-};
-
-void FitParameters::SetParamFile(std::string fileName) {
-  parFileName = fileName;
-  return;
-}
-
-// Parameter File Parser
-void FitParameters::ReadParamFile(std::string fileName) {
-  std::string line;
-  std::ifstream card(fileName.c_str(), std::ifstream::in);
-
-  while (std::getline(card >> std::ws, line, '\n')) {
-    std::vector<std::string> inputlist = GeneralUtils::ParseToStr(line, " ");
-
-    // Check the line length
-    if (inputlist.size() < 3) continue;
-
-    // Check whether this is a comment
-    if (inputlist[0].c_str()[0] == '#') continue;
-
-    // Check whether this is a relevant line
-    if (inputlist[0].compare("config") != 0) continue;
-
-    std::string parName = inputlist[1];
-    std::string parEntry = inputlist[2];
-    if (parameterMap_all.find(parName) == parameterMap_all.end())
-      parameterMap_all.insert(
-          std::map<std::string, std::string>::value_type(parName, parEntry));
-    else
-      parameterMap_all[parName] = parEntry;
-  }
-  card.close();
-  return;
-}
-
-// Used to override a parameter by the command line
-void FitParameters::ForceParam(std::string parOption) {
-  unsigned first = parOption.find("=");
-  std::string parName = parOption.substr(0, first);
-  std::string parEntry = parOption.substr(first + 1, parOption.size());
-
-  QLOG(REC,"Read in Parameter Override : " << parName << " = " << parEntry);
-
-  parameterMap_all.insert(
-      std::map<std::string, std::string>::value_type(parName, parEntry));
-  if (parameterMap_all.find(parName) == parameterMap_all.end())
-    parameterMap_all.insert(
-        std::map<std::string, std::string>::value_type(parName, parEntry));
-  else
-    parameterMap_all[parName] = parEntry;
-
-  return;
-};
-
-void FitParameters::SetParB(std::string parName, bool val) {
-  if (parameterMap_bool.find(parName) != parameterMap_bool.end()) {
-    parameterMap_bool[parName] = val;
-  } else {
-    parameterMap_bool.insert(
-        std::map<std::string, bool>::value_type(parName, val));
-  }
-
-  return;
-}
-
-void FitParameters::SetParD(std::string parName, double val) {
-  // Check if it is saved in int map
-  if (parameterMap_double.find(parName) != parameterMap_double.end()) {
-    parameterMap_double[parName] = val;
-  } else {
-    parameterMap_double.insert(
-        std::map<std::string, double>::value_type(parName, val));
-  }
-  return;
-}
-
-void FitParameters::SetParI(std::string parName, int val) {
-  // Check if it is saved in int map
-  if (parameterMap_int.find(parName) != parameterMap_int.end()) {
-    parameterMap_int[parName] = val;
-  } else {
-    parameterMap_int.insert(
-        std::map<std::string, int>::value_type(parName, val));
-  }
-  return;
-}
-
-// Parameter fetch commands
-int FitParameters::GetParI(std::string parName) {
-  return Config::Get().ConfI(parName);
-};
-
-// Parameter fetch commands
-bool FitParameters::GetParB(std::string parName) {
-  return Config::Get().ConfB(parName);
-};
-
-double FitParameters::GetParD(std::string parName) {
-  return Config::Get().ConfD(parName);
-};
-
-std::string FitParameters::GetParS(std::string parName) {
-  return Config::Get().ConfS(parName);
-};
-
-std::string FitParameters::GetParDIR(std::string parName) {
-  std::string outstr = this->GetParS(parName);
-
-  // Make replacements in the string
-  const int nfiletypes = 2;
-  const std::string filetypes[nfiletypes] = {"@data", "@nuisance"};
-  std::string filerepl[nfiletypes] = {FitPar::GetDataBase(),
-                                      FitPar::GetDataBase() + "/../"};
-
-  for (int i = 0; i < nfiletypes; i++) {
-    std::string findstring = filetypes[i];
-    std::string replstring = filerepl[i];
-    if (outstr.find(findstring) != std::string::npos) {
-      outstr.replace(outstr.find(findstring), findstring.size(), filerepl[i]);
-      break;
-    }
-  }
-
-  return outstr;
-};
-
-std::string FitParameters::GetAllParametersArg() {
-  std::map<std::string, std::string>::iterator mystr = parameterMap_all.begin();
-  std::string longlist = "";
-
-  for (; mystr != parameterMap_all.end(); mystr++) {
-    longlist += "-q " + mystr->first + "=" + mystr->second + " ";
-  }
-
-  return longlist;
-}
-
-void FitParameters::MakeParameterCard(std::string filename) {
-  std::ofstream parcard;
-  parcard.open((filename).c_str(), std::ios::out);
-  std::map<std::string, std::string>::iterator mystr = parameterMap_all.begin();
-
-  for (; mystr != parameterMap_all.end(); mystr++) {
-    std::string name = (mystr->first);
-    parcard << "config " << name << " ";
-
-    if (parameterMap_int.find(name) != parameterMap_int.end())
-      parcard << parameterMap_int.at(name);
-    else if (parameterMap_double.find(name) != parameterMap_double.end())
-      parcard << parameterMap_double.at(name);
-    else if (parameterMap_string.find(name) != parameterMap_string.end())
-      parcard << parameterMap_string.at(name);
-    else if (parameterMap_all.find(name) != parameterMap_all.end())
-      parcard << parameterMap_all.at(name);
-    parcard << "\n";
-  }
-
-  parcard.close();
-
-  return;
-}
-
-void FitParameters::Write() {
-  // Loop through parameters
-  /*  TTree* tr = new TTree("fit_header","fit_header");
-  tr->Branch("par_name",  &parNames);
-  tr->Branch("par_value", &parValues);
-  tr->Branch("card_input", &cardLines);
-  tr->Fill();
-
-  tr->Write();
-  */
-  return;
-}
-
-// Global Access Namespace
-//! Namespace to allow singletons to be accessed easily
-namespace FitPar {
-
-//! Returns FitParameters singleton. Usually used for parameters,
-//! e.g. FitPar::Config().GetParI("input.maxevents")
-FitParameters& Config() { return FitParameters::GetParams(); };
-
-std::string GetDataBase() { return GeneralUtils::GetTopLevelDir() + "/data/"; };
-}
diff --git a/src/Utils/FitParameters.h b/src/Utils/FitParameters.h
deleted file mode 100644
index b7261a5..0000000
--- a/src/Utils/FitParameters.h
+++ /dev/null
@@ -1,128 +0,0 @@
-// Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret
-
-/*******************************************************************************
-*    This file is part of NUISANCE.
-*
-*    NUISANCE is free software: you can redistribute it and/or modify
-*    it under the terms of the GNU General Public License as published by
-*    the Free Software Foundation, either version 3 of the License, or
-*    (at your option) any later version.
-*
-*    NUISANCE is distributed in the hope that it will be useful,
-*    but WITHOUT ANY WARRANTY; without even the implied warranty of
-*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-*    GNU General Public License for more details.
-*
-*    You should have received a copy of the GNU General Public License
-*    along with NUISANCE.  If not, see <http://www.gnu.org/licenses/>.
-*******************************************************************************/
-
-#ifndef FITPARAMETERS_H_SEEN
-#define FITPARAMETERS_H_SEEN
-
-#include <math.h>
-#include <stdlib.h>
-#include <cstring>
-#include <fstream>
-#include <iostream>
-#include <map>
-#include <numeric>
-#include <sstream>
-#include <sstream>
-#include <string>
-#include <vector>
-
-#include "TTree.h"
-#include "TFile.h"
-#include "TGraph.h"
-
-#include "GeneralUtils.h"
-// #include "FitLogger.h"
-#include "NuisConfig.h"
-#include "NuisKey.h"
-//using namespace std;
-
-/*!
- *  \addtogroup FitBase
- *  @{
- */
-
-//! Singleton class to allow easy reading and modification of configuration
-//! parameters
-class FitParameters {
- public:
-  static FitParameters& GetParams(void);
-
-  virtual ~FitParameters();
-
-  FitParameters();
-
-  void SetParamFile(std::string fileName);
-  // Parameter File Parser
-  void ReadParamFile(std::string fileName);
-
-  // Used to override a parameter by the command line
-  void ForceParam(std::string parOption);
-
-  void SetParB(std::string parName, bool val);
-
-  void SetParD(std::string parName, double val);
-
-  void SetParI(std::string parName, int val);
-
-  // Parameter fetch commands
-  int GetParI(std::string parName);
-
-  // Parameter fetch commands
-  bool GetParB(std::string parName);
-
-  double GetParD(std::string parName);
-
-  std::string GetParS(std::string parName);
-
-  std::string GetParDIR(std::string parName);
-  
-  // Variables
-  std::string parFileName;
-  std::map<std::string, std::string> parameterMap_all;
-
-  std::string GetAllParametersArg();
-
-  void MakeParameterCard(std::string filename);
-  
-  void Write();
-
-  TFile* out;  // pointer to output file
-  std::string outputname;
-  std::map<std::string, int> parameterMap_int;
-  std::map<std::string, double> parameterMap_double;
-  std::map<std::string, std::string> parameterMap_string;
-  std::map<std::string, bool> parameterMap_bool;
-
-  std::vector<std::string> parNames;
-  std::vector<std::string> parValues;
-  std::vector<std::string> cardLines;
-  int iteration;
-
- protected:
-  static FitParameters* m_fitparameterInstance;
-};
-
-
-// Global Access Namespace
-//! Namespace to allow singletons to be accessed easily
-namespace FitPar {
-
-//! Returns FitParameters singleton. Usually used for parameters,
-//! e.g. FitPar::Config().GetParI("input.maxevents")
-FitParameters& Config();
-
-//! Return Fitter DataBase
-std::string GetDataBase();
-}
-
-
-/*! @} */
-#endif
-// Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret  
-
diff --git a/src/Utils/FitUtils.h b/src/Utils/FitUtils.h
index bcb5729..fd7024c 100644
--- a/src/Utils/FitUtils.h
+++ b/src/Utils/FitUtils.h
@@ -1,177 +1,177 @@
 // Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret
 
 /*******************************************************************************
 *    This file is part of NUISANCE.
 *
 *    NUISANCE is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    NUISANCE is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with NUISANCE.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
 #ifndef FITUTILS_H_SEEN
 #define FITUTILS_H_SEEN
 
 #include <math.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <ctime>
 #include <iostream>
 #include <numeric>
 
 #include <TChain.h>
 #include <TFile.h>
 #include <TH1D.h>
 #include <TH2D.h>
 #include <THStack.h>
 #include <TKey.h>
 #include <TLegend.h>
 #include <TList.h>
 #include <TLorentzVector.h>
 #include <TObjArray.h>
 #include <TROOT.h>
 #include <TRandom3.h>
 #include <TTree.h>
 #include "FitEvent.h"
 #include "TGraph.h"
 #include "TH2Poly.h"
 #include "FitEvent.h"
 
-#include "FitParameters.h"
+
 #include "FitLogger.h"
 
 /*!
  *  \addtogroup Utils
  *  @{
  */
 
 /// Functions needed by individual samples for calculating kinematic quantities.
 namespace FitUtils {
 
 /// Return a vector of all values saved in map
 double *GetArrayFromMap(std::vector<std::string> invals,
                         std::map<std::string, double> inmap);
 
 /// Returns kinetic energy of particle
 double T(TLorentzVector part);
 
 /// Returns momentum of particle
 double p(TLorentzVector part);
 double p(FitParticle* part);
 
 /// Returns angle between particles (_NOT_ cosine!)
 double th(TLorentzVector part, TLorentzVector part2);
 double th(FitParticle* part1, FitParticle* part2);
 
 /// Hadronic mass reconstruction
 double Wrec(TLorentzVector pnu, TLorentzVector pmu);
 
 /// Hadronic mass true from initial state particles and muon; useful if the full
 /// FSI vectors aren't not saved and we for some reasons need W_true
 double Wtrue(TLorentzVector pnu, TLorentzVector pmu, TLorentzVector pnuc);
 
 double SumKE_PartVect(std::vector<FitParticle *> const fps);
 double SumTE_PartVect(std::vector<FitParticle *> const fps);
 
 /// Return E Hadronic for all FS Particles in Hadronic System
 double GetErecoil_TRUE(FitEvent *event);
 
 /// Return E Hadronic for all Charged FS Particles in Hadronic System
 double GetErecoil_CHARGED(FitEvent *event);
 
 /*
   CCQE MiniBooNE/MINERvA
 */
 /// Function to calculate the reconstructed Q^{2}_{QE}
 double Q2QErec(TLorentzVector pmu, double costh, double binding,
                bool neutrino = true);
 
 /// Function returns the reconstructed E_{nu} values
 double EnuQErec(TLorentzVector pmu, double costh, double binding,
                 bool neutrino = true);
 
 //! Function to calculate the reconstructed Q^{2}_{QE}
 double Q2QErec(double pl, double costh, double binding,
 	       bool neutrino = true);
 
 //! Function returns the reconstructed E_{nu} values
 double EnuQErec(double pl, double costh, double binding,
 		bool neutrino = true);
 
 /*
   CCQE1p MINERvA
 */
 /// Reconstruct Q2QE given just the maximum energy proton.
 double ProtonQ2QErec(double pE, double binding);
 
 /*
   E Recoil MINERvA
 */
 double GetErecoil_MINERvA_LowRecoil(FitEvent *event);
 
 /*
   CC1pi0 MiniBooNE
 */
 /// Reconstruct Enu from CCpi0 vectors and binding energy
 double EnuCC1pi0rec(TLorentzVector pnu, TLorentzVector pmu,
                     TLorentzVector ppi0 = TLorentzVector(0, 0, 0, 0));
 
 /// Reconstruct Q2 from CCpi0 vectors and binding energy
 double Q2CC1pi0rec(TLorentzVector pnu, TLorentzVector pmu,
                    TLorentzVector ppi0 = TLorentzVector(0, 0, 0, 0));
 
 /*
   CC1pi+ MiniBooNE
 */
 
 /// returns reconstructed Enu a la MiniBooNE CCpi+
 /// returns reconstructed Enu a la MiniBooNE CCpi+
 // Also for when not having pion info (so when we have a Michel tag in T2K)
 double EnuCC1piprec(TLorentzVector pnu, TLorentzVector pmu, TLorentzVector ppip,
                     bool pionInfo = true);
 
 /// returns reconstructed Enu assumming resonance interaction where intermediate
 /// resonance was a Delta
 double EnuCC1piprecDelta(TLorentzVector pnu, TLorentzVector pmu);
 
 /// returns reconstructed in a variety of flavours
 double Q2CC1piprec(TLorentzVector pnu, TLorentzVector pmu, TLorentzVector ppip,
                    int enuType = 0, bool pionInfo = true);
 
 /*
   T2K CC1pi+ on CH
 */
 double thq3pi_CC1pip_T2K(TLorentzVector pnu, TLorentzVector pmu,
                          TLorentzVector ppi);
 double q3_CC1pip_T2K(TLorentzVector pnu, TLorentzVector pmu,
                      TLorentzVector ppi);
 double WrecCC1pip_T2K_MB(TLorentzVector pnu, TLorentzVector pmu,
                          TLorentzVector ppip);
 double EnuCC1piprec_T2K_eMB(TLorentzVector pnu, TLorentzVector pmu,
                             TLorentzVector ppi);
 
 /*
   nucleon single pion
 */
 double MpPi(TLorentzVector pp, TLorentzVector ppi);
 
 /// Gets delta p T as defined in Phys.Rev. C94 (2016) no.1, 015503
 double Get_STV_dpt(FitEvent *event, int ISPDG, bool Is0pi);
 /// Gets delta phi T as defined in Phys.Rev. C94 (2016) no.1, 015503
 double Get_STV_dphit(FitEvent *event, int ISPDG, bool Is0pi);
 /// Gets delta alpha T as defined in Phys.Rev. C94 (2016) no.1, 015503
 double Get_STV_dalphat(FitEvent *event, int ISPDG, bool Is0pi);
 
 double CosThAdler(TLorentzVector Pnu, TLorentzVector Pmu, TLorentzVector Ppi, TLorentzVector Pprot);
 double PhiAdler(TLorentzVector Pnu, TLorentzVector Pmu, TLorentzVector Ppi, TLorentzVector Pprot);
 }
 
 /*! @} */
 #endif
diff --git a/src/Utils/NuisConfig.cxx b/src/Utils/NuisConfig.cxx
deleted file mode 100644
index db5aabb..0000000
--- a/src/Utils/NuisConfig.cxx
+++ /dev/null
@@ -1,831 +0,0 @@
-// Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret
-
-/*******************************************************************************
-*    This file is part of NUISANCE.
-*
-*    NUISANCE is free software: you can redistribute it and/or modify
-*    it under the terms of the GNU General Public License as published by
-*    the Free Software Foundation, either version 3 of the License, or
-*    (at your option) any later version.
-*
-*    NUISANCE is distributed in the hope that it will be useful,
-*    but WITHOUT ANY WARRANTY; without even the implied warranty of
-*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-*    GNU General Public License for more details.
-*
-*    You should have received a copy of the GNU General Public License
-*    along with NUISANCE.  If not, see <http://www.gnu.org/licenses/>.
-*******************************************************************************/
-#include "NuisConfig.h"
-#include "FitParameters.h"
-
-struct SXmlAttr_t {
-  SXmlAttr_t* fNext;
-  // after structure itself memory for attribute name is preserved
-  // if first byte is 0, this is special attribute
-  static inline char* Name(void* arg) {
-    return (char*)arg + sizeof(SXmlAttr_t);
-  }
-};
-
-enum EXmlNodeType {
-  kXML_NODE = 1,     // normal node with children
-  kXML_COMMENT = 2,  // comment (stored as value of node fName)
-  kXML_PI_NODE = 3,  // processing instructions node (like <?name  attr="" ?>
-  kXML_RAWLINE = 4,  // just one line of xml code
-  kXML_CONTENT =
-      5  // node content, can appear many times in between of normal nodes
-};
-
-struct SXmlNode_t {
-  EXmlNodeType fType;      //  this is node type - node, comment, processing
-                           //  instruction and so on
-  SXmlAttr_t* fAttr;       // first attribute
-  SXmlAttr_t* fNs;         // name space definition (if any)
-  SXmlNode_t* fNext;       // next node on the same level of hierarchy
-  SXmlNode_t* fChild;      // first child node
-  SXmlNode_t* fLastChild;  // last child node
-  SXmlNode_t* fParent;     // parent node
-  // consequent bytes after structure are node name
-  // if first byte is 0, next is node content
-  static inline char* Name(void* arg) {
-    return (char*)arg + sizeof(SXmlNode_t);
-  }
-};
-
-nuisconfig::nuisconfig() {
-  // Initial Setup
-  std::string filename =
-      GeneralUtils::GetTopLevelDir() + "/parameters/config.xml";
-  std::cout << "[ NUISANCE ]: Loading DEFAULT config from : " << filename;
-
-  // Create XML Engine
-  fXML = new TXMLEngine;
-
-  // Load in documents
-  fXMLDocs.clear();
-  fXML->SetSkipComments(true);
-  fXMLDocs.push_back(fXML->ParseFile(filename.c_str(), 1000000));
-
-  // Setup Main XML Node
-  fMainNode = fXML->DocGetRootElement(fXMLDocs[0]);
-  // RemoveIdenticalNodes();
-
-  std::cout << " -> DONE." << std::endl;
-}
-
-nuisconfig::~nuisconfig() {
-  // Free all xml docs
-  //  for (int i = 0; i < fXMLDocs.size(); i++){
-  //    fXML->FreeDoc( fXMLDocs.at(i) );
-  //  }
-
-  // Remove XMLDocs
-  // fXMLDocs.clear();
-
-  // Delete Engine
-  // delete fXML;
-}
-
-void nuisconfig::OverrideConfig(std::string conf) {
-  std::vector<std::string> opts = GeneralUtils::ParseToStr(conf, "=");
-  SetConfS(opts[0], opts[1]);
-}
-
-XMLNodePointer_t nuisconfig::GetConfigNode(std::string name) {
-  // Loop over children and look for name
-  XMLNodePointer_t child = fXML->GetChild(fMainNode);
-  while (child != 0) {
-    // Select only config parameters
-    if (!std::string(fXML->GetNodeName(child)).compare("config")) {
-      // Loop over config attributes and search for name
-      XMLAttrPointer_t attr = fXML->GetFirstAttr(child);
-      while (attr != 0) {
-        // Save name value
-        if (std::string(fXML->GetAttrName(attr)) == name.c_str()) {
-          return child;
-        }
-
-        // Get Next Attribute
-        attr = fXML->GetNextAttr(attr);
-      }
-    }
-
-    // Next Child
-    child = fXML->GetNext(child);
-  }
-
-  return 0;
-}
-
-/// Request a string config key
-std::string nuisconfig::SetConfS(const std::string name, std::string val) {
-  XMLNodePointer_t node = GetConfigNode(name);
-  if (!node) node = CreateNode("config");
-  SetS(node, name, val);
-  return val;
-}
-
-/// Get nuisconfig::SetConfig Bool
-bool nuisconfig::SetConfB(const std::string name, bool val) {
-  XMLNodePointer_t node = GetConfigNode(name);
-  if (!node) node = CreateNode("config");
-  SetB(node, name, val);
-  return val;
-}
-
-/// Get nuisconfig::SetConfig Int
-int nuisconfig::SetConfI(const std::string name, int val) {
-  XMLNodePointer_t node = GetConfigNode(name);
-  if (!node) node = CreateNode("config");
-  SetI(node, name, val);
-  return val;
-}
-
-/// Get nuisconfig::SetConfig Double
-double nuisconfig::SetConfD(const std::string name, double val) {
-  XMLNodePointer_t node = GetConfigNode(name);
-  if (!node) node = CreateNode("config");
-  SetD(node, name, val);
-  return val;
-}
-
-std::string nuisconfig::ConvertParameterLineToXML(std::string line) {
-  // Parse
-  std::vector<std::string> parsed = GeneralUtils::ParseToStr(line, " ");
-
-  // Min limits
-  if (parsed.size() < 2) {
-    ERR(FTL) << " Insufficient parameter options" << std::endl;
-    throw;
-  }
-
-  // Setup XMLLine
-  std::string xmlline = "parameter";
-
-  // Name
-  xmlline += " name=\"" + parsed[0] + "\"";
-
-  // Nominal
-  xmlline += " nominal=\"" + parsed[1] + "\"";
-
-  // State
-  xmlline += " state=\"" + parsed[2] + "\"";
-
-  return "<" + xmlline + "/>";
-}
-
-std::string nuisconfig::ConvertSampleLineToXML(std::string line) {
-  // Parse
-  std::vector<std::string> parsed = GeneralUtils::ParseToStr(line, " ");
-
-  // Min limits
-  if (parsed.size() < 2) {
-    ERR(FTL) << "Insufficient sample options" << std::endl;
-  }
-
-  // Setup XMLLine
-  std::string xmlline = "sample";
-
-  // Name
-  xmlline += " name=\"" + parsed[1] + "\"";
-
-  // InputFile
-  xmlline += " input=\"" + parsed[2] + "\"";
-
-  // If option add it
-  if (parsed.size() > 3) {
-    xmlline += " state=\"" + parsed[3] + "\"";
-  }
-
-  // If norm add it
-  if (parsed.size() > 4) {
-    xmlline += " norm=\"" + parsed[4] + "\"";
-  }
-
-  return "<" + xmlline + "/>";
-}
-
-void nuisconfig::AddXMLLine(std::string line) {
-  // XMLLine
-  std::string xmlline = "";
-
-  // If = in it its not an xml
-  if (line.find("=") != std::string::npos) {
-    xmlline = "<" + line + "/>";
-
-    // Else Convert it to a line
-  } else {
-    // Parse XMLLine
-    std::vector<std::string> parsed = GeneralUtils::ParseToStr(line, " ");
-    if (parsed.empty()) return;
-
-    // Convert it to new fomat
-    if (!parsed[0].compare("sample")) {
-      xmlline = ConvertSampleLineToXML(line);
-    } else if (!parsed[0].compare("parameter")) {
-      xmlline = ConvertParameterLineToXML(line);
-    }
-  }
-
-  // Ad the line
-  std::cout << "[ NUISANCE ]: Adding XMLLine in nuisconfig: '" << xmlline
-            << "'";
-
-  // Make XML Structure
-  fXMLDocs.push_back(fXML->ParseString(xmlline.c_str()));
-
-  int nxml = fXMLDocs.size();
-  XMLNodePointer_t newdocroot = fXML->DocGetRootElement(fXMLDocs[nxml - 1]);
-  fXML->AddChild(fMainNode, newdocroot);
-
-  std::cout << " -> DONE." << std::endl;
-}
-
-void nuisconfig::FinaliseConfig(std::string name) {
-  std::cout << "[ NUISANCE ]: Finalising configuration";
-  // Save full config to file
-  WriteConfig(name);
-  RemoveEmptyNodes();
-  RemoveIdenticalNodes();
-  std::cout << "-> DONE." << std::endl;
-}
-
-void nuisconfig::LoadXMLConfig(std::string filename, std::string state = "") {
-  std::cout << "[ NUISANCE ]: Loading XML config from : " << filename;
-  // Add new file to xml docs list
-  fXMLDocs.push_back(fXML->ParseFile(filename.c_str(), 1000000));
-
-  // Get New Doc ROOT
-  int nxml = fXMLDocs.size();
-  XMLNodePointer_t newdocroot = fXML->DocGetRootElement(fXMLDocs[nxml - 1]);
-
-  // Loop over children and add
-  XMLNodePointer_t child = fXML->GetChild(newdocroot);
-  while (child != 0) {
-    // Add additional state flag if given
-    if (!state.empty()) {
-      if (GetS(child, "source").empty()) {
-        fXML->NewAttr(child, 0, "source", state.c_str());
-      } else {
-        // fXML->SetAttr
-      }
-
-      // If its a config node, then remove previous attributes, overriding
-      if (!std::string(fXML->GetNodeName(child)).compare("config")) {
-        // Loop over attribues
-        XMLAttrPointer_t attr1 = fXML->GetFirstAttr(child);
-        while (attr1 != 0) {
-          if (!ConfS(fXML->GetAttrName(attr1)).empty()) {
-            std::vector<XMLNodePointer_t> confignodes = GetNodes("config");
-
-            for (size_t i = 0; i < confignodes.size(); i++) {
-              if (fXML->HasAttr(confignodes[i], fXML->GetAttrName(attr1))) {
-                std::cout << fXML->GetAttrName(attr1) << std::endl;
-                fXML->FreeAttr(confignodes[i], fXML->GetAttrName(attr1));
-                break;
-              }
-            }
-          }
-          attr1 = fXML->GetNextAttr(attr1);
-        }
-      }
-    }
-
-    // Add this child to the main config list
-    fXML->AddChild(fMainNode, child);
-
-    // Get Next Child
-    child = fXML->GetNext(child);
-  }
-  // std::cout << "Removing Identical Nodes" << std::endl;
-  std::cout << " -> DONE." << std::endl;
-}
-
-void nuisconfig::LoadConfig(std::string filename, std::string state) {
-  // Open file and see if its XML
-  std::cout << "[ NUISANCE ]: Trying to parse file : " << filename;
-  StopTalking();
-  XMLDocPointer_t tempdoc = fXML->ParseFile(filename.c_str(), 1000000);
-  StartTalking();
-
-  if (tempdoc) {
-    std::cout << " -> Found XML file." << std::endl;
-    LoadXMLConfig(filename, state);
-  } else {
-    std::cout << " -> Assuming its a simple card file." << std::endl;
-    LoadCardConfig(filename, state);
-  }
-}
-
-void nuisconfig::LoadCardConfig(std::string filename, std::string state) {
-  // Build XML Config from the card file
-  std::vector<std::string> cardlines =
-      GeneralUtils::ParseFileToStr(filename, "\n");
-  int linecount = 0;
-
-  for (std::vector<std::string>::iterator iter = cardlines.begin();
-       iter != cardlines.end(); iter++) {
-    std::string line = (*iter);
-    linecount++;
-
-    // Skip Comments
-    if (line.empty()) continue;
-    if (line.c_str()[0] == '#') continue;
-
-    // Parse whitespace
-    std::vector<std::string> strvct = GeneralUtils::ParseToStr(line, " ");
-    if (strvct.empty()) continue;
-
-    // Get Identifier
-    std::string id = strvct[0];
-
-    // Build backwards compatible xml configs
-    if (!id.compare("sample")) Config::CreateSampleKeyFromLine(line);
-
-    if (id.find("_parameter") != std::string::npos)
-      Config::CreateParameterKeyFromLine(line);
-
-    if (!id.compare("covar") || !id.compare("pull") || !id.compare("throw"))
-      Config::CreatePullKeyFromLine(line);
-
-    if (!id.compare("config")) Config::CreateOldConfigKeyFromLine(line);
-  }
-
-  return;
-}
-
-XMLNodePointer_t nuisconfig::CreateNode(std::string name) {
-  return fXML->NewChild(fMainNode, 0, name.c_str());
-}
-
-void nuisconfig::WriteConfig(std::string outputname) {
-  // Create a New XML Doc
-  XMLDocPointer_t newxmldoc = fXML->NewDoc();
-  fXML->DocSetRootElement(newxmldoc, fMainNode);
-
-  // Save document to file
-  //  fXML->SaveDoc(newxmldoc, outputname.c_str());
-}
-
-void nuisconfig::CheckCallCount(std::string name) {
-  // Add Count Warning Flag so we only warn once...
-  if (fConfigCallWarning.find(name) == fConfigCallWarning.end()) {
-    fConfigCallWarning[name] = false;
-    fConfigCallCount[name] = 0;
-  }
-
-  // Check for inefficiency and warn if it happens
-  if (abs(time(NULL) - fCurrentTime) > 1) {
-    fCurrentTime = time(NULL);
-
-    // Check count since last 10 seconds
-    if (!fConfigCallWarning[name] and fConfigCallCount[name] > 100) {
-      ERR(WRN) << "Config Parameter " << name << " has been requested "
-               << fConfigCallCount[name] << " times in the last second."
-               << std::endl;
-      ERR(WRN) << "This is very inefficient! Please try to change this."
-               << std::endl;
-      fConfigCallWarning[name] = true;
-    }
-
-    // Reset counter
-    fConfigCallCount[name] = 0;
-  }
-
-  // Add to Call Count
-  fConfigCallCount[name] += 1;
-}
-
-std::string nuisconfig::ConfS(const std::string name) {
-  std::string temp = "";
-
-  CheckCallCount(name);
-
-  // Loop over children and look for name
-  XMLNodePointer_t child = fXML->GetChild(fMainNode);
-  while (child != 0) {
-    // std::cout << "Child = " << fXML->GetNodeName(child) << std::endl;
-    // Select only config parameters
-    if (!std::string(fXML->GetNodeName(child)).compare("config")) {
-      // std::cout << "Found Config " << std::endl;
-      // Loop over config attributes and search for name
-      XMLAttrPointer_t attr = fXML->GetFirstAttr(child);
-      while (attr != 0) {
-        // Save name value
-        // std::cout << "Setting Temp " << std::string(fXML->GetAttrName(attr))
-        // << " '" << fXML->GetAttrValue(attr) << "' " << std::endl;
-        if (std::string(fXML->GetAttrName(attr)) == name.c_str()) {
-          // std::cout << "Setting Temp " <<
-          // std::string(fXML->GetAttrName(attr)) << " " <<
-          // fXML->GetAttrValue(attr) << std::endl;
-          temp = fXML->GetAttrValue(attr);
-        }
-
-        // Get Next Attribute
-        attr = fXML->GetNextAttr(attr);
-      }
-    }
-
-    // Next Child
-    child = fXML->GetNext(child);
-  }
-
-  // Return Config Value
-  return temp;
-}
-
-bool nuisconfig::ConfB(const std::string name) {
-  std::string pars = ConfS(name);
-  return GeneralUtils::StrToBool(pars);
-}
-
-int nuisconfig::ConfI(const std::string name) {
-  std::string pars = ConfS(name);
-  return GeneralUtils::StrToInt(pars);
-}
-
-double nuisconfig::ConfD(const std::string name) {
-  std::string pars = ConfS(name);
-  return GeneralUtils::StrToDbl(pars);
-}
-
-std::vector<XMLNodePointer_t> nuisconfig::GetChildNodes(
-    XMLNodePointer_t node, const std::string type) {
-  std::vector<XMLNodePointer_t> nodelist;
-
-  /// Loop over all children
-  XMLNodePointer_t child = fXML->GetChild(node);
-  while (child != 0) {
-    /// Get nodes for given type (if type empty return all)
-    if (std::string(fXML->GetNodeName(child)) == type.c_str() or type.empty()) {
-      nodelist.push_back(child);
-    }
-
-    // Next child
-    child = fXML->GetNext(child);
-  }
-
-  // return list
-  return nodelist;
-}
-
-std::vector<XMLNodePointer_t> nuisconfig::GetNodes(const std::string type) {
-  return GetChildNodes(fMainNode, type);
-}
-
-/// Get String from a given node
-std::string nuisconfig::GetS(XMLNodePointer_t node, std::string name) {
-  // If node empty return empty
-  if (node == 0) return "";
-
-  // Check request count
-  CheckCallCount(name);
-
-  // Get Attribute from child with name
-  XMLAttrPointer_t attr = fXML->GetFirstAttr(node);
-  std::string temp = "";
-
-  // Check if its a search or exact (should probs just add wildcards...)
-  bool exact = true;
-  if (name.size() > 0) {
-    if (name[0] == '*' and name[name.size() - 1] == '*') {
-      exact = false;
-    }
-  }
-
-  if (!fXML) {
-    std::cout << "AAAAH NO XML" << std::endl;
-    throw;
-  }
-
-  // Loop over all attributes
-  while (attr != 0) {
-    // Find value of correct name
-    if (exact) {
-      // std::cout << "Getting Attr name = " << attr << " " << name <<
-      // std::endl;
-      if (std::string(fXML->GetAttrName(attr)) == name.c_str()) {
-        temp = fXML->GetAttrValue(attr);
-      }
-    } else {
-    }
-
-    // Next Attribute
-    attr = fXML->GetNextAttr(attr);
-  }
-
-  return temp;
-}
-
-bool nuisconfig::Has(XMLNodePointer_t node, std::string name) {
-  // If node empty return empty
-  if (node == 0) return false;
-
-  // Get Attribute from child with name
-  SXmlNode_t* snode = (SXmlNode_t*)node;
-  // SXmlAttr_t* sattr = snode->fAttr;
-
-  XMLAttrPointer_t attr = fXML->GetFirstAttr(node);
-
-  bool found = false;
-
-  // Check if its a search or exact (should probs just add wildcards...)
-  bool exact = true;
-  if (name.size() > 0) {
-    if (name[0] == '*' and name[name.size() - 1] == '*') {
-      exact = false;
-    }
-  }
-
-  // Loop over all attributes
-  while (attr != 0) {
-    // Find value of correct name
-    if (exact) {
-      if (std::string(fXML->GetAttrName(attr)) == name.c_str()) {
-        found = true;
-      }
-    } else {
-    }
-
-    // Next Attribute
-    attr = fXML->GetNextAttr(attr);
-  }
-
-  return found;
-}
-
-/// Get Bools from a given node
-bool nuisconfig::GetB(XMLNodePointer_t node, std::string name) {
-  std::string tempattr = GetS(node, name);
-  return GeneralUtils::StrToBool(tempattr);
-}
-
-/// Get int from given node
-int nuisconfig::GetI(XMLNodePointer_t node, std::string name) {
-  std::string tempattr = GetS(node, name);
-  return GeneralUtils::StrToInt(tempattr);
-}
-
-/// Get double from given node
-double nuisconfig::GetD(XMLNodePointer_t node, std::string name) {
-  std::string tempattr = GetS(node, name);
-  return GeneralUtils::StrToDbl(tempattr);
-}
-
-std::vector<std::string> nuisconfig::GetVS(XMLNodePointer_t node,
-                                           std::string name, const char* del) {
-  std::string tempattr = GetS(node, name);
-  return GeneralUtils::ParseToStr(tempattr, del);
-}
-
-std::vector<int> nuisconfig::GetVI(XMLNodePointer_t node, std::string name,
-                                   const char* del) {
-  std::string tempattr = GetS(node, name);
-  return GeneralUtils::ParseToInt(tempattr, del);
-}
-
-std::vector<double> nuisconfig::GetVD(XMLNodePointer_t node, std::string name,
-                                      const char* del) {
-  std::string tempattr = GetS(node, name);
-  return GeneralUtils::ParseToDbl(tempattr, del);
-}
-
-namespace Config {
-nuisconfig& Get() { return nuisconfig::GetConfig(); };
-}
-
-nuisconfig* nuisconfig::m_nuisconfigInstance = NULL;
-nuisconfig& nuisconfig::GetConfig(void) {
-  if (!m_nuisconfigInstance) m_nuisconfigInstance = new nuisconfig;
-  return *m_nuisconfigInstance;
-};
-
-void nuisconfig::AddS(XMLNodePointer_t node, std::string name,
-                      std::string val) {
-  fXML->NewAttr(node, 0, name.c_str(), val.c_str());
-}
-
-void nuisconfig::AddB(XMLNodePointer_t node, std::string name, bool val) {
-  AddS(node, name, GeneralUtils::BoolToStr(val));
-}
-
-void nuisconfig::AddI(XMLNodePointer_t node, std::string name, int val) {
-  AddS(node, name, GeneralUtils::IntToStr(val));
-}
-void nuisconfig::AddD(XMLNodePointer_t node, std::string name, double val) {
-  AddS(node, name, GeneralUtils::DblToStr(val));
-}
-
-void nuisconfig::SetS(XMLNodePointer_t node, std::string name,
-                      std::string val) {
-  // Remove and readd attribute
-  if (fXML->HasAttr(node, name.c_str())) {
-    fXML->FreeAttr(node, name.c_str());
-  }
-
-  AddS(node, name, val);
-}
-
-void nuisconfig::SetB(XMLNodePointer_t node, std::string name, bool val) {
-  SetS(node, name, GeneralUtils::BoolToStr(val));
-}
-
-void nuisconfig::SetI(XMLNodePointer_t node, std::string name, int val) {
-  SetS(node, name, GeneralUtils::IntToStr(val));
-}
-void nuisconfig::SetD(XMLNodePointer_t node, std::string name, double val) {
-  SetS(node, name, GeneralUtils::DblToStr(val));
-}
-
-void nuisconfig::ChangeS(XMLNodePointer_t node, std::string name,
-                         std::string val) {
-  if (!fXML->HasAttr(node, name.c_str())) return;
-  SetS(node, name, val);
-}
-
-void nuisconfig::ChangeB(XMLNodePointer_t node, std::string name, bool val) {
-  ChangeS(node, name, GeneralUtils::BoolToStr(val));
-}
-
-void nuisconfig::ChangeI(XMLNodePointer_t node, std::string name, int val) {
-  ChangeS(node, name, GeneralUtils::IntToStr(val));
-}
-void nuisconfig::ChangeD(XMLNodePointer_t node, std::string name, double val) {
-  ChangeS(node, name, GeneralUtils::DblToStr(val));
-}
-
-void nuisconfig::RemoveEmptyNodes() {
-  std::vector<XMLNodePointer_t> nodelist = Config::Get().GetNodes();
-  for (size_t i = 0; i < nodelist.size(); i++) {
-    if (fXML->IsEmptyNode(nodelist[i])) {
-      RemoveNode(nodelist[i]);
-    }
-  }
-}
-
-void nuisconfig::RemoveIdenticalNodes() {
-  std::vector<XMLNodePointer_t> removed;
-
-  // Loop over all nodes and check for identical nodes
-  std::vector<XMLNodePointer_t> nodelist = Config::Get().GetNodes();
-  for (size_t i = 0; i < nodelist.size(); i++) {
-    for (size_t j = 0; j < nodelist.size(); j++) {
-      XMLNodePointer_t node1 = nodelist[i];
-      XMLNodePointer_t node2 = nodelist[j];
-
-      // Check node already removed.
-      if (std::find(removed.begin(), removed.end(), node1) != removed.end())
-        continue;
-      if (std::find(removed.begin(), removed.end(), node2) != removed.end())
-        continue;
-      if (i == j) continue;
-
-      // Check matching
-      if (!MatchingNodes(node1, node2)) continue;
-
-      if (std::string(fXML->GetNodeName(node1)).compare("config") and
-          fXML->IsEmptyNode(node1)) {
-        // Matching so print out warning
-        std::cout << "Matching nodes given! Removing node1!" << std::endl
-                  << "Node 1" << std::endl;
-        PrintNode(node1);
-
-        std::cout << "Node 2" << std::endl;
-        PrintNode(node2);
-      }
-
-      // Remove node
-      removed.push_back(node1);
-    }
-  }
-
-  // Now go through and remove this node.
-  for (size_t i = 0; i < removed.size(); i++) {
-    RemoveNode(removed.at(i));
-  }
-
-  return;
-}
-
-void nuisconfig::RemoveNode(XMLNodePointer_t node) {
-  fXML->FreeAllAttr(node);
-  fXML->CleanNode(node);
-  fXML->FreeNode(node);
-  fXML->UnlinkNode(node);
-}
-
-void nuisconfig::PrintNode(XMLNodePointer_t node) {
-  // Print Node Name
-  std::cout << fXML->GetNodeName(node) << std::endl;
-
-  // Loop and print all attributes
-  XMLAttrPointer_t attr = fXML->GetFirstAttr(node);
-  while (attr != 0) {
-    std::cout << " -> " << fXML->GetAttrName(attr) << " : "
-              << fXML->GetAttrValue(attr) << std::endl;
-    attr = fXML->GetNextAttr(attr);
-  }
-}
-
-bool nuisconfig::MatchingNodes(XMLNodePointer_t node1, XMLNodePointer_t node2) {
-  bool matching = true;
-  XMLAttrPointer_t attr = fXML->GetFirstAttr(node1);
-  while (attr != 0) {
-    if (GetS(node2, fXML->GetAttrName(attr)) != fXML->GetAttrValue(attr))
-      matching = false;
-    attr = fXML->GetNextAttr(attr);
-  }
-  return matching;
-}
-
-std::string nuisconfig::GetTag(std::string name) {
-  std::vector<XMLAttrPointer_t> alltags = GetNodes("tag");
-  std::string tagval = "";
-  bool tagfound = false;
-
-  for (size_t i = 0; i < alltags.size(); i++) {
-    if (!Has(alltags[i], name)) continue;
-    tagval = GetS(alltags[i], name);
-    tagfound = true;
-  }
-
-  if (!tagfound) {
-    ERR(FTL) << "Cannot find tag " << name << " in global conig!" << std::endl;
-    throw;
-  }
-
-  return tagval;
-};
-
-void nuisconfig::ExpandAllTags() {
-  return;
-  /*
-  // Loop over children and look for name
-  XMLNodePointer_t child = fXML->GetChild(fMainNode);
-  while (child != 0) {
-
-    // Loop over attributes and search for tags
-    XMLAttrPointer_t attr = fXML->GetFirstAttr(child);
-    while ( attr != 0 ) {
-
-      // Search attribute value for <>
-      std::string attrval = std::string(fXML->GetAttrValue(attr));
-      std::string attrname = std::string(fXML->GetAttrName(attr));
-
-      // Search for <>
-      while (attrval.find("<") != std::string::npos and
-             attrval.find(">") != std::string::npos){
-
-        size_t startdel = 0;
-        size_t enddel = 0;
-        std::string replacestring = "";
-
-        for (size_t i = 0; i < attrval.size(); i++){
-
-          if (attrval[i] == '<'){
-            replacestring = "";
-            startdel = i;
-          }
-
-          replacestring.push_back(attrval[i]);
-
-          if (attrval[i] == '>'){
-            enddel = i;
-            break;
-          }
-        }
-
-        attrval.replace(startdel, replacestring, GetTag(replacestring) );
-      }
-
-      fXML->FreeAttr(child, attr);
-      attr = fXML->NewAttr(child, attr, attrname.c_str(), attrval.c_str());
-
-      // Get Next Attribute
-      attr = fXML->GetNextAttr(attr);
-    }
-    child = fXML->GetNext(child);
-  }
-  */
-};
-
-std::vector<std::string> nuisconfig::GetAllKeysForNode(XMLNodePointer_t node) {
-  bool matching = true;
-  XMLAttrPointer_t attr = fXML->GetFirstAttr(node);
-  std::vector<std::string> keys;
-  while (attr != 0) {
-    if (!std::string(fXML->GetAttrName(attr)).empty()) {
-      keys.push_back(std::string(fXML->GetAttrName(attr)));
-      //      std::cout << "Pushing Back : " <<
-      //      std::string(fXML->GetAttrName(attr)) << std::endl;
-    }
-    attr = fXML->GetNextAttr(attr);
-  }
-
-  //  for (int i = 0; i < keys.size(); i++){
-  //    std::cout << "Got Key: " << keys[i] << std::endl;
-  //  }
-
-  return keys;
-}
diff --git a/src/Utils/NuisConfig.h b/src/Utils/NuisConfig.h
deleted file mode 100644
index bbeea91..0000000
--- a/src/Utils/NuisConfig.h
+++ /dev/null
@@ -1,184 +0,0 @@
-// Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret
-
-/*******************************************************************************
-*    This file is part of NUISANCE.
-*
-*    NUISANCE is free software: you can redistribute it and/or modify
-*    it under the terms of the GNU General Public License as published by
-*    the Free Software Foundation, either version 3 of the License, or
-*    (at your option) any later version.
-*
-*    NUISANCE is distributed in the hope that it will be useful,
-*    but WITHOUT ANY WARRANTY; without even the implied warranty of
-*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-*    GNU General Public License for more details.
-*
-*    You should have received a copy of the GNU General Public License
-*    along with NUISANCE.  If not, see <http://www.gnu.org/licenses/>.
-*******************************************************************************/
-
-#ifndef NUISCONFIG_H_SEEN
-#define NUISCONFIG_H_SEEN
-
-#include <algorithm>
-#include <map>
-
-#include "TXMLEngine.h"
-
-#include "GeneralUtils.h"
-
-// New NUISANCE Config Class
-class nuisconfig {
- public:
-  /// Singleton Get Function
-  static nuisconfig& GetConfig(void);
-
-  /// Constructor \n
-  /// Loads defaults from $NUISANCE/parameters/config.xml
-  nuisconfig();
-
-  /// Desctructor \n Frees XML Docs
-  virtual ~nuisconfig();
-
-  /// Adds a new configuration list
-  void LoadConfig(std::string filename, std::string state);
-
-  /// Adds a new config from new xml file format
-  void LoadXMLConfig(std::string filename, std::string state);
-
-  /// Adds a new config from old card file format
-  void LoadCardConfig(std::string filename, std::string state);
-
-  /// Save the config to file
-  void WriteConfig(std::string filename);
-
-  void OverrideConfig(std::string conf);
-
-  XMLNodePointer_t GetConfigNode(std::string name);
-
-  /// Request a string config key
-  std::string SetConfS(const std::string name, std::string val);
-
-  /// Get SetConfig Bool
-  bool SetConfB(const std::string name, bool val);
-
-  /// Get SetConfig Int
-  int SetConfI(const std::string name, int val);
-
-  /// Get SetConfig Double
-  double SetConfD(const std::string name, double val);
-
-  // Set config
-  std::string ConfS(const std::string name);
-
-  /// Get Config Bool
-  bool ConfB(const std::string name);
-
-  /// Get Config Int
-  int ConfI(const std::string name);
-
-  /// Get Config Double
-  double ConfD(const std::string name);
-
-  /// Node Functions
-  void CheckCallCount(std::string name);
-
-  /// Get list of child nodes of given element
-  std::vector<XMLNodePointer_t> GetChildNodes(XMLNodePointer_t node,
-                                              const std::string type);
-
-  // Get List of child nodes of nuisance element
-  std::vector<XMLNodePointer_t> GetNodes(std::string type = "");
-
-  /// Get String from a given node
-  std::string GetS(XMLNodePointer_t node, std::string name);
-
-  /// Get Bools from a given node
-  bool GetB(XMLNodePointer_t node, std::string name);
-
-  /// Get int from given node
-  int GetI(XMLNodePointer_t node, std::string name);
-
-  /// Get double from given node
-  double GetD(XMLNodePointer_t node, std::string name);
-
-  // Add Children to root node
-  XMLNodePointer_t CreateNode(std::string name);
-
-  // Add line
-  void AddXMLLine(std::string line);
-
-  std::string ConvertSampleLineToXML(std::string line);
-  std::string ConvertParameterLineToXML(std::string line);
-  void FinaliseConfig(std::string name);
-
-  // Add attribute to node
-  void AddS(XMLNodePointer_t node, std::string name, std::string val);
-  void AddB(XMLNodePointer_t node, std::string name, bool val);
-  void AddI(XMLNodePointer_t node, std::string name, int val);
-  void AddD(XMLNodePointer_t node, std::string name, double val);
-
-  void SetS(XMLNodePointer_t node, std::string name, std::string val);
-  void SetB(XMLNodePointer_t node, std::string name, bool val);
-  void SetI(XMLNodePointer_t node, std::string name, int val);
-  void SetD(XMLNodePointer_t node, std::string name, double val);
-
-  void ChangeS(XMLNodePointer_t node, std::string name, std::string val);
-  void ChangeB(XMLNodePointer_t node, std::string name, bool val);
-  void ChangeI(XMLNodePointer_t node, std::string name, int val);
-  void ChangeD(XMLNodePointer_t node, std::string name, double val);
-
-  // Check has element
-  bool Has(XMLNodePointer_t node, std::string name);
-
-  // Reconfigure (sorts overrides, logger, etc)
-  void Reconfigure(){};
-
-  /// OLD Wrapper Functions for GetParI,etc
-  inline std::string GetParS(std::string name) { return ConfS(name); };
-  inline int GetParI(std::string name) { return ConfI(name); };
-  inline double GetParD(std::string name) { return ConfD(name); };
-  inline bool GetParB(std::string name) { return ConfB(name); };
-
-  // Get Vectors
-  std::vector<std::string> GetVS(XMLNodePointer_t node, std::string name,
-                                 const char* del);
-  std::vector<int> GetVI(XMLNodePointer_t node, std::string name,
-                         const char* del);
-  std::vector<double> GetVD(XMLNodePointer_t node, std::string name,
-                            const char* del);
-
-  void RemoveEmptyNodes();
-  void RemoveIdenticalNodes();
-
-  std::vector<std::string> GetAllKeysForNode(XMLNodePointer_t node);
-
-  bool MatchingNodes(XMLNodePointer_t node1, XMLNodePointer_t node2);
-  void PrintNode(XMLNodePointer_t node);
-  void RemoveNode(XMLNodePointer_t node);
-
-  std::string GetTag(std::string name);
-
-  std::string GetElementName(XMLNodePointer_t node){ return fXML->GetNodeName(node); }
-  void ExpandAllTags();
-
- private:
-  XMLNodePointer_t fMainNode;             ///< Main XML Parent Node
-  TXMLEngine* fXML;                       ///< ROOT XML Engine
-  std::vector<XMLDocPointer_t> fXMLDocs;  ///< List of all XML document inputs
-
-  int fCurrentTime;  ///< Unix time for inefficiency checking
-  std::map<std::string, int> fConfigCallCount;  ///< To check for inefficiency.
-  std::map<std::string, bool> fConfigCallWarning;  ///< Only print warning once.
-
- protected:
-  static nuisconfig* m_nuisconfigInstance;
-};
-
-// Get Function for Singleton
-namespace Config {
-nuisconfig& Get();
-}
-
-/*! @} */
-#endif
diff --git a/src/Utils/NuisKey.cxx b/src/Utils/NuisKey.cxx
deleted file mode 100644
index c4d857e..0000000
--- a/src/Utils/NuisKey.cxx
+++ /dev/null
@@ -1,201 +0,0 @@
-#include "NuisKey.h"
-
-std::string nuiskey::GetS(std::string name) {
-  return Config::Get().GetS(fNode, name);
-};
-
-int nuiskey::GetI(std::string name) { return Config::Get().GetI(fNode, name); };
-
-double nuiskey::GetD(std::string name) {
-  return Config::Get().GetD(fNode, name);
-};
-
-bool nuiskey::GetB(std::string name) {
-  return Config::Get().GetB(fNode, name);
-};
-
-std::vector<std::string> nuiskey::GetVS(std::string name, const char* del) {
-  return Config::Get().GetVS(fNode, name, del);
-};
-
-std::vector<int> nuiskey::GetVI(std::string name, const char* del) {
-  return Config::Get().GetVI(fNode, name, del);
-};
-
-std::vector<double> nuiskey::GetVD(std::string name, const char* del) {
-  return Config::Get().GetVD(fNode, name, del);
-};
-
-std::vector<nuiskey> Config::QueryKeys(const std::string type,
-                                       const std::string test1) {
-  // Get Vector of nodes
-  std::vector<XMLNodePointer_t> nodelist = Config::Get().GetNodes(type);
-
-  // Convert List into a key list for easier access
-  std::vector<nuiskey> keylist;
-  for (std::vector<XMLNodePointer_t>::const_iterator iter = nodelist.begin();
-       iter != nodelist.end(); iter++) {
-    // Create new key
-    nuiskey newkey = nuiskey(*iter);
-
-    // Add test1
-    if (!test1.empty()) {
-      std::vector<std::string> testvect = GeneralUtils::ParseToStr(test1, "=");
-      if (testvect.size() < 2) continue;
-      if (newkey.GetS(testvect[0]) != testvect[1]) continue;
-    }
-
-    // Save node as nuiskey
-    keylist.push_back(newkey);
-  }
-
-  // Return list of keys
-  return keylist;
-}
-
-nuiskey Config::QueryLastKey(const std::string type, const std::string test1) {
-  // Loop over all for now because I'm lazy...
-  std::vector<nuiskey> allkeys = Config::QueryKeys(type, test1);
-  if (allkeys.size() < 1)
-    return nuiskey();
-  else
-    return allkeys[allkeys.size() - 1];
-}
-
-nuiskey Config::QueryFirstKey(const std::string type, const std::string test1) {
-  // Loop over all for now because I'm lazy...
-  std::vector<nuiskey> allkeys = Config::QueryKeys(type, test1);
-  if (allkeys.size() < 1)
-    return nuiskey();
-  else
-    return allkeys[allkeys.size() - 1];
-}
-
-nuiskey Config::CreateParameterKeyFromLine(const std::string line) {
-  nuiskey parameterkey = Config::CreateKey("parameter");
-
-  // Parse
-  std::vector<std::string> strvct = GeneralUtils::ParseToStr(line, " ");
-
-  // Add to key
-  parameterkey.AddS("type", strvct[0]);
-  parameterkey.AddS("name", strvct[1]);
-  parameterkey.AddS("nominal", strvct[2]);
-
-  if (strvct.size() == 7) {
-    parameterkey.AddS("low", strvct[3]);
-    parameterkey.AddS("high", strvct[4]);
-    parameterkey.AddS("step", strvct[5]);
-    parameterkey.AddS("state", strvct[6]);
-  } else if (strvct.size() == 3) {
-    parameterkey.AddS("state", "FIX");
-  } else if (strvct.size() == 4) {
-    parameterkey.AddS("state", strvct[3]);
-  }
-
-  return parameterkey;
-}
-
-bool nuiskey::Has(const std::string name) {
-  return Config::Get().Has(fNode, name);
-}
-
-std::string nuiskey::GetElementName() { return Config::Get().GetElementName(fNode); }
-
-nuiskey Config::CreatePullKeyFromLine(const std::string line) {
-  nuiskey pullkey = Config::CreateKey("covar");
-
-  // Parse
-  std::vector<std::string> strvct = GeneralUtils::ParseToStr(line, " ");
-  pullkey.AddS("name", strvct[1]);
-  pullkey.AddS("input", strvct[2]);
-  pullkey.AddS("type", strvct[3]);
-
-  return pullkey;
-}
-
-nuiskey Config::CreateOldConfigKeyFromLine(const std::string line) {
-  nuiskey configkey = Config::CreateKey("config");
-
-  std::vector<std::string> strvct = GeneralUtils::ParseToStr(line, " ");
-  configkey.AddS(strvct[1], strvct[2]);
-
-  return configkey;
-}
-
-nuiskey Config::CreateSampleKeyFromLine(const std::string line) {
-  // Create new key
-  nuiskey samplekey = Config::CreateKey("sample");
-
-  // Parse
-  std::vector<std::string> strvct = GeneralUtils::ParseToStr(line, " ");
-
-  // Get elements
-  samplekey.AddS("name", strvct[1]);
-  samplekey.AddS("input", strvct[2]);
-  if (strvct.size() > 3) {
-    samplekey.AddS("type", strvct[3]);
-  }
-  if (strvct.size() > 4) {
-    samplekey.AddS("norm", strvct[4]);
-  }
-
-  return samplekey;
-}
-
-nuiskey Config::CreateKey(const std::string name) {
-  return nuiskey(Config::Get().CreateNode(name));
-}
-
-void nuiskey::AddS(std::string name, std::string newval) {
-  Config::Get().AddS(fNode, name, newval);
-}
-void nuiskey::AddI(std::string name, int newval) {
-  Config::Get().AddI(fNode, name, newval);
-}
-void nuiskey::AddD(std::string name, double newval) {
-  Config::Get().AddD(fNode, name, newval);
-}
-void nuiskey::AddB(std::string name, bool newval) {
-  Config::Get().AddB(fNode, name, newval);
-}
-
-void nuiskey::SetS(std::string name, std::string newval) {
-  Config::Get().SetS(fNode, name, newval);
-}
-void nuiskey::SetI(std::string name, int newval) {
-  Config::Get().SetI(fNode, name, newval);
-}
-void nuiskey::SetD(std::string name, double newval) {
-  Config::Get().SetD(fNode, name, newval);
-}
-void nuiskey::SetB(std::string name, bool newval) {
-  Config::Get().SetB(fNode, name, newval);
-}
-
-void nuiskey::ChangeS(std::string name, std::string newval) {
-  Config::Get().ChangeS(fNode, name, newval);
-}
-void nuiskey::ChangeI(std::string name, int newval) {
-  Config::Get().ChangeI(fNode, name, newval);
-}
-void nuiskey::ChangeD(std::string name, double newval) {
-  Config::Get().ChangeD(fNode, name, newval);
-}
-void nuiskey::ChangeB(std::string name, bool newval) {
-  Config::Get().ChangeB(fNode, name, newval);
-}
-
-std::vector<std::string> nuiskey::GetAllKeys() {
-  return Config::Get().GetAllKeysForNode(fNode);
-}
-
-std::vector<nuiskey> nuiskey::GetListOfChildNodes(std::string const& filter) {
-  std::vector<XMLNodePointer_t> nodelist =
-      Config::Get().GetChildNodes(fNode, filter);
-  std::vector<nuiskey> keylist;
-  for (size_t n_it = 0; n_it < nodelist.size(); ++n_it) {
-    keylist.push_back(nuiskey(nodelist[n_it]));
-  }
-  return keylist;
-}
diff --git a/src/Utils/NuisKey.h b/src/Utils/NuisKey.h
deleted file mode 100644
index 606d3be..0000000
--- a/src/Utils/NuisKey.h
+++ /dev/null
@@ -1,70 +0,0 @@
-#ifndef NUISKEY_H
-#define NUISKEY_H
-
-#include <vector>
-
-#include "NuisConfig.h"
-
-class nuiskey {
- public:
-  nuiskey(){};
-
-  nuiskey(XMLNodePointer_t node) { fNode = node; };
-
-  ~nuiskey(){};
-
-  std::string GetS(std::string name);
-  int GetI(std::string name);
-  double GetD(std::string name);
-  bool GetB(std::string name);
-
-  std::vector<std::string> GetVS(std::string name, const char* del);
-  std::vector<int> GetVI(std::string name, const char* del);
-  std::vector<double> GetVD(std::string name, const char* del);
-
-  void SetS(std::string name, std::string newval);
-  void SetI(std::string name, int newval);
-  void SetD(std::string name, double newval);
-  void SetB(std::string name, bool newval);
-
-  void ChangeS(std::string name, std::string newval);
-  void ChangeI(std::string name, int newval);
-  void ChangeD(std::string name, double newval);
-  void ChangeB(std::string name, bool newval);
-
-  void AddS(std::string name, std::string newval);
-  void AddI(std::string name, int newval);
-  void AddD(std::string name, double newval);
-  void AddB(std::string name, bool newval);
-
-  bool Has(std::string name);
-
-  std::string GetElementName();
-
-  std::vector<std::string> GetAllKeys();
-
-  std::vector<nuiskey> GetListOfChildNodes(std::string const& filter = "");
-
-  XMLNodePointer_t fNode;  ///< XML Node in Config::Get().fXML for this key
-};
-
-namespace Config {
-
-// Return a vector of keys for use
-std::vector<nuiskey> QueryKeys(const std::string name,
-                               const std::string test1 = "");
-nuiskey QueryFirstKey(const std::string name, const std::string test1 = "");
-nuiskey QueryLastKey(const std::string name, const std::string test1 = "");
-
-// Create a new global config entry
-nuiskey CreateKey(const std::string name);
-
-// void ConvertAndLoadCardToXMLFormat(const std::string cardfile);
-
-// Backwards compatible sample key options
-nuiskey CreateSampleKeyFromLine(const std::string line);
-nuiskey CreateParameterKeyFromLine(const std::string line);
-nuiskey CreatePullKeyFromLine(const std::string line);
-nuiskey CreateOldConfigKeyFromLine(const std::string line);
-}
-#endif
diff --git a/src/Utils/ParserUtils.h b/src/Utils/ParserUtils.h
index 475c7fb..e8151bd 100644
--- a/src/Utils/ParserUtils.h
+++ b/src/Utils/ParserUtils.h
@@ -1,40 +1,51 @@
 #ifndef PARSER_UTILS_H
 #define PARSER_UTILS_H
-#include "FitParameters.h"
-#include "GeneralUtils.h"
+
+#include <math.h>
+#include <stdlib.h>
+#include <cstring>
+#include <fstream>
+#include <iostream>
+#include <map>
+#include <numeric>
+#include <sstream>
+#include <sstream>
+#include <string>
 #include <vector>
+#include <algorithm>
+#include "GeneralUtils.h"
 
 /// All functions used to parse input arguments.
 namespace ParserUtils {
 
 /// Checks a list of arguments for '-?' flags that have not been removed
 void CheckBadArguments(std::vector<std::string> args);
 
 /// Parses the arguments looked for the 'opt' flag and saves it into val
 void ParseArgument(std::vector<std::string>& args, std::string opt,
                    int& val, bool required = false, bool duplicates = true);
 
 /// Parses the arguments looked for the 'opt' flag and saves it into val
 void ParseArgument(std::vector<std::string>& args, std::string opt,
                    std::string& val, bool required = false, bool duplicates = true);
 
 /// Parses the arguments looked for the 'opt' flag and saves it into val
 void ParseSplitArgument(std::vector<std::string>& args, std::string opt,
                         std::string& val, bool required = false, bool duplicates = true);
 
 /// Parses the arguments looked for the 'opt' flag and saves all proceeding values into val (UNSTABLE)
 void ParseSplitArgument(std::vector<std::string>& args, std::string opt,
                         std::vector<std::string>& val, bool required = false, bool duplicates = true);
 
 // /// Take everything left in the string
 // void ParseRemainingXML(std::vector<std::string>& args, std::vector<std::string>& cmds);
 
 /// Parse arguments looking for '+/-opt' and add/subtract from counter when it occurs
 void ParseCounter(std::vector<std::string>& args, std::string opt, int& count);
 
 /// In the case where duplicates can be given, parses all cases into the val vector
 void ParseArgument(std::vector<std::string>& args, std::string opt,
                    std::vector<std::string>& val, bool required = false, bool duplicates = true);
 };
 
 #endif
diff --git a/src/Utils/PlotUtils.cxx b/src/Utils/PlotUtils.cxx
index 309f826..4eabf23 100644
--- a/src/Utils/PlotUtils.cxx
+++ b/src/Utils/PlotUtils.cxx
@@ -1,999 +1,999 @@
 // Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret
 
 /*******************************************************************************
 *    This file is part of NUISANCE.
 *
 *    NUISANCE is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    NUISANCE is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with NUISANCE.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
 
 #include "PlotUtils.h"
 #include "FitEvent.h"
-#include "FitParameters.h"
+#include "StatUtils.h"
 
 // MOVE TO MB UTILS!
 // This function is intended to be modified to enforce a consistent masking for
 // all models.
 TH2D* PlotUtils::SetMaskHist(std::string type, TH2D* data) {
   TH2D* fMaskHist = (TH2D*)data->Clone("fMaskHist");
 
   for (int xBin = 0; xBin < fMaskHist->GetNbinsX(); ++xBin) {
     for (int yBin = 0; yBin < fMaskHist->GetNbinsY(); ++yBin) {
       if (data->GetBinContent(xBin + 1, yBin + 1) == 0)
         fMaskHist->SetBinContent(xBin + 1, yBin + 1, 0);
       else
         fMaskHist->SetBinContent(xBin + 1, yBin + 1, 0.5);
 
       if (!type.compare("MB_numu_2D")) {
         if (yBin == 19 && xBin < 8)
           fMaskHist->SetBinContent(xBin + 1, yBin + 1, 1.0);
       } else {
         if (yBin == 19 && xBin < 11)
           fMaskHist->SetBinContent(xBin + 1, yBin + 1, 1.0);
       }
       if (yBin == 18 && xBin < 3)
         fMaskHist->SetBinContent(xBin + 1, yBin + 1, 1.0);
       if (yBin == 17 && xBin < 2)
         fMaskHist->SetBinContent(xBin + 1, yBin + 1, 1.0);
       if (yBin == 16 && xBin < 1)
         fMaskHist->SetBinContent(xBin + 1, yBin + 1, 1.0);
     }
   }
 
   return fMaskHist;
 };
 
 // MOVE TO GENERAL UTILS?
 bool PlotUtils::CheckObjectWithName(TFile* inFile, std::string substring) {
   TIter nextkey(inFile->GetListOfKeys());
   TKey* key;
 
   while ((key = (TKey*)nextkey())) {
     std::string test(key->GetName());
     if (test.find(substring) != std::string::npos) return true;
   }
   return false;
 };
 
 // MOVE TO GENERAL UTILS?
 std::string PlotUtils::GetObjectWithName(TFile* inFile, std::string substring) {
   TIter nextkey(inFile->GetListOfKeys());
   TKey* key;
   std::string output = "";
 
   while ((key = (TKey*)nextkey())) {
     std::string test(key->GetName());
     if (test.find(substring) != std::string::npos) output = test;
   }
 
   return output;
 };
 
 void PlotUtils::CreateNeutModeArray(TH1* hist, TH1* neutarray[]) {
   for (int i = 0; i < 60; i++) {
     neutarray[i] = (TH1*)hist->Clone(Form("%s_NMODE_%i", hist->GetName(), i));
   }
   return;
 };
 
 void PlotUtils::DeleteNeutModeArray(TH1* neutarray[]) {
   for (int i = 0; i < 60; i++) {
     delete neutarray[i];
   }
   return;
 };
 
 void PlotUtils::FillNeutModeArray(TH1D* hist[], int mode, double xval,
                                   double weight) {
   if (abs(mode) > 60) return;
   hist[abs(mode)]->Fill(xval, weight);
   return;
 };
 
 void PlotUtils::FillNeutModeArray(TH2D* hist[], int mode, double xval,
                                   double yval, double weight) {
   if (abs(mode) > 60) return;
   hist[abs(mode)]->Fill(xval, yval, weight);
   return;
 };
 
 THStack PlotUtils::GetNeutModeStack(std::string title, TH1* ModeStack[],
                                     int option) {
   (void)option;
   THStack allmodes = THStack(title.c_str(), title.c_str());
 
   for (int i = 0; i < 60; i++) {
     allmodes.Add(ModeStack[i]);
   }
 
   // Credit to Clarence for copying all this out.
 
   // CC
   ModeStack[1]->SetTitle("CCQE");
   ModeStack[1]->SetFillColor(kBlue);
   // ModeStack[1]->SetFillStyle(3444);
   ModeStack[1]->SetLineColor(kBlue);
   ModeStack[2]->SetTitle("2p/2h Nieves");
   ModeStack[2]->SetFillColor(kRed);
   // ModeStack[2]->SetFillStyle(3344);
   ModeStack[2]->SetLineColor(kRed);
 
   // ModeStack[11]->SetTitle("#it{#nu + p #rightarrow l^{-} + p + #pi^{+}}");
   ModeStack[11]->SetTitle("CC1#pi^{+} on p");
   ModeStack[11]->SetFillColor(kGreen);
   // ModeStack[11]->SetFillStyle(3004);
   ModeStack[11]->SetLineColor(kGreen);
   // ModeStack[12]->SetTitle("#it{#nu + n #rightarrow l^{-} + p + #pi^{0}}");
   ModeStack[12]->SetTitle("CC1#pi^{0} on n");
   ModeStack[12]->SetFillColor(kGreen + 3);
   // ModeStack[12]->SetFillStyle(3005);
   ModeStack[12]->SetLineColor(kGreen);
   // ModeStack[13]->SetTitle("#it{#nu + n #rightarrow l^{-} + n + #pi^{+}}");
   ModeStack[13]->SetTitle("CC1#pi^{+} on n");
   ModeStack[13]->SetFillColor(kGreen - 2);
   // ModeStack[13]->SetFillStyle(3004);
   ModeStack[13]->SetLineColor(kGreen);
 
   ModeStack[16]->SetTitle("CC coherent");
   ModeStack[16]->SetFillColor(kBlue);
   // ModeStack[16]->SetFillStyle(3644);
   ModeStack[16]->SetLineColor(kBlue);
 
   // ModeStack[17]->SetTitle("#it{#nu + n #rightarrow l^{-} + p + #gamma}");
   ModeStack[17]->SetTitle("CC1#gamma");
   ModeStack[17]->SetFillColor(kMagenta);
   // ModeStack[17]->SetFillStyle(3001);
   ModeStack[17]->SetLineColor(kMagenta);
 
   ModeStack[21]->SetTitle("Multi #pi (1.3 < W < 2.0)");
   ModeStack[21]->SetFillColor(kYellow);
   // ModeStack[21]->SetFillStyle(3005);
   ModeStack[21]->SetLineColor(kYellow);
 
   // ModeStack[22]->SetTitle("#it{#nu + n #rightarrow l^{-} + p + #eta^{0}}");
   ModeStack[22]->SetTitle("CC1#eta^{0} on n");
   ModeStack[22]->SetFillColor(kYellow - 2);
   // ModeStack[22]->SetFillStyle(3013);
   ModeStack[22]->SetLineColor(kYellow - 2);
   // ModeStack[23]->SetTitle("#it{#nu + n #rightarrow l^{-} + #Lambda +
   // K^{+}}");
   ModeStack[23]->SetTitle("CC1#Labda1K^{+}");
   ModeStack[23]->SetFillColor(kYellow - 6);
   // ModeStack[23]->SetFillStyle(3013);
   ModeStack[23]->SetLineColor(kYellow - 6);
 
   ModeStack[26]->SetTitle("DIS (W > 2.0)");
   ModeStack[26]->SetFillColor(kRed);
   // ModeStack[26]->SetFillStyle(3006);
   ModeStack[26]->SetLineColor(kRed);
 
   // NC
   // ModeStack[31]->SetTitle("#it{#nu + n #rightarrow #nu + n + #pi^{0}}");
   ModeStack[31]->SetTitle("NC1#pi^{0} on n");
   ModeStack[31]->SetFillColor(kBlue);
   // ModeStack[31]->SetFillStyle(3004);
   ModeStack[31]->SetLineColor(kBlue);
   // ModeStack[32]->SetTitle("#it{#nu + p #rightarrow #nu + p + #pi^{0}}");
   ModeStack[32]->SetTitle("NC1#pi^{0} on p");
   ModeStack[32]->SetFillColor(kBlue + 3);
   // ModeStack[32]->SetFillStyle(3004);
   ModeStack[32]->SetLineColor(kBlue + 3);
   // ModeStack[33]->SetTitle("#it{#nu + n #rightarrow #nu + p + #pi^{-}}");
   ModeStack[33]->SetTitle("NC1#pi^{-} on n");
   ModeStack[33]->SetFillColor(kBlue - 2);
   // ModeStack[33]->SetFillStyle(3005);
   ModeStack[33]->SetLineColor(kBlue - 2);
   // ModeStack[34]->SetTitle("#it{#nu + p #rightarrow #nu + n + #pi^{+}}");
   ModeStack[34]->SetTitle("NC1#pi^{+} on p");
   ModeStack[34]->SetFillColor(kBlue - 8);
   // ModeStack[34]->SetFillStyle(3005);
   ModeStack[34]->SetLineColor(kBlue - 8);
 
   ModeStack[36]->SetTitle("NC Coherent");
   ModeStack[36]->SetFillColor(kBlue + 8);
   // ModeStack[36]->SetFillStyle(3644);
   ModeStack[36]->SetLineColor(kBlue + 8);
 
   // ModeStack[38]->SetTitle("#it{#nu + n #rightarrow #nu + n + #gamma}");
   ModeStack[38]->SetTitle("NC1#gamma on n");
   ModeStack[38]->SetFillColor(kMagenta);
   // ModeStack[38]->SetFillStyle(3001);
   ModeStack[38]->SetLineColor(kMagenta);
   // ModeStack[39]->SetTitle("#it{#nu + p #rightarrow #nu + p + #gamma}");
   ModeStack[39]->SetTitle("NC1#gamma on p");
   ModeStack[39]->SetFillColor(kMagenta - 10);
   // ModeStack[39]->SetFillStyle(3001);
   ModeStack[39]->SetLineColor(kMagenta - 10);
 
   ModeStack[41]->SetTitle("Multi #pi (1.3 < W < 2.0)");
   ModeStack[41]->SetFillColor(kBlue - 10);
   // ModeStack[41]->SetFillStyle(3005);
   ModeStack[41]->SetLineColor(kBlue - 10);
 
   // ModeStack[42]->SetTitle("#it{#nu + n #rightarrow #nu + n + #eta^{0}}");
   ModeStack[42]->SetTitle("NC1#eta^{0} on n");
   ModeStack[42]->SetFillColor(kYellow - 2);
   // ModeStack[42]->SetFillStyle(3013);
   ModeStack[42]->SetLineColor(kYellow - 2);
   // ModeStack[43]->SetTitle("#it{#nu + p #rightarrow #nu + p + #eta^{0}}");
   ModeStack[43]->SetTitle("NC1#eta^{0} on p");
   ModeStack[43]->SetFillColor(kYellow - 4);
   // ModeStack[43]->SetFillStyle(3013);
   ModeStack[43]->SetLineColor(kYellow - 4);
 
   // ModeStack[44]->SetTitle("#it{#nu + n #rightarrow #nu + #Lambda + K^{0}}");
   ModeStack[44]->SetTitle("NC1#Lambda1K^{0} on n");
   ModeStack[44]->SetFillColor(kYellow - 6);
   // ModeStack[44]->SetFillStyle(3014);
   ModeStack[44]->SetLineColor(kYellow - 6);
   // ModeStack[45]->SetTitle("#it{#nu + p #rightarrow #nu + #Lambda + K^{+}}");
   ModeStack[45]->SetTitle("NC1#Lambda1K^{+}");
   ModeStack[45]->SetFillColor(kYellow - 10);
   // ModeStack[45]->SetFillStyle(3014);
   ModeStack[45]->SetLineColor(kYellow - 10);
 
   ModeStack[46]->SetTitle("DIS (W > 2.0)");
   ModeStack[46]->SetFillColor(kRed);
   // ModeStack[46]->SetFillStyle(3006);
   ModeStack[46]->SetLineColor(kRed);
 
   // ModeStack[51]->SetTitle("#it{#nu + p #rightarrow #nu + p}");
   ModeStack[51]->SetTitle("NC on p");
   ModeStack[51]->SetFillColor(kBlack);
   // ModeStack[51]->SetFillStyle(3444);
   ModeStack[51]->SetLineColor(kBlack);
   // ModeStack[52]->SetTitle("#it{#nu + n #rightarrow #nu + n}");
   ModeStack[52]->SetTitle("NC on n");
   ModeStack[52]->SetFillColor(kGray);
   // ModeStack[52]->SetFillStyle(3444);
   ModeStack[52]->SetLineColor(kGray);
 
   return allmodes;
 };
 
 TLegend PlotUtils::GenerateStackLegend(THStack stack, int xlow, int ylow,
                                        int xhigh, int yhigh) {
   TLegend leg = TLegend(xlow, ylow, xhigh, yhigh);
 
   TObjArray* histarray = stack.GetStack();
 
   int nhist = histarray->GetEntries();
   for (int i = 0; i < nhist; i++) {
     TH1* hist = (TH1*)(histarray->At(i));
     leg.AddEntry((hist), ((TH1*)histarray->At(i))->GetTitle(), "fl");
   }
 
   leg.SetName(Form("%s_LEG", stack.GetName()));
 
   return leg;
 };
 
 void PlotUtils::ScaleNeutModeArray(TH1* hist[], double factor,
                                    std::string option) {
   for (int i = 0; i < 60; i++) {
     if (hist[i]) hist[i]->Scale(factor, option.c_str());
   }
 
   return;
 };
 
 void PlotUtils::ResetNeutModeArray(TH1* hist[]) {
   for (int i = 0; i < 60; i++) {
     if (hist[i]) hist[i]->Reset();
   }
 
   return;
 };
 
 //********************************************************************
 // This assumes the Enu axis is the x axis, as is the case for MiniBooNE 2D
 // distributions
 void PlotUtils::FluxUnfoldedScaling(TH2D* fMCHist, TH1D* fhist, TH1D* ehist,
                                     double scalefactor) {
   //********************************************************************
 
   // Make clones to avoid changing stuff
   TH1D* eventhist = (TH1D*)ehist->Clone();
   TH1D* fFluxHist = (TH1D*)fhist->Clone();
 
   // Undo width integral in SF
   fMCHist->Scale(scalefactor /
                  eventhist->Integral(1, eventhist->GetNbinsX() + 1, "width"));
 
   // Standardise The Flux
   eventhist->Scale(1.0 / fFluxHist->Integral());
   fFluxHist->Scale(1.0 / fFluxHist->Integral());
 
   // Do interpolation for 2D plots?
   // fFluxHist = PlotUtils::InterpolateFineHistogram(fFluxHist,100,"width");
   // eventhist = PlotUtils::InterpolateFineHistogram(eventhist,100,"width");
 
   // eventhist->Scale(1.0/fFluxHist->Integral());
   // fFluxHist->Scale(1.0/fFluxHist->Integral());
 
   // Scale fMCHist by eventhist integral
   fMCHist->Scale(eventhist->Integral(1, eventhist->GetNbinsX() + 1));
 
   // Now Get a flux PDF assuming X axis is Enu
   TH1D* pdfflux = (TH1D*)fMCHist->ProjectionX()->Clone();
   //  pdfflux->Write( (std::string(fMCHist->GetName()) + "_PROJX").c_str());
   pdfflux->Reset();
 
   // Awful MiniBooNE Check for the time being
   bool ismb =
       std::string(fMCHist->GetName()).find("MiniBooNE") != std::string::npos;
 
   for (int i = 0; i < pdfflux->GetNbinsX(); i++) {
     double Ml = pdfflux->GetXaxis()->GetBinLowEdge(i + 1);
     double Mh = pdfflux->GetXaxis()->GetBinLowEdge(i + 2);
     // double Mc = pdfflux->GetXaxis()->GetBinCenter(i+1);
     // double Mw = pdfflux->GetBinWidth(i+1);
     double fluxint = 0.0;
 
     // Scaling to match flux for MB
     if (ismb) {
       Ml /= 1.E3;
       Mh /= 1.E3;
       //  Mc /= 1.E3;
       //  Mw /= 1.E3;
     }
 
     for (int j = 0; j < fFluxHist->GetNbinsX(); j++) {
       // double Fc = fFluxHist->GetXaxis()->GetBinCenter(j+1);
       double Fl = fFluxHist->GetXaxis()->GetBinLowEdge(j + 1);
       double Fh = fFluxHist->GetXaxis()->GetBinLowEdge(j + 2);
       double Fe = fFluxHist->GetBinContent(j + 1);
       double Fw = fFluxHist->GetXaxis()->GetBinWidth(j + 1);
 
       if (Fl >= Ml and Fh <= Mh) {
         fluxint += Fe;
       } else if (Fl < Ml and Fl < Mh and Fh > Ml and Fh < Mh) {
         fluxint += Fe * (Fh - Ml) / Fw;
       } else if (Fh > Mh and Fl < Mh and Fh > Ml and Fl > Ml) {
         fluxint += Fe * (Mh - Fl) / Fw;
       } else if (Ml >= Fl and Mh <= Fh) {
         fluxint += Fe * (Mh - Ml) / Fw;
       } else {
         continue;
       }
     }
 
     pdfflux->SetBinContent(i + 1, fluxint);
   }
 
   for (int i = 0; i < fMCHist->GetNbinsX(); i++) {
     for (int j = 0; j < fMCHist->GetNbinsY(); j++) {
       if (pdfflux->GetBinContent(i + 1) == 0.0) continue;
 
       double binWidth = fMCHist->GetYaxis()->GetBinLowEdge(j + 2) -
                         fMCHist->GetYaxis()->GetBinLowEdge(j + 1);
       fMCHist->SetBinContent(i + 1, j + 1,
                              fMCHist->GetBinContent(i + 1, j + 1) /
                                  pdfflux->GetBinContent(i + 1) / binWidth);
       fMCHist->SetBinError(i + 1, j + 1, fMCHist->GetBinError(i + 1, j + 1) /
                                              pdfflux->GetBinContent(i + 1) /
                                              binWidth);
     }
   }
 
   delete eventhist;
   delete fFluxHist;
 
   return;
 };
 
 TH1D* PlotUtils::InterpolateFineHistogram(TH1D* hist, int res,
                                           std::string opt) {
   int nbins = hist->GetNbinsX();
   double elow = hist->GetXaxis()->GetBinLowEdge(1);
   double ehigh = hist->GetXaxis()->GetBinLowEdge(nbins + 1);
   bool width = true;  // opt.find("width") != std::string::npos;
 
   TH1D* fine = new TH1D("fine", "fine", nbins * res, elow, ehigh);
 
   TGraph* temp = new TGraph();
 
   for (int i = 0; i < nbins; i++) {
     double E = hist->GetXaxis()->GetBinCenter(i + 1);
     double C = hist->GetBinContent(i + 1);
     double W = hist->GetXaxis()->GetBinWidth(i + 1);
     if (!width) W = 1.0;
 
     if (W != 0.0) temp->SetPoint(temp->GetN(), E, C / W);
   }
 
   for (int i = 0; i < fine->GetNbinsX(); i++) {
     double E = fine->GetXaxis()->GetBinCenter(i + 1);
     double W = fine->GetBinWidth(i + 1);
     if (!width) W = 1.0;
 
     fine->SetBinContent(i + 1, temp->Eval(E, 0, "S") * W);
   }
 
   fine->Scale(hist->Integral(1, hist->GetNbinsX() + 1) /
               fine->Integral(1, fine->GetNbinsX() + 1));
   std::cout << "Interpolation Difference = "
             << fine->Integral(1, fine->GetNbinsX() + 1) << "/"
             << hist->Integral(1, hist->GetNbinsX() + 1) << std::endl;
 
   return fine;
 }
 
 //********************************************************************
 // This interpolates the flux by a TGraph instead of requiring the flux and MC
 // flux to have the same binning
 void PlotUtils::FluxUnfoldedScaling(TH1D* mcHist, TH1D* fhist, TH1D* ehist,
                                     double scalefactor, int nevents) {
   //********************************************************************
 
   TH1D* eventhist = (TH1D*)ehist->Clone();
   TH1D* fFluxHist = (TH1D*)fhist->Clone();
 
   if (FitPar::Config().GetParB("save_flux_debug")) {
     std::string name = std::string(mcHist->GetName());
 
     mcHist->Write((name + "_UNF_MC").c_str());
     fFluxHist->Write((name + "_UNF_FLUX").c_str());
     eventhist->Write((name + "_UNF_EVT").c_str());
 
     TH1D* scalehist = new TH1D("scalehist", "scalehist", 1, 0.0, 1.0);
     scalehist->SetBinContent(1, scalefactor);
     scalehist->SetBinContent(2, nevents);
 
     scalehist->Write((name + "_UNF_SCALE").c_str());
   }
 
   // Undo width integral in SF
   mcHist->Scale(scalefactor /
                 eventhist->Integral(1, eventhist->GetNbinsX() + 1, "width"));
 
   // Standardise The Flux
   eventhist->Scale(1.0 / fFluxHist->Integral());
   fFluxHist->Scale(1.0 / fFluxHist->Integral());
 
   // Scale mcHist by eventhist integral
   mcHist->Scale(eventhist->Integral(1, eventhist->GetNbinsX() + 1));
 
   // Now Get a flux PDF
   TH1D* pdfflux = (TH1D*)mcHist->Clone();
   pdfflux->Reset();
 
   for (int i = 0; i < mcHist->GetNbinsX(); i++) {
     double Ml = mcHist->GetXaxis()->GetBinLowEdge(i + 1);
     double Mh = mcHist->GetXaxis()->GetBinLowEdge(i + 2);
     // double Mc = mcHist->GetXaxis()->GetBinCenter(i+1);
     // double Me = mcHist->GetBinContent(i+1);
     // double Mw = mcHist->GetBinWidth(i+1);
     double fluxint = 0.0;
 
     for (int j = 0; j < fFluxHist->GetNbinsX(); j++) {
       // double Fc = fFluxHist->GetXaxis()->GetBinCenter(j+1);
       double Fl = fFluxHist->GetXaxis()->GetBinLowEdge(j + 1);
       double Fh = fFluxHist->GetXaxis()->GetBinLowEdge(j + 2);
       double Fe = fFluxHist->GetBinContent(j + 1);
       double Fw = fFluxHist->GetXaxis()->GetBinWidth(j + 1);
 
       if (Fl >= Ml and Fh <= Mh) {
         fluxint += Fe;
       } else if (Fl < Ml and Fl < Mh and Fh > Ml and Fh < Mh) {
         fluxint += Fe * (Fh - Ml) / Fw;
       } else if (Fh > Mh and Fl < Mh and Fh > Ml and Fl > Ml) {
         fluxint += Fe * (Mh - Fl) / Fw;
       } else if (Ml >= Fl and Mh <= Fh) {
         fluxint += Fe * (Mh - Ml) / Fw;
       } else {
         continue;
       }
     }
 
     pdfflux->SetBinContent(i + 1, fluxint);
   }
 
   // Scale MC hist by pdfflux
   for (int i = 0; i < mcHist->GetNbinsX(); i++) {
     if (pdfflux->GetBinContent(i + 1) == 0.0) continue;
 
     mcHist->SetBinContent(
         i + 1, mcHist->GetBinContent(i + 1) / pdfflux->GetBinContent(i + 1));
     mcHist->SetBinError(
         i + 1, mcHist->GetBinError(i + 1) / pdfflux->GetBinContent(i + 1));
   }
 
   delete eventhist;
   delete fFluxHist;
 
   return;
 };
 
 // MOVE TO GENERAL UTILS
 //********************************************************************
 void PlotUtils::Set2DHistFromText(std::string dataFile, TH2* hist, double norm,
                                   bool skipbins) {
   //********************************************************************
 
   std::string line;
   std::ifstream data(dataFile.c_str(), ifstream::in);
 
   int yBin = 0;
   while (std::getline(data >> std::ws, line, '\n')) {
     std::vector<double> entries = GeneralUtils::ParseToDbl(line, " ");
 
     // Loop over entries and insert them into the histogram
     for (uint xBin = 0; xBin < entries.size(); xBin++) {
       if (!skipbins or entries[xBin] != -1.0)
         hist->SetBinContent(xBin + 1, yBin + 1, entries[xBin] * norm);
     }
     yBin++;
   }
 
   return;
 }
 
 // MOVE TO GENERAL UTILS
 TH1D* PlotUtils::GetTH1DFromFile(std::string dataFile, std::string title,
                                  std::string fPlotTitles,
                                  std::string alt_name) {
   TH1D* tempPlot;
 
   // If format is a root file
   if (dataFile.find(".root") != std::string::npos) {
     TFile* temp_infile = new TFile(dataFile.c_str(), "READ");
     tempPlot = (TH1D*)temp_infile->Get(title.c_str());
     tempPlot->SetDirectory(0);
 
     temp_infile->Close();
     delete temp_infile;
 
     // Else its a space seperated txt file
   } else {
     // Make a TGraph Errors
     TGraphErrors* gr = new TGraphErrors(dataFile.c_str(), "%lg %lg %lg");
     if (gr->IsZombie()) {
       exit(-1);
     }
     double* bins = gr->GetX();
     double* values = gr->GetY();
     double* errors = gr->GetEY();
     int npoints = gr->GetN();
 
     // Fill the histogram from it
     tempPlot = new TH1D(title.c_str(), title.c_str(), npoints - 1, bins);
 
     for (int i = 0; i < npoints; ++i) {
       tempPlot->SetBinContent(i + 1, values[i]);
 
       // If only two columns are present in the input file, use the sqrt(values)
       // as the error
       // equivalent to assuming that the error is statistical
       if (!errors[i])
         tempPlot->SetBinError(i + 1, sqrt(values[i]));
       else
         tempPlot->SetBinError(i + 1, errors[i]);
     }
 
     delete gr;
   }
 
   // Allow alternate naming for root files
   if (!alt_name.empty()) {
     tempPlot->SetNameTitle(alt_name.c_str(), alt_name.c_str());
   }
 
   // Allow alternate axis titles
   if (!fPlotTitles.empty()) {
     tempPlot->SetNameTitle(
         tempPlot->GetName(),
         (std::string(tempPlot->GetTitle()) + fPlotTitles).c_str());
   }
 
   return tempPlot;
 };
 
 TH1D* PlotUtils::GetRatioPlot(TH1D* hist1, TH1D* hist2) {
   // make copy of first hist
   TH1D* new_hist = (TH1D*)hist1->Clone();
 
   // Do bins and errors ourselves as scales can go awkward
   for (int i = 0; i < new_hist->GetNbinsX(); i++) {
     if (hist2->GetBinContent(i + 1) == 0.0) {
       new_hist->SetBinContent(i + 1, 0.0);
     }
 
     new_hist->SetBinContent(
         i + 1, hist1->GetBinContent(i + 1) / hist2->GetBinContent(i + 1));
     new_hist->SetBinError(
         i + 1, hist1->GetBinError(i + 1) / hist2->GetBinContent(i + 1));
   }
 
   return new_hist;
 };
 
 TH1D* PlotUtils::GetRenormalisedPlot(TH1D* hist1, TH1D* hist2) {
   // make copy of first hist
   TH1D* new_hist = (TH1D*)hist1->Clone();
 
   if (hist1->Integral("width") == 0 or hist2->Integral("width") == 0) {
     new_hist->Reset();
     return new_hist;
   }
 
   Double_t scaleF = hist2->Integral("width") / hist1->Integral("width");
   new_hist->Scale(scaleF);
 
   return new_hist;
 };
 
 TH1D* PlotUtils::GetShapePlot(TH1D* hist1) {
   // make copy of first hist
   TH1D* new_hist = (TH1D*)hist1->Clone();
 
   if (hist1->Integral("width") == 0) {
     new_hist->Reset();
     return new_hist;
   }
 
   Double_t scaleF1 = 1.0 / hist1->Integral("width");
 
   new_hist->Scale(scaleF1);
 
   return new_hist;
 };
 
 TH1D* PlotUtils::GetShapeRatio(TH1D* hist1, TH1D* hist2) {
   TH1D* new_hist1 = GetShapePlot(hist1);
   TH1D* new_hist2 = GetShapePlot(hist2);
 
   // Do bins and errors ourselves as scales can go awkward
   for (int i = 0; i < new_hist1->GetNbinsX(); i++) {
     if (hist2->GetBinContent(i + 1) == 0) {
       new_hist1->SetBinContent(i + 1, 0.0);
     }
 
     new_hist1->SetBinContent(i + 1, new_hist1->GetBinContent(i + 1) /
                                         new_hist2->GetBinContent(i + 1));
     new_hist1->SetBinError(
         i + 1, new_hist1->GetBinError(i + 1) / new_hist2->GetBinContent(i + 1));
   }
 
   delete new_hist2;
 
   return new_hist1;
 };
 
 TH2D* PlotUtils::GetCovarPlot(TMatrixDSym* cov, std::string name,
                               std::string title) {
   TH2D* CovarPlot;
 
   if (cov)
     CovarPlot = new TH2D((*cov));
   else
     CovarPlot = new TH2D(name.c_str(), title.c_str(), 1, 0, 1, 1, 0, 1);
 
   CovarPlot->SetName(name.c_str());
   CovarPlot->SetTitle(title.c_str());
 
   return CovarPlot;
 }
 
 TH2D* PlotUtils::GetFullCovarPlot(TMatrixDSym* cov, std::string name) {
   return PlotUtils::GetCovarPlot(
       cov, name + "_COV", name + "_COV;Bins;Bins;Covariance (#times10^{-76})");
 }
 
 TH2D* PlotUtils::GetInvCovarPlot(TMatrixDSym* cov, std::string name) {
   return PlotUtils::GetCovarPlot(
       cov, name + "_INVCOV",
       name + "_INVCOV;Bins;Bins;Inv. Covariance (#times10^{-76})");
 }
 
 TH2D* PlotUtils::GetDecompCovarPlot(TMatrixDSym* cov, std::string name) {
   return PlotUtils::GetCovarPlot(
       cov, name + "_DECCOV",
       name + "_DECCOV;Bins;Bins;Decomp Covariance (#times10^{-76})");
 }
 
 TH1D* PlotUtils::GetTH1DFromRootFile(std::string file, std::string name) {
   if (name.empty()) {
     std::vector<std::string> tempfile = GeneralUtils::ParseToStr(file, ";");
     file = tempfile[0];
     name = tempfile[1];
   }
 
   TFile* rootHistFile = new TFile(file.c_str(), "READ");
   TH1D* tempHist = (TH1D*)rootHistFile->Get(name.c_str())->Clone();
   tempHist->SetDirectory(0);
 
   rootHistFile->Close();
 
   return tempHist;
 }
 
 TH2D* PlotUtils::GetTH2DFromRootFile(std::string file, std::string name) {
   if (name.empty()) {
     std::vector<std::string> tempfile = GeneralUtils::ParseToStr(file, ";");
     file = tempfile[0];
     name = tempfile[1];
   }
 
   TFile* rootHistFile = new TFile(file.c_str(), "READ");
   TH2D* tempHist = (TH2D*)rootHistFile->Get(name.c_str())->Clone();
   tempHist->SetDirectory(0);
 
   rootHistFile->Close();
 
   return tempHist;
 }
 
 TH1* PlotUtils::GetTH1FromRootFile(std::string file, std::string name) {
   if (name.empty()) {
     std::vector<std::string> tempfile = GeneralUtils::ParseToStr(file, ";");
     file = tempfile[0];
     name = tempfile[1];
   }
 
   TFile* rootHistFile = new TFile(file.c_str(), "READ");
   if (!rootHistFile || rootHistFile->IsZombie()) {
     THROW("Couldn't open root file: \"" << file << "\".");
   }
   TH1* tempHist = dynamic_cast<TH1*>(rootHistFile->Get(name.c_str())->Clone());
   if (!tempHist) {
     THROW("Couldn't retrieve: \"" << name << "\" from root file: \"" << file
                                   << "\".");
   }
   tempHist->SetDirectory(0);
 
   rootHistFile->Close();
 
   return tempHist;
 }
 
 /// Returns a vector of named TH1*s found in a single input file.
 ///
 /// Expects a descriptor like: file.root[hist1|hist2|...]
 std::vector<TH1*> PlotUtils::GetTH1sFromRootFile(
     std::string const& descriptor) {
   std::vector<std::string> descriptors =
       GeneralUtils::ParseToStr(descriptor, ",");
 
   std::vector<TH1*> hists;
   for (size_t d_it = 0; d_it < descriptors.size(); ++d_it) {
     std::string& d = descriptors[d_it];
 
     std::vector<std::string> fname = GeneralUtils::ParseToStr(d, "[");
     if (!fname.size() || !fname[0].length()) {
       THROW("Couldn't find input file when attempting to parse : \""
             << d << "\". Expected input.root[hist1|hist2|...].");
     }
 
     if (fname[1][fname[1].length() - 1] == ']') {
       fname[1] = fname[1].substr(0, fname[1].length() - 1);
     }
     std::vector<std::string> histnames =
         GeneralUtils::ParseToStr(fname[1], "|");
     if (!histnames.size()) {
       THROW(
           "Couldn't find any histogram name specifiers when attempting to "
           "parse "
           ": \""
           << fname[1] << "\". Expected hist1|hist2|...");
     }
 
     TFile* rootHistFile = new TFile(fname[0].c_str(), "READ");
     if (!rootHistFile || rootHistFile->IsZombie()) {
       THROW("Couldn't open root file: \"" << fname[0] << "\".");
     }
 
     for (size_t i = 0; i < histnames.size(); ++i) {
       TH1* tempHist =
           dynamic_cast<TH1*>(rootHistFile->Get(histnames[i].c_str())->Clone());
       if (!tempHist) {
         THROW("Couldn't retrieve: \"" << histnames[i] << "\" from root file: \""
                                       << fname[0] << "\".");
       }
       tempHist->SetDirectory(0);
       hists.push_back(tempHist);
     }
     rootHistFile->Close();
   }
 
   return hists;
 }
 
 TH2D* PlotUtils::GetTH2DFromTextFile(std::string file) {
   /// Contents should be
   /// Low Edfe
 
   return NULL;
 }
 
 void PlotUtils::AddNeutModeArray(TH1D* hist1[], TH1D* hist2[], double scaling) {
   for (int i = 0; i < 60; i++) {
     if (!hist2[i]) continue;
     if (!hist1[i]) continue;
     hist1[i]->Add(hist2[i], scaling);
   }
   return;
 }
 
 void PlotUtils::ScaleToData(TH1D* data, TH1D* mc, TH1I* mask) {
   double scaleF = GetDataMCRatio(data, mc, mask);
   mc->Scale(scaleF);
 
   return;
 }
 
 void PlotUtils::MaskBins(TH1D* hist, TH1I* mask) {
   for (int i = 0; i < hist->GetNbinsX(); i++) {
     if (mask->GetBinContent(i + 1) <= 0.5) continue;
 
     hist->SetBinContent(i + 1, 0.0);
     hist->SetBinError(i + 1, 0.0);
 
     LOG(REC) << "MaskBins: Set " << hist->GetName() << " Bin " << i + 1
              << " to 0.0 +- 0.0" << std::endl;
   }
 
   return;
 }
 
 void PlotUtils::MaskBins(TH2D* hist, TH2I* mask) {
   for (int i = 0; i < hist->GetNbinsX(); i++) {
     for (int j = 0; j < hist->GetNbinsY(); j++) {
       if (mask->GetBinContent(i + 1, j + 1) <= 0.5) continue;
 
       hist->SetBinContent(i + 1, j + 1, 0.0);
       hist->SetBinError(i + 1, j + 1, 0.0);
 
       LOG(REC) << "MaskBins: Set " << hist->GetName() << " Bin " << i + 1 << " "
                << j + 1 << " to 0.0 +- 0.0" << std::endl;
     }
   }
   return;
 }
 
 double PlotUtils::GetDataMCRatio(TH1D* data, TH1D* mc, TH1I* mask) {
   double rat = 1.0;
 
   TH1D* newmc = (TH1D*)mc->Clone();
   TH1D* newdt = (TH1D*)data->Clone();
 
   if (mask) {
     MaskBins(newmc, mask);
     MaskBins(newdt, mask);
   }
 
   rat = newdt->Integral() / newmc->Integral();
 
   return rat;
 }
 
 TH2D* PlotUtils::GetCorrelationPlot(TH2D* cov, std::string name) {
   TH2D* cor = (TH2D*)cov->Clone();
   cor->Reset();
 
   for (int i = 0; i < cov->GetNbinsX(); i++) {
     for (int j = 0; j < cov->GetNbinsY(); j++) {
       if (cov->GetBinContent(i + 1, i + 1) != 0.0 and
           cov->GetBinContent(j + 1, j + 1) != 0.0)
         cor->SetBinContent(i + 1, j + 1,
                            cov->GetBinContent(i + 1, j + 1) /
                                (sqrt(cov->GetBinContent(i + 1, i + 1) *
                                      cov->GetBinContent(j + 1, j + 1))));
     }
   }
 
   if (!name.empty()) {
     cor->SetNameTitle(name.c_str(), (name + ";;correlation").c_str());
   }
 
   cor->SetMinimum(-1);
   cor->SetMaximum(1);
 
   return cor;
 }
 
 TH2D* PlotUtils::GetDecompPlot(TH2D* cov, std::string name) {
   TMatrixDSym* covarmat = new TMatrixDSym(cov->GetNbinsX());
 
   for (int i = 0; i < cov->GetNbinsX(); i++)
     for (int j = 0; j < cov->GetNbinsY(); j++)
       (*covarmat)(i, j) = cov->GetBinContent(i + 1, j + 1);
 
   TMatrixDSym* decompmat = StatUtils::GetDecomp(covarmat);
 
   TH2D* dec = (TH2D*)cov->Clone();
   for (int i = 0; i < cov->GetNbinsX(); i++)
     for (int j = 0; j < cov->GetNbinsY(); j++)
       dec->SetBinContent(i + 1, j + 1, (*decompmat)(i, j));
 
   delete covarmat;
   delete decompmat;
 
   dec->SetNameTitle(name.c_str(), (name + ";;;decomposition").c_str());
 
   return dec;
 }
 
 TH2D* PlotUtils::MergeIntoTH2D(TH1D* xhist, TH1D* yhist, std::string zname) {
   std::vector<double> xedges, yedges;
   for (int i = 0; i < xhist->GetNbinsX() + 2; i++) {
     xedges.push_back(xhist->GetXaxis()->GetBinLowEdge(i + 1));
   }
   for (int i = 0; i < yhist->GetNbinsX() + 2; i++) {
     yedges.push_back(yhist->GetXaxis()->GetBinLowEdge(i + 1));
   }
 
   int nbinsx = xhist->GetNbinsX();
   int nbinsy = yhist->GetNbinsX();
 
   std::string name =
       std::string(xhist->GetName()) + "_vs_" + std::string(yhist->GetName());
   std::string titles = ";" + std::string(xhist->GetXaxis()->GetTitle()) + ";" +
                        std::string(yhist->GetXaxis()->GetTitle()) + ";" + zname;
 
   TH2D* newplot = new TH2D(name.c_str(), (name + titles).c_str(), nbinsx,
                            &xedges[0], nbinsy, &yedges[0]);
 
   return newplot;
 }
 
 //***************************************************
 void PlotUtils::MatchEmptyBins(TH1D* data, TH1D* mc) {
   //**************************************************
 
   for (int i = 0; i < data->GetNbinsX(); i++) {
     if (data->GetBinContent(i + 1) == 0.0 or data->GetBinError(i + 1) == 0.0)
       mc->SetBinContent(i + 1, 0.0);
   }
 
   return;
 }
 
 //***************************************************
 void PlotUtils::MatchEmptyBins(TH2D* data, TH2D* mc) {
   //**************************************************
 
   for (int i = 0; i < data->GetNbinsX(); i++) {
     for (int j = 0; j < data->GetNbinsY(); j++) {
       if (data->GetBinContent(i + 1, j + 1) == 0.0 or
           data->GetBinError(i + 1, j + 1) == 0.0)
         mc->SetBinContent(i + 1, j + 1, 0.0);
     }
   }
 
   return;
 }
 
 //***************************************************
 TH1D* PlotUtils::GetProjectionX(TH2D* hist, TH2I* mask) {
   //***************************************************
 
   TH2D* maskedhist = StatUtils::ApplyHistogramMasking(hist, mask);
 
   TH1D* hist_X = maskedhist->ProjectionX();
 
   delete maskedhist;
   return hist_X;
 }
 
 //***************************************************
 TH1D* PlotUtils::GetProjectionY(TH2D* hist, TH2I* mask) {
   //***************************************************
 
   TH2D* maskedhist = StatUtils::ApplyHistogramMasking(hist, mask);
 
   TH1D* hist_Y = maskedhist->ProjectionY();
 
   delete maskedhist;
   return hist_Y;
 }
diff --git a/src/Utils/PlotUtils.h b/src/Utils/PlotUtils.h
index c326320..acd29da 100644
--- a/src/Utils/PlotUtils.h
+++ b/src/Utils/PlotUtils.h
@@ -1,241 +1,240 @@
 // Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret
 
 /*******************************************************************************
 *    This file is part of NUISANCE.
 *
 *    NUISANCE is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    NUISANCE is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with NUISANCE.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
 
 #ifndef PLOTUTILS_H_SEEN
 #define PLOTUTILS_H_SEEN
 
 #include "TF1.h"
 #include "TFile.h"
 #include "TH1.h"
 #include "TMatrixD.h"
 #include "TProfile.h"
 #include "TSystem.h"
 #include "TVectorD.h"
 
 #include <cstring>
 #include <iostream>
 #include <sstream>
 #include <string>
 #include <vector>
 
 // C Includes
 #include <math.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <cstring>
 #include <iostream>
 #include <iostream>
 #include <numeric>
 #include <sstream>
 #include <string>
 #include <vector>
 
 // ROOT includes
 #include <TChain.h>
 #include <TFile.h>
 #include <TH1D.h>
 #include <TH2D.h>
 #include <THStack.h>
 #include <TKey.h>
 #include <TLegend.h>
 #include <TList.h>
 #include <TLorentzVector.h>
 #include <TObjArray.h>
 #include <TROOT.h>
 #include <TRandom3.h>
 #include <TTree.h>
 #include <ctime>
 #include "TGraphErrors.h"
 #include "TH2Poly.h"
 #include "TMatrixDSym.h"
 
 // Fit includes
 #include "FitEvent.h"
 #include "FitLogger.h"
-#include "FitParameters.h"
 #include "GeneralUtils.h"
 #include "StatUtils.h"
 
 /*!
  *  \addtogroup Utils
  *  @{
  */
 
 //! Functions to handle different TH1s and TFiles
 namespace PlotUtils {
 
 /*!
   MISC Functions
 */
 
 //! Check the root file has an object containing the given substring in its name
 bool CheckObjectWithName(TFile* inFile, std::string substring);
 
 //! Get object in a TFile that has  a matching substring in its name
 std::string GetObjectWithName(TFile* inFile, std::string substring);
 
 /*!
   Interaction Mode Histogram Handling
 */
 
 //! Fill the Histogram Array with 61 new histograms for interaction channels.
 void CreateNeutModeArray(TH1* hist, TH1* neutarray[]);
 
 //! Call Fill on the relevent Mode 1D Histogram
 void FillNeutModeArray(TH1D* hist[], int mode, double xval,
                        double weight = 1.0);
 
 //! Call Fill on the relevant Mode 2D Histogram
 void FillNeutModeArray(TH2D* hist[], int mode, double xval, double yval,
                        double weight = 1.0);
 
 //! Given two arrays of histograms for the NEUT interaction mode, hist1 = hist1
 //! + scale*hist2
 void AddNeutModeArray(TH1D* hist1[], TH1D* hist2[], double scaling = 1.0);
 
 //! Generate a legend for the THStack
 TLegend GenerateStackLegend(THStack stack, int xlow, int ylow, int xhigh,
                             int yhigh);
 
 //! Turn the array of TH1 histograms into a stack of Modes
 THStack GetNeutModeStack(std::string title, TH1* ModeStack[], int option);
 
 //! Reset each histogram in the mode array
 void ResetNeutModeArray(TH1* hist[]);
 
 //! Scale each histogram in the mode array by a single scaling factor, option
 //! can be used to define "width" scaling.
 void ScaleNeutModeArray(TH1* hist[], double factor, std::string option = "");
 
 //! Free up the memory used by each of the 61 mode histograms
 void DeleteNeutModeArray(TH1* neutarray[]);
 
 /*!
   Handling Functions
 */
 
 //! Fill a mask histogram from a text file
 TH2D* SetMaskHist(std::string type, TH2D* data);
 
 //! Divide by the flux histogram for Enu Histograms
 void DivideByFlux(TH1D* fMCHist, TH1D* fFluxHist);
 
 TH1D* InterpolateFineHistogram(TH1D* hist, int res, std::string opt);
 
 //! Flux unfolded scaling, like DivideByFlux but uses interpolation.
 void FluxUnfoldedScaling(TH1D* plot, TH1D* flux, TH1D* events = NULL,
                          double scalefactor = 1.0, int nevents = 1);
 
 //! Flux unfolded scaling for 2D histograms
 void FluxUnfoldedScaling(TH2D* plot, TH1D* flux, TH1D* events = NULL,
                          double scalefactor = 1.0);
 
 //! Fill a 2D Histogram from a text file
 void Set2DHistFromText(std::string dataFile, TH2* hist, double norm,
                        bool skipbins = false);
 
 //! Fill a 2D Poly Histogram from a text file
 void Set2PolyHistFromText(std::string dataFile, TH2Poly* hist, double norm,
                           bool skipbins = false);
 
 //! Fill a 1D Histogram from a text file
 TH1D* GetTH1DFromFile(std::string dataFile, std::string title = "",
                       std::string fPlotTitles = "", std::string alt_name = "");
 
 TH1* GetTH1FromRootFile(std::string file, std::string name);
 
 std::vector<TH1*> GetTH1sFromRootFile(std::string const& descriptor);
 
 //! Grab a 1D Histrogram from a ROOT File
 TH1D* GetTH1DFromRootFile(std::string file, std::string name);
 
 //! Grab a 2D Histrogram from a ROOT File
 TH2D* GetTH2DFromRootFile(std::string file, std::string name);
 
 //! Grab a 2D Histrogram from a ROOT File
 TH2D* GetTH2DFromTextFile(std::string file);
 
 //! Scale mc to match data considering empty and masked bins
 void ScaleToData(TH1D* data, TH1D* mc, TH1I* mask);
 
 //! Apply bin masking (More cosmetic)
 void MaskBins(TH1D* hist, TH1I* mask);
 
 //! Apply bin masking (More cosmetic)
 void MaskBins(TH2D* hist, TH2I* mask);
 
 //! Get the data MC ratio considering empty and masked bins
 double GetDataMCRatio(TH1D* data, TH1D* mc, TH1I* mask = NULL);
 
 /*!
   Formatting Plot Utils
 */
 
 //! Create new ratio plot. hist3 = hist1/hist2
 TH1D* GetRatioPlot(TH1D* hist1, TH1D* hist2);
 
 //! Create new plot of hist2 normalised to hist1. hist2 = hist1 *
 //! (Integral(hist1)/Integral(hist2))
 TH1D* GetRenormalisedPlot(TH1D* hist1, TH1D* hist2);
 
 //! Normalise histogram to area of unity.
 TH1D* GetShapePlot(TH1D* hist1);
 
 //! Normalise hist1 and hist2 to unity, before creating a new plot of their
 //! ratio.
 TH1D* GetShapeRatio(TH1D* hist1, TH1D* hist2);
 
 //! Create a covariance histogram from a TMatrixDSym and add titles given.
 TH2D* GetCovarPlot(TMatrixDSym* cov, std::string name, std::string title);
 
 //! Wrapper function to create full covariance plot
 TH2D* GetFullCovarPlot(TMatrixDSym* cov, std::string name);
 
 //! Wrapper function to create inverted covariance plot
 TH2D* GetInvCovarPlot(TMatrixDSym* cov, std::string name);
 
 //! Wrapper function to create decomposed covariance plot
 TH2D* GetDecompCovarPlot(TMatrixDSym* cov, std::string name);
 
 //! Given a covariance histogram, divide by errors to form a correlation plot.
 TH2D* GetCorrelationPlot(TH2D* cov, std::string name);
 
 //! Given a covariance histogram, calculate the decomposed matrix to form a
 //! decomposed plot.
 TH2D* GetDecompPlot(TH2D* cov, std::string name);
 
 //! Given two 1D histograms create a 2D histogram which uses their bin edges to
 //! define both axes.
 TH2D* MergeIntoTH2D(TH1D* xhist, TH1D* yhist, std::string zname = "");
 
 //! Given a 1D Histogram, set any empty bins in Data to empty bins in MC
 void MatchEmptyBins(TH1D* data, TH1D* mc);
 
 //! Given a 2D Histogram, set any empty bins in Data to empty bins in MC
 void MatchEmptyBins(TH2D* data, TH2D* mc);
 
 //! Return a projection of a 2D Histogram onto X accounting for bin masking
 TH1D* GetProjectionX(TH2D* hist, TH2I* mask);
 
 //! Return a projection of a 2D Histogram onto Y accounting for bin masking
 TH1D* GetProjectionY(TH2D* hist, TH2I* mask);
 }
 
 /*! @} */
 #endif