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 5338a9a..c4a0b7f 100644
--- a/app/nuissmear.cxx
+++ b/app/nuissmear.cxx
@@ -1,172 +1,172 @@
 // 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 -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[-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;
   }
 
   // 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;
 }
 
 //*******************************
 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");
 
-  samplekey.AddS("name", "FlatTree");
-  samplekey.AddS("input", gOptInputFile);
-  samplekey.AddS("type", gOptType);
+  samplekey.Set("name", "FlatTree");
+  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.");
   }
   flattreecreator =
       new Smearceptance_Tester(std::string("FlatTree_") + gOptOptions,
                                gOptInputFile, FitBase::GetRW(), gOptType, "");
 
   // 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/src/FCN/SampleList.cxx b/src/FCN/SampleList.cxx
index 424dfff..f495952 100644
--- a/src/FCN/SampleList.cxx
+++ b/src/FCN/SampleList.cxx
@@ -1,1052 +1,1052 @@
 #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_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_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 "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")) {
     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 {
     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/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 b87e8a6..a139019 100644
--- a/src/FitBase/Measurement1D.cxx
+++ b/src/FitBase/Measurement1D.cxx
@@ -1,1896 +1,1896 @@
 // 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 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();
 
 
   // 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 503e687..abf98c2 100644
--- a/src/FitBase/Measurement1D.h
+++ b/src/FitBase/Measurement1D.h
@@ -1,656 +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.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 ea2e1e5..6a05dc8 100644
--- a/src/FitBase/MeasurementBase.h
+++ b/src/FitBase/MeasurementBase.h
@@ -1,357 +1,357 @@
 // 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;
 
 };
 
 
 
 
 // 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/InputHandler/FitEvent.h b/src/InputHandler/FitEvent.h
index c8916c6..033f1ce 100644
--- a/src/InputHandler/FitEvent.h
+++ b/src/InputHandler/FitEvent.h
@@ -1,613 +1,613 @@
 // 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"
 
 /// 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;
 
 
   /// 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 27340dd..3ac974f 100644
--- a/src/InputHandler/InputUtils.cxx
+++ b/src/InputHandler/InputUtils.cxx
@@ -1,169 +1,169 @@
 // 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 "GeneratorUtils.h"
 
 #include "InputUtils.h"
 #include "InputHandler.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"
                                          };
 
   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];
     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);
       break;
     }
   }
 
   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(GeneratorUtils::NEUT_TreeName.c_str()));
   if (NEUT_Input) {
     return kNEUT_Input;
   }
   TTree *NUWRO_Input =
     dynamic_cast<TTree *>(inpF->Get(GeneratorUtils::NuWro_TreeName.c_str()));
   if (NUWRO_Input) {
     return kNUWRO_Input;
   }
   TTree *GENIE_Input =
     dynamic_cast<TTree *>(inpF->Get(GeneratorUtils::GENIE_TreeName.c_str()));
   if (GENIE_Input) {
     return kGENIE_Input;
   }
   TTree *GiBUU_Input =
     dynamic_cast<TTree *>(inpF->Get(GeneratorUtils::GiBUU_TreeName.c_str()));
   if (GiBUU_Input) {
     return kGiBUU_Input;
   }
 */
   return kInvalid_Input;
 }
 
 std::string PrependGuessedInputTypeToName(std::string const &inpFName) {
   TFile *inpF = TFile::Open(inpFName.c_str(), "READ");
   if (!inpF || !inpF->IsOpen()) {
     ERR(FTL) << "Couldn't open \"" << inpFName << "\" for reading."
              << std::endl;
     throw;
   }
   InputType iType = GuessInputTypeFromFile(inpF);
   if (iType == kInvalid_Input) {
     ERR(FTL) << "Couldn't determine input type from file: " << inpFName
              << "." << std::endl;
     throw;
   }
   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/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/Reweight/MINERvAWeightCalcs.h b/src/Reweight/MINERvAWeightCalcs.h
index 540795a..629b6ec 100644
--- a/src/Reweight/MINERvAWeightCalcs.h
+++ b/src/Reweight/MINERvAWeightCalcs.h
@@ -1,148 +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"
 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];
 };
 
 };  // namespace reweight
 };  // namespace nuisance
 
 #endif // __GENIE_ENABLED__
 #endif //__MINERVA_RW_ENABLED__
 
 #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/Routines/BayesianRoutines.cxx b/src/Routines/BayesianRoutines.cxx
index 05bfa3f..88b2e0a 100755
--- a/src/Routines/BayesianRoutines.cxx
+++ b/src/Routines/BayesianRoutines.cxx
@@ -1,524 +1,519 @@
 // 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 "BayesianRoutines.h"
 
 void BayesianRoutines::Init() {
 
   fInputFile = "";
   fInputRootFile = NULL;
 
   fOutputFile = "";
   fOutputRootFile = NULL;
 
   fStrategy = "BayesianThrows";
   fRoutines.clear();
   fRoutines.push_back("BayesianThrows");
 
   fCardFile = "";
 
   fFakeDataInput = "";
 
   fSampleFCN    = NULL;
 
   fAllowedRoutines = ("f");
 
 };
 
 BayesianRoutines::~BayesianRoutines() {
 };
 
 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, "-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
   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();
 
   SetupRWEngine();
   SetupFCN();
 
   return;
 };
 
 void BayesianRoutines::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;
   }
 }
 
 /*
   Setup Functions
 */
 //*************************************
 void BayesianRoutines::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 BayesianRoutines::SetupFCN() {
 //*************************************
 
   LOG(FIT) << "Making the jointFCN" << std::endl;
   if (fSampleFCN) delete fSampleFCN;
   fSampleFCN = new JointFCN(fOutputRootFile);
 
   fInputThrows = fSampleFCN->GetPullList();
 
   return;
 }
 
 /*
   Fitting Functions
 */
 //*************************************
 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 BayesianRoutines::ThrowParameters() {
 //*************************************
 
   // 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();
 
   }
 
   // Now update Parameters
   UpdateRWEngine(fThrownVals);
 
   // Update Pulls
   for (PullListConstIter iter = fInputThrows.begin();
        iter != fInputThrows.end(); iter++) {
     ParamPull* pull = *iter;
     pull->Reconfigure();
   }
 
   return;
 };
 
 //*************************************
 void BayesianRoutines::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);
     LOG(FIT) << "Running Routine: " << routine << std::endl;
 
     if (!routine.compare("BayesianThrows")) GenerateThrows();
     else THROW("UNKNOWN ROUTINE " << routine);
   }
 
   return;
 }
 
 //*************************************
 void BayesianRoutines::GenerateThrows() {
 //*************************************
 
   // 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();
 
   // 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];
   }
 
   likenames .clear();
   likevals  .clear();
   likendof  .clear();
 
   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() );
   }
 
   // Run Throws and save
   for (Int_t i = 0; i < nthrows; i++) {
 
     // Skip the start throw
     if (i == 0) continue;
     LOG(FIT) << "Throw " << i << " ================================" << std::endl;
 
     // Throw Parameters
     ThrowParameters();
     FitBase::GetRW()->Print();
 
     // 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/BayesianRoutines.h b/src/Routines/BayesianRoutines.h
index 3e56888..777e716 100755
--- a/src/Routines/BayesianRoutines.h
+++ b/src/Routines/BayesianRoutines.h
@@ -1,183 +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 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 "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 BayesianRoutines{
 //*************************************
 
 public:
 
   /*
     Constructor/Destructor
   */
 
   //! Constructor reads in arguments given at the command line for the fit here.
   BayesianRoutines(int argc, char* argv[]);
     
   //! Default destructor
   ~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
   */
   void SetupSystematicsFromXML();
 
   //! Setups up our custom RW engine with all the parameters passed in the card file
   void SetupRWEngine();
 
   //! 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);
 
   //! Given a single routine (see tutorial for options) run that fit routine now.
   int RunFitRoutine(std::string routine);
 
   //! 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;
 
   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;
 
 
   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/Routines/ComparisonRoutines.cxx b/src/Routines/ComparisonRoutines.cxx
index c5463c0..4e25ed9 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;
   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 9d1dc26..d0ca6df 100755
--- a/src/Routines/MinimizerRoutines.cxx
+++ b/src/Routines/MinimizerRoutines.cxx
@@ -1,1510 +1,1505 @@
 // 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"
 
 /*
   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");
 };
 
 //*************************************
 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  = "";
 
   // 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 = "";   }
 
   // make minimizer
   if (fMinimizer) delete fMinimizer;
   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")) {
 
     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/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 f991df5..dd13fda 100755
--- a/src/Routines/SystematicRoutines.cxx
+++ b/src/Routines/SystematicRoutines.cxx
@@ -1,1527 +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;
 
   // 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 5ac1a40..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/Tests/ParserTests.cxx b/src/Tests/ParserTests.cxx
index 236eed3..a02688a 100644
--- a/src/Tests/ParserTests.cxx
+++ b/src/Tests/ParserTests.cxx
@@ -1,100 +1,102 @@
 #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;
 
-  FitPar::Config().ForceParam("NEUT_DIR=/var/test/NEUT");
-  FitPar::Config().ForceParam("NUWRO_DIR=/var/test/NUWRO");
-  FitPar::Config().ForceParam("GENIE_DIR=/var/test/GENIE");
-  FitPar::Config().ForceParam("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]);
 
-  FitPar::Config().ForceParam("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..2ac8c01 100644
--- a/src/Utils/CMakeLists.txt
+++ b/src/Utils/CMakeLists.txt
@@ -1,93 +1,91 @@
 # 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})
 
 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)
diff --git a/src/Utils/FitLogger.h b/src/Utils/FitLogger.h
index 6817bac..0f03a5d 100644
--- a/src/Utils/FitLogger.h
+++ b/src/Utils/FitLogger.h
@@ -1,207 +1,207 @@
 // 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 <iosfwd>
 #include <iostream>
 #include <fstream>
 #include <sstream>
 #include "Initialiser.h"
-#include "FitParameters.h"
+
 #include "TRandom3.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__) << "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/FitParameters.cxx b/src/Utils/FitParameters.cxx
deleted file mode 100644
index 5fd01e2..0000000
--- a/src/Utils/FitParameters.cxx
+++ /dev/null
@@ -1,231 +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());
-
-  // LOG(REC) << "Read in Parameter Override : " << parName << " = " << parEntry
-  // << std::endl;
-
-  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/GeneralUtils.h b/src/Utils/GeneralUtils.h
index 3139b52..8bcda5c 100644
--- a/src/Utils/GeneralUtils.h
+++ b/src/Utils/GeneralUtils.h
@@ -1,132 +1,131 @@
 // 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 GENERALUTILS_H_SEEN
 #define GENERALUTILS_H_SEEN
 
 #include <math.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <cstring>
 #include <fstream>
 #include <iostream>
 #include <iostream>
 #include <numeric>
 #include <limits>
 #include <sstream>
 #include <string>
 #include <vector>
-#include "FitLogger.h"
 #include "PhysConst.h"
 
 /*!
  *  \addtogroup Utils
  *  @{
  */
 
 /// Functions which deal with basic string and file handling. They should have
 /// no dependence on the other NUISANCE files!
 namespace GeneralUtils {
 
 /*!
   String handling and file parsing functions
 */
 
 /// Parse a string into a vector of doubles given a delimiter "del"
 std::vector<double> ParseToDbl(std::string str, const char* del);
 
 /// Parse a string into a vector of ints given a delimiter "del"
 std::vector<int> ParseToInt(std::string str, const char* del);
 
 /// Parse a string into a vector of strings given a delimiter "del"
 std::vector<std::string> ParseToStr(std::string str, const char* del);
 
 /// Parse text file into a vector of strings 
 std::vector<std::string> ParseFileToStr(std::string str, const char* del);
 
 /// Convert a string to a double
 double StrToDbl(std::string str);
 
 /// Convert a string to an int
 int StrToInt(std::string str);
 
 /// Convert a string to an bool
 bool StrToBool(std::string str);
 
 /// Convert a bool to string
 std::string BoolToStr(bool val);
 
 /// Convert Int to string
 std::string IntToStr(int val);
 
 /// Convert Double to String
 std::string DblToStr(double val);
 
 /// Return the top level environmental variable for the fitter
 std::string GetTopLevelDir();
 
 // /// A utility function to return a std::vector from an array
 // template <typename T, size_t N>
 // std::vector<T> makeVector(const T (&data)[N]) {
 //   return std::vector<T>(data, data + N);
 // }
 std::vector<std::string> LoadCharToVectStr(int argc, char* argv[]);
 
 
 template <typename T, size_t N>
 size_t GetArraySize(const T (&data)[N]) {
   return N;
 }
 template <typename T>
 size_t GetHammingWeight(T const& d) {
   T c = d;
   size_t w = 0;
   while (bool(c)) {
     w += c & 1;
     c = (c >> 1);
   }
   return w;
 }
 
 template <typename T>
 size_t GetFirstOnBit(T const& d) {
   T c = d;
   size_t fob = 0;
   while (bool(c)) {
     if (c & 1) {
       return fob;
     } else {
       c = (c >> 1);
     }
     fob++;
   }
   return fob;
 }
 
 template <typename T>
 size_t IsSmallNum(T const& d) {
   if (std::numeric_limits<T>::is_integer) {
     return (d == 0);
   }
   return (((d > 0) && (d < std::numeric_limits<T>::epsilon())) ||
           ((d < 0) && (d > -std::numeric_limits<T>::epsilon())));
 }
 }
 
 /*! @} */
 #endif
diff --git a/src/Utils/NuisConfig.cxx b/src/Utils/NuisConfig.cxx
index db5aabb..a44a325 100644
--- a/src/Utils/NuisConfig.cxx
+++ b/src/Utils/NuisConfig.cxx
@@ -1,831 +1,786 @@
 // 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));
+#include "TXMLEngine.h"
+#include "GeneralUtils.h"
+#include "FitLogger.h"
+#include "GeneralUtils.h"
 
-  // Setup Main XML Node
-  fMainNode = fXML->DocGetRootElement(fXMLDocs[0]);
-  // RemoveIdenticalNodes();
+namespace Config {
+nuisconfig& Get() { return nuisconfig::GetConfig(); };
 
-  std::cout << " -> DONE." << std::endl;
+std::string GetPar(std::string name) {
+  return Get().GetConfig(name);
 }
-
-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;
+int GetParI(std::string name) {
+  return Get().GetConfigI(name);
 }
-
-void nuisconfig::OverrideConfig(std::string conf) {
-  std::vector<std::string> opts = GeneralUtils::ParseToStr(conf, "=");
-  SetConfS(opts[0], opts[1]);
+bool GetParB(std::string name) {
+  return Get().GetConfigB(name);
 }
-
-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;
+double GetParD(std::string name) {
+  return Get().GetConfigD(name);
 }
-
-/// 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;
+void SetPar(std::string name, std::string val) {
+  Get().SetConfig(name, 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;
+void SetPar(std::string name, bool val) {
+  Get().SetConfig(name, 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;
+void SetPar(std::string name, int val) {
+  Get().SetConfig(name, val);
+}
+void SetPar(std::string name, float val) {
+  Get().SetConfig(name, val);
+}
+void SetPar(std::string name, double val) {
+  Get().SetConfig(name, 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";
+nuisconfig* nuisconfig::m_nuisconfigInstance = NULL;
+nuisconfig& nuisconfig::GetConfig(void) {
+  if (!m_nuisconfigInstance) m_nuisconfigInstance = new nuisconfig;
+  return *m_nuisconfigInstance;
+};
 
-  // Name
-  xmlline += " name=\"" + parsed[0] + "\"";
 
-  // Nominal
-  xmlline += " nominal=\"" + parsed[1] + "\"";
 
-  // State
-  xmlline += " state=\"" + parsed[2] + "\"";
+// Main Class Definition
+nuisconfig::nuisconfig() {
 
-  return "<" + xmlline + "/>";
-}
+  // Load default Parameters
+  std::string filename = (GeneralUtils::GetTopLevelDir() +
+                          "/parameters/config.xml");
+  std::cout << "[ NUISANCE ]: Loading DEFAULT settings from : " << filename;
 
-std::string nuisconfig::ConvertSampleLineToXML(std::string line) {
-  // Parse
-  std::vector<std::string> parsed = GeneralUtils::ParseToStr(line, " ");
+  // Create XML Engine
+  fXML = new TXMLEngine;
+  fXML->SetSkipComments(true);
 
-  // Min limits
-  if (parsed.size() < 2) {
-    ERR(FTL) << "Insufficient sample options" << std::endl;
+  // Load in documents
+  fXMLDocs.push_back(fXML->ParseFile(filename.c_str(), 1000000));
+  if (!fXMLDocs[0]) {
+    THROW("Cannot Read Parameters File!");
   }
 
-  // Setup XMLLine
-  std::string xmlline = "sample";
+  // Setup Main XML Node to be the first file read
+  fMainNode = fXML->DocGetRootElement(fXMLDocs[0]);
 
-  // Name
-  xmlline += " name=\"" + parsed[1] + "\"";
+  // Print result
+  std::cout << " -> DONE." << std::endl;
+}
 
-  // InputFile
-  xmlline += " input=\"" + parsed[2] + "\"";
+nuisconfig::~nuisconfig() {
+  // Should really delete XML objects here but we don't
+}
 
-  // If option add it
-  if (parsed.size() > 3) {
-    xmlline += " state=\"" + parsed[3] + "\"";
-  }
+void nuisconfig::LoadSettings(std::string filename, std::string state) {
 
-  // If norm add it
-  if (parsed.size() > 4) {
-    xmlline += " norm=\"" + parsed[4] + "\"";
-  }
+  // 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);
 
-  return "<" + xmlline + "/>";
+    // Otherwise its an old simple card file
+  } else {
+    std::cout << " -> Assuming its a simple card file." << std::endl;
+    LoadCardSettings(filename, state);
+  }
 }
 
-void nuisconfig::AddXMLLine(std::string line) {
-  // XMLLine
-  std::string xmlline = "";
+void nuisconfig::LoadXMLSettings(std::string filename, std::string state = "") {
+  std::cout << "[ NUISANCE ]: Loading XML settings from : " << filename;
 
-  // If = in it its not an xml
-  if (line.find("=") != std::string::npos) {
-    xmlline = "<" + line + "/>";
+  // Here we manually load all the children from the card file into our root node
 
-    // 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);
-    }
+  // Add new file to xml docs list
+  XMLNodePointer_t docroot = fXML->ParseFile(filename.c_str(), 1000000);
+  if (!docroot) {
+    THROW("Cannot open XML settings file");
   }
 
-  // Ad the line
-  std::cout << "[ NUISANCE ]: Adding XMLLine in nuisconfig: '" << xmlline
-            << "'";
+  // Save to doc list
+  fXMLDocs.push_back(fXML->ParseFile(filename.c_str(), 1000000));
 
-  // Make XML Structure
-  fXMLDocs.push_back(fXML->ParseString(xmlline.c_str()));
+  // Loop over children in the new document
+  XMLNodePointer_t child = fXML->GetChild(docroot);
+  while (child != 0) {
 
-  int nxml = fXMLDocs.size();
-  XMLNodePointer_t newdocroot = fXML->DocGetRootElement(fXMLDocs[nxml - 1]);
-  fXML->AddChild(fMainNode, newdocroot);
+    // SPECIAL CONFIG CASE
+    // If its a config node, then remove previous attributes, overriding old value
+    if (!std::string(fXML->GetNodeName(child)).compare("config")) {
 
-  std::cout << " -> DONE." << std::endl;
-}
+      // Loop over attribues
+      XMLAttrPointer_t attr1 = fXML->GetFirstAttr(child);
+      while (attr1 != 0) {
 
-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;
-}
+        // If a valid attribute name is given then compare
+        if (!GetConfigS(fXML->GetAttrName(attr1)).empty()) {
 
-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 full list of present configs
+          std::vector<XMLNodePointer_t> confignodes = GetNodes("config");
 
-  // Get New Doc ROOT
-  int nxml = fXMLDocs.size();
-  XMLNodePointer_t newdocroot = fXML->DocGetRootElement(fXMLDocs[nxml - 1]);
+          // Loop over present configs and compare
+          for (size_t i = 0; i < confignodes.size(); i++) {
 
-  // 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;
-              }
+            // 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;
             }
           }
-          attr1 = fXML->GetNextAttr(attr1);
         }
+
+        // Move onto next config attribute
+        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();
+void nuisconfig::LoadCardSettings(std::string filename, std::string state) {
+  std::cout << "[ NUISANCE ]: Loading simple config from : " << filename;
 
-  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
+  // Build XML Config from the card file by parsing each line
   std::vector<std::string> cardlines =
-      GeneralUtils::ParseFileToStr(filename, "\n");
+    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
-    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());
-}
+    // Sample structure
+    if (!id.compare("sample")) {
+      CreateSampleNodeFromLine(line);
+    }
 
-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;
-  }
+    // Any parameter structure
+    if (id.find("_parameter") != std::string::npos) {
+      CreateParameterNodeFromLine(line);
+    }
 
-  // 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;
+    // Any covar structure
+    if (!id.compare("covar") || !id.compare("pull") || !id.compare("throw")) {
+      CreatePullNodeFromLine(line);
     }
 
-    // Reset counter
-    fConfigCallCount[name] = 0;
+    // Any config structure
+    if (!id.compare("config")) {
+      CreateOldConfigNodeFromLine(line);
+    }
   }
-
-  // Add to Call Count
-  fConfigCallCount[name] += 1;
+  std::cout << " -> DONE." << std::endl;
 }
 
-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);
-        }
+XMLNodePointer_t nuisconfig::CreateSampleNodeFromLine(const std::string line) {
 
-        // Get Next Attribute
-        attr = fXML->GetNextAttr(attr);
-      }
-    }
+  // Create new node entry
+  XMLNodePointer_t samplenode = CreateNode("sample");
 
-    // Next Child
-    child = fXML->GetNext(child);
-  }
+  // Parse line
+  std::vector<std::string> strvct = GeneralUtils::ParseToStr(line, " ");
 
-  // Return Config Value
-  return temp;
-}
+  // 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]);
 
-bool nuisconfig::ConfB(const std::string name) {
-  std::string pars = ConfS(name);
-  return GeneralUtils::StrToBool(pars);
+  return samplenode;
 }
 
-int nuisconfig::ConfI(const std::string name) {
-  std::string pars = ConfS(name);
-  return GeneralUtils::StrToInt(pars);
-}
+XMLNodePointer_t nuisconfig::CreateParameterNodeFromLine(const std::string line) {
 
-double nuisconfig::ConfD(const std::string name) {
-  std::string pars = ConfS(name);
-  return GeneralUtils::StrToDbl(pars);
-}
+  // Create new node entry
+  XMLNodePointer_t parnode = CreateNode("parameter");
 
-std::vector<XMLNodePointer_t> nuisconfig::GetChildNodes(
-    XMLNodePointer_t node, const std::string type) {
-  std::vector<XMLNodePointer_t> nodelist;
+  // Parse line
+  std::vector<std::string> strvct = GeneralUtils::ParseToStr(line, " ");
 
-  /// 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);
-    }
+  // 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]);
 
-    // Next child
-    child = fXML->GetNext(child);
-  }
+  // 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]);
 
-  // return list
-  return nodelist;
-}
+    // Fixed param structure
+  } else if (strvct.size() == 3) {
+    Set(parnode, "state", "FIX");
+  } else if (strvct.size() == 4) {
+    Set(parnode, "state", strvct[3]);
+  }
 
-std::vector<XMLNodePointer_t> nuisconfig::GetNodes(const std::string type) {
-  return GetChildNodes(fMainNode, type);
+  return parnode;
 }
 
-/// 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;
-    }
-  }
+XMLNodePointer_t nuisconfig::CreatePullNodeFromLine(const std::string line) {
 
-  if (!fXML) {
-    std::cout << "AAAAH NO XML" << std::endl;
-    throw;
-  }
+  // Create new node entry
+  XMLNodePointer_t parnode = CreateNode("covar");
 
-  // 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 {
-    }
+  // Parse line
+  std::vector<std::string> strvct = GeneralUtils::ParseToStr(line, " ");
 
-    // Next Attribute
-    attr = fXML->GetNextAttr(attr);
-  }
+  // 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 temp;
+  return parnode;
 }
 
-bool nuisconfig::Has(XMLNodePointer_t node, std::string name) {
-  // If node empty return empty
-  if (node == 0) return false;
+XMLNodePointer_t nuisconfig::CreateOldConfigNodeFromLine(const std::string line) {
 
-  // Get Attribute from child with name
-  SXmlNode_t* snode = (SXmlNode_t*)node;
-  // SXmlAttr_t* sattr = snode->fAttr;
+  // Create new node entry
+  XMLNodePointer_t confignode = CreateNode("config");
 
-  XMLAttrPointer_t attr = fXML->GetFirstAttr(node);
+  // Parse line
+  std::vector<std::string> strvct = GeneralUtils::ParseToStr(line, " ");
 
-  bool found = false;
+  // Add line elements to the node
+  // name value
+  if (strvct.size() > 2) Set(confignode, strvct[1], strvct[2]);
 
-  // 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;
-    }
-  }
+  return confignode;
+}
 
-  // 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 {
-    }
+void nuisconfig::FinaliseSettings(std::string name) {
+  std::cout << "[ NUISANCE ]: Finalising run settings";
 
-    // Next Attribute
-    attr = fXML->GetNextAttr(attr);
-  }
+  // Save full config to file
+  RemoveEmptyNodes();
+  RemoveIdenticalNodes();
+  WriteSettings(name);
 
-  return found;
+  std::cout << " -> DONE." << std::endl;
 }
 
-/// 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);
-}
+void nuisconfig::WriteSettings(std::string outputname) {
 
-/// Get int from given node
-int nuisconfig::GetI(XMLNodePointer_t node, std::string name) {
-  std::string tempattr = GetS(node, name);
-  return GeneralUtils::StrToInt(tempattr);
-}
+  // Create a New XML Doc
+  XMLDocPointer_t newxmldoc = fXML->NewDoc();
+  fXML->DocSetRootElement(newxmldoc, fMainNode);
 
-/// Get double from given node
-double nuisconfig::GetD(XMLNodePointer_t node, std::string name) {
-  std::string tempattr = GetS(node, name);
-  return GeneralUtils::StrToDbl(tempattr);
-}
+  // Save document to file
+  if (GetConfigB("SaveParsedXMLFile")) {
+    fXML->SaveDoc(newxmldoc, outputname.c_str());
+  }
 
-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));
+XMLNodePointer_t nuisconfig::CreateNode(std::string name) {
+  return fXML->NewChild(fMainNode, 0, name.c_str());
 }
 
-void nuisconfig::AddI(XMLNodePointer_t node, std::string name, int val) {
-  AddS(node, name, GeneralUtils::IntToStr(val));
+XMLNodePointer_t nuisconfig::CreateNode(XMLNodePointer_t node, std::string name) {
+  return fXML->NewChild(node, 0, name.c_str());
 }
-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);
-}
+XMLNodePointer_t nuisconfig::GetNode(XMLNodePointer_t node, std::string type) {
 
-void nuisconfig::SetB(XMLNodePointer_t node, std::string name, bool val) {
-  SetS(node, name, GeneralUtils::BoolToStr(val));
-}
+  /// Loop over all children
+  XMLNodePointer_t child = fXML->GetChild(node);
+  while (child != 0) {
 
-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));
-}
+    /// Get nodes for given type (if type empty return all)
+    if (std::string(fXML->GetNodeName(child)) == type.c_str() or type.empty()) {
+      return child;
+    }
 
-void nuisconfig::ChangeS(XMLNodePointer_t node, std::string name,
-                         std::string val) {
-  if (!fXML->HasAttr(node, name.c_str())) return;
-  SetS(node, name, val);
-}
+    // Next child
+    child = fXML->GetNext(child);
+  }
 
-void nuisconfig::ChangeB(XMLNodePointer_t node, std::string name, bool val) {
-  ChangeS(node, name, GeneralUtils::BoolToStr(val));
+  // Child not found
+  return 0;
 }
 
-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;
+XMLNodePointer_t nuisconfig::GetNode(std::string type) {
+  return GetNode(fMainNode, type);
+}
+
+std::vector<XMLNodePointer_t> nuisconfig::GetNodes(XMLNodePointer_t node,
+    std::string type) {
+
+  // Create new vector for nodes
+  std::vector<XMLNodePointer_t> nodelist;
+
+  /// Loop over all children
+  XMLNodePointer_t child = fXML->GetChild(node);
+  while (child != 0) {
 
-  for (size_t i = 0; i < alltags.size(); i++) {
-    if (!Has(alltags[i], name)) continue;
-    tagval = GetS(alltags[i], name);
-    tagfound = true;
+    /// 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);
   }
 
-  if (!tagfound) {
-    ERR(FTL) << "Cannot find tag " << name << " in global conig!" << std::endl;
-    throw;
+  // return list
+  return nodelist;
+}
+
+std::vector<XMLNodePointer_t> nuisconfig::GetNodes(std::string type) {
+  return GetNodes(fMainNode, type);
+}
+
+void nuisconfig::Set(XMLNodePointer_t node, std::string name, std::string val) {
+
+  // Remove and re-add attribute
+  if (fXML->HasAttr(node, name.c_str())) {
+    fXML->FreeAttr(node, name.c_str());
   }
 
-  return tagval;
-};
+  fXML->NewAttr(node, 0, name.c_str(), val.c_str());
+}
 
-void nuisconfig::ExpandAllTags() {
-  return;
-  /*
-  // Loop over children and look for name
-  XMLNodePointer_t child = fXML->GetChild(fMainNode);
-  while (child != 0) {
+void nuisconfig::Set(XMLNodePointer_t node, std::string name, bool val) {
+  Set(node, name, GeneralUtils::BoolToStr(val));
+}
+
+void nuisconfig::Set(XMLNodePointer_t node, std::string name, int val) {
+  Set(node, name, GeneralUtils::IntToStr(val));
+}
 
-    // Loop over attributes and search for tags
-    XMLAttrPointer_t attr = fXML->GetFirstAttr(child);
-    while ( attr != 0 ) {
+void nuisconfig::Set(XMLNodePointer_t node, std::string name, float val) {
+  Set(node, name, GeneralUtils::DblToStr(val));
+}
 
-      // Search attribute value for <>
-      std::string attrval = std::string(fXML->GetAttrValue(attr));
-      std::string attrname = std::string(fXML->GetAttrName(attr));
+void nuisconfig::Set(XMLNodePointer_t node, std::string name, double val) {
+  Set(node, name, GeneralUtils::DblToStr(val));
+}
 
-      // Search for <>
-      while (attrval.find("<") != std::string::npos and
-             attrval.find(">") != std::string::npos){
+void nuisconfig::SetS(XMLNodePointer_t node, std::string name, std::string val) {
+  Set(node, name, val);
+}
 
-        size_t startdel = 0;
-        size_t enddel = 0;
-        std::string replacestring = "";
+void nuisconfig::SetB(XMLNodePointer_t node, std::string name, bool val) {
+  Set(node, name, GeneralUtils::BoolToStr(val));
+}
 
-        for (size_t i = 0; i < attrval.size(); i++){
+void nuisconfig::SetI(XMLNodePointer_t node, std::string name, int val) {
+  Set(node, name, GeneralUtils::IntToStr(val));
+}
 
-          if (attrval[i] == '<'){
-            replacestring = "";
-            startdel = i;
-          }
+void nuisconfig::SetF(XMLNodePointer_t node, std::string name, float val) {
+  Set(node, name, GeneralUtils::DblToStr(val));
+}
 
-          replacestring.push_back(attrval[i]);
+void nuisconfig::SetD(XMLNodePointer_t node, std::string name, double val) {
+  Set(node, name, GeneralUtils::DblToStr(val));
+}
 
-          if (attrval[i] == '>'){
-            enddel = i;
-            break;
-          }
-        }
+bool nuisconfig::Has(XMLNodePointer_t node, std::string name) {
 
-        attrval.replace(startdel, replacestring, GetTag(replacestring) );
-      }
+  // If node empty return empty
+  if (node == 0) return false;
+
+  // Search attributes
+  XMLAttrPointer_t attr = fXML->GetFirstAttr(node);
+  bool found = false;
 
-      fXML->FreeAttr(child, attr);
-      attr = fXML->NewAttr(child, attr, attrname.c_str(), attrval.c_str());
+  // Loop over all attributes
+  while (attr != 0) {
 
-      // Get Next Attribute
-      attr = fXML->GetNextAttr(attr);
+    // Find value of correct name
+    if (std::string(fXML->GetAttrName(attr)) == name.c_str()) {
+      found = true;
+      break;
     }
-    child = fXML->GetNext(child);
+
+    // Next Attribute
+    attr = fXML->GetNextAttr(attr);
   }
-  */
-};
+
+  return found;
+}
+
+std::string nuisconfig::Get(XMLNodePointer_t node, std::string 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 name) {
+  return Get(node, name);
+}
+
+bool nuisconfig::GetB(XMLNodePointer_t node, std::string name) {
+  std::string tempattr = Get(node, name);
+  return GeneralUtils::StrToBool(tempattr);
+}
+
+int nuisconfig::GetI(XMLNodePointer_t node, std::string name) {
+  std::string tempattr = Get(node, name);
+  return GeneralUtils::StrToInt(tempattr);
+}
+
+float nuisconfig::GetF(XMLNodePointer_t node, std::string name) {
+  std::string tempattr = Get(node, name);
+  return GeneralUtils::StrToDbl(tempattr);
+}
+
+double nuisconfig::GetD(XMLNodePointer_t node, std::string name) {
+  std::string tempattr = Get(node, name);
+  return GeneralUtils::StrToDbl(tempattr);
+}
+
+std::vector<std::string> nuisconfig::GetVS(XMLNodePointer_t node,
+    std::string 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 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 name,
+                                      const char* 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)));
-      //      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;
 }
+
+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;
+}
+
+void nuisconfig::SetConfig(std::string name, std::string val) {
+  XMLNodePointer_t node = GetConfigNode(name);
+  if (!node) node = CreateNode("config");
+  Set(node, name, val);
+}
+
+void nuisconfig::SetConfig(std::string name, bool val) {
+  XMLNodePointer_t node = GetConfigNode(name);
+  if (!node) node = CreateNode("config");
+  Set(node, name, val);
+}
+
+void nuisconfig::SetConfig(std::string name, int val) {
+  XMLNodePointer_t node = GetConfigNode(name);
+  if (!node) node = CreateNode("config");
+  Set(node, name, val);
+}
+
+void nuisconfig::SetConfig(std::string name, float val) {
+  XMLNodePointer_t node = GetConfigNode(name);
+  if (!node) node = CreateNode("config");
+  Set(node, name, val);
+}
+
+void nuisconfig::SetConfig(std::string name, double val) {
+  XMLNodePointer_t node = GetConfigNode(name);
+  if (!node) node = CreateNode("config");
+  Set(node, name, val);
+}
+
+void nuisconfig::OverrideConfig(std::string conf) {
+  std::vector<std::string> opts = GeneralUtils::ParseToStr(conf, "=");
+  SetConfig(opts[0], opts[1]);
+}
+
+std::string nuisconfig::GetConfig(std::string 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;
+}
+
+std::string nuisconfig::GetConfigS(const std::string name) {
+  return GetConfig(name);
+}
+
+bool nuisconfig::GetConfigB(const std::string name) {
+  std::string pars = GetConfig(name);
+  return GeneralUtils::StrToBool(pars);
+}
+
+int nuisconfig::GetConfigI(const std::string name) {
+  std::string pars = GetConfig(name);
+  return GeneralUtils::StrToInt(pars);
+}
+
+float nuisconfig::GetConfigF(const std::string name) {
+  std::string pars = GetConfig(name);
+  return GeneralUtils::StrToDbl(pars);
+}
+
+double nuisconfig::GetConfigD(const std::string name) {
+  std::string pars = GetConfig(name);
+  return GeneralUtils::StrToDbl(pars);
+}
+
+
+std::string nuisconfig::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;
+};
+
+
+
+
+
+namespace FitPar {
+  std::string GetDataBase() { return GeneralUtils::GetTopLevelDir() + "/data/"; };
+  nuisconfig& Config()  { return Config::Get(); };
+}
+
+
diff --git a/src/Utils/NuisConfig.h b/src/Utils/NuisConfig.h
index bbeea91..bd2cf9b 100644
--- a/src/Utils/NuisConfig.h
+++ b/src/Utils/NuisConfig.h
@@ -1,184 +1,202 @@
 // 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"
+#include "TFile.h"
+
 
-// New NUISANCE Config Class
+// 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 LoadConfig(std::string filename, std::string state);
+  void LoadSettings(std::string filename, std::string state);
 
   /// Adds a new config from new xml file format
-  void LoadXMLConfig(std::string filename, std::string state);
+  void LoadXMLSettings(std::string filename, std::string state);
 
   /// Adds a new config from old card file format
-  void LoadCardConfig(std::string filename, std::string state);
+  void LoadCardSettings(std::string filename, std::string state);
 
   /// Save the config to file
-  void WriteConfig(std::string filename);
+  void WriteSettings(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);
+  void RemoveEmptyNodes();
+  void RemoveIdenticalNodes();
 
-  /// 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);
+  void OverrideConfig(std::string conf);
 
-  // Set config
-  std::string ConfS(const std::string name);
+  XMLNodePointer_t GetConfigNode(std::string name);
+  XMLNodePointer_t CreateNode(XMLNodePointer_t node, std::string name);
 
-  /// Get Config Bool
-  bool ConfB(const std::string name);
+  /// Request a string config key
+  void SetConfig(std::string name, std::string val);
+  void SetConfig(std::string name, bool val);
+  void SetConfig(std::string name, int val);
+  void SetConfig(std::string name, float val);
+  void SetConfig(std::string name, double val);
 
-  /// Get Config Int
-  int ConfI(const std::string name);
+  void SetParS(std::string name, std::string val);
+  void SetParB(std::string name, bool val);
+  void SetParI(std::string name, int val);
+  void SetParD(std::string name, double val);
 
-  /// Get Config Double
-  double ConfD(const std::string name);
+  // Set config
+  std::string GetConfig(const std::string name);
+  std::string GetConfigS(const std::string name);
+  bool GetConfigB(const std::string name);
+  int GetConfigI(const std::string name);
+  float GetConfigF(const std::string name);
+  double GetConfigD(const std::string name);
+
+  std::string GetPar(const std::string name) { return GetConfig(name); };
+  std::string GetParS(const std::string name){ return GetConfigS(name); };
+  bool GetParB(const std::string name){ return GetConfigB(name); };
+  int GetParI(const std::string name){ return GetConfigI(name); };
+  double GetParD(const std::string name){return GetConfigD(name); };
+
+XMLNodePointer_t CreateSampleNodeFromLine(const std::string line);
+XMLNodePointer_t CreateParameterNodeFromLine(const std::string line);
+XMLNodePointer_t CreatePullNodeFromLine(const std::string line);
+XMLNodePointer_t CreateOldConfigNodeFromLine(const std::string line);
 
   /// 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 = "");
+  std::vector<XMLNodePointer_t> GetNodes(XMLNodePointer_t node, std::string type = "");
+
+  XMLNodePointer_t GetNode(std::string type = "");
+  XMLNodePointer_t GetNode(XMLNodePointer_t node, std::string type = "");
 
   /// Get String from a given node
+  std::string Get(XMLNodePointer_t node, std::string name);
   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
+  float GetF(XMLNodePointer_t node, std::string name);
   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);
+  void FinaliseSettings(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 Set(XMLNodePointer_t node, std::string name, std::string val);
+  void Set(XMLNodePointer_t node, std::string name, bool val);
+  void Set(XMLNodePointer_t node, std::string name, int val);
+  void Set(XMLNodePointer_t node, std::string name, float val);
+  void Set(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 SetF(XMLNodePointer_t node, std::string name, float 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();
+
+  std::string GetParDIR(std::string 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
 
   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();
+
+std::string GetPar(std::string name);
+std::string GetParS(std::string name);
+int GetParI(std::string name);
+bool GetParB(std::string name);
+double GetParD(std::string name);
+
+void SetPar(std::string name, std::string val);
+void SetPar(std::string name, bool val);
+void SetPar(std::string name, int val);
+void SetPar(std::string name, float val);
+void SetPar(std::string name, double val);
+
+}
+
+namespace FitPar {
+  nuisconfig& Config();
+  std::string GetDataBase();
+
 }
 
 /*! @} */
 #endif
diff --git a/src/Utils/NuisKey.cxx b/src/Utils/NuisKey.cxx
index c4d857e..e0f824a 100644
--- a/src/Utils/NuisKey.cxx
+++ b/src/Utils/NuisKey.cxx
@@ -1,201 +1,132 @@
 #include "NuisKey.h"
 
+nuiskey::nuiskey(std::string name){
+  fNode = Config::Get().CreateNode(name);
+}
+
 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); };
+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);
 };
 
+void nuiskey::Set(std::string name, std::string newval) {
+  Config::Get().SetS(fNode, name, newval);
+}
+void nuiskey::Set(std::string name, int newval) {
+  Config::Get().SetI(fNode, name, newval);
+}
+void nuiskey::Set(std::string name, double newval) {
+  Config::Get().SetD(fNode, name, newval);
+}
+void nuiskey::Set(std::string name, bool newval) {
+  Config::Get().SetB(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);
+}
+
+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 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
index 606d3be..9ff766f 100644
--- a/src/Utils/NuisKey.h
+++ b/src/Utils/NuisKey.h
@@ -1,70 +1,62 @@
 #ifndef NUISKEY_H
 #define NUISKEY_H
 
 #include <vector>
 
 #include "NuisConfig.h"
 
 class nuiskey {
  public:
   nuiskey(){};
 
   nuiskey(XMLNodePointer_t node) { fNode = node; };
+  nuiskey(std::string name);
 
   ~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);
+  void Set(std::string name, std::string newval);
+  void Set(std::string name, int newval);
+  void Set(std::string name, double newval);
+  void Set(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 50aeeb2..c7d17fd 100644
--- a/src/Utils/PlotUtils.cxx
+++ b/src/Utils/PlotUtils.cxx
@@ -1,927 +1,927 @@
 // 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"
+
 
 // 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;
 }
 
 
 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 7a488a8..70dbd7c 100644
--- a/src/Utils/PlotUtils.h
+++ b/src/Utils/PlotUtils.h
@@ -1,230 +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/>.
 *******************************************************************************/
 
 #ifndef PLOTUTILS_H_SEEN
 #define PLOTUTILS_H_SEEN
 
 
 #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>
 
 // C Includes
 #include <stdlib.h>
 #include <numeric>
 #include <math.h>
 #include <iostream>
 #include <unistd.h>
 #include <vector>
 #include <string>
 #include <iostream>
 #include <sstream>
 #include <cstring>
 
 // ROOT includes
 #include <TROOT.h>
 #include <TH1D.h>
 #include <TH2D.h>
 #include <TTree.h>
 #include <TFile.h>
 #include <TChain.h>
 #include <TLorentzVector.h>
 #include <TList.h>
 #include <TKey.h>
 #include <THStack.h>
 #include <TLegend.h>
 #include <TObjArray.h>
 #include <TRandom3.h>
 #include<ctime>
 #include "TH2Poly.h"
 #include "TGraphErrors.h"
 #include "TMatrixDSym.h"
 
 // Fit includes
 #include "FitEvent.h"
-#include "FitParameters.h"
+
 #include "FitLogger.h"
 #include "StatUtils.h"
 #include "GeneralUtils.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="");
 
   //! 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
diff --git a/src/Utils/StackBase.h b/src/Utils/StackBase.h
index 826edb1..398afa6 100644
--- a/src/Utils/StackBase.h
+++ b/src/Utils/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/StatUtils.cxx b/src/Utils/StatUtils.cxx
index a32ec94..2648470 100644
--- a/src/Utils/StatUtils.cxx
+++ b/src/Utils/StatUtils.cxx
@@ -1,1301 +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();
 
   // 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/Utils/StatUtils.h
index bf26e90..f22e67c 100644
--- a/src/Utils/StatUtils.h
+++ b/src/Utils/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