diff --git a/src/Routines/SplineRoutines.cxx b/src/Routines/SplineRoutines.cxx
index 996122e..ea67d2d 100755
--- a/src/Routines/SplineRoutines.cxx
+++ b/src/Routines/SplineRoutines.cxx
@@ -1,1616 +1,1637 @@
 // 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 "StatusMessage.h"
 
 #include "SplineRoutines.h"
 
 /*
   Constructor/Destructor
 */
 //************************
 void SplineRoutines::Init() {
   //************************
 
   fStrategy = "SaveEvents";
   fRoutines.clear();
 
   fCardFile = "";
 
   fSampleFCN = NULL;
   fRW = NULL;
 
   fAllowedRoutines = ("SaveEvents,TestEvents,SaveSplineEvents");
 };
 
 //*************************************
 SplineRoutines::~SplineRoutines() {
   //*************************************
 };
 
 /*
   Input Functions
 */
 //*************************************
 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);
 
   // 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]);
   }
 
   // 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");
 
   // Add Error Verbo Lines
   verbocount += Config::Get().GetParI("VERBOSITY");
   errorcount += Config::Get().GetParI("ERROR");
   std::cout << "[ NUISANCE ]: Setting VERBOSITY=" << verbocount << std::endl;
   std::cout << "[ NUISANCE ]: Setting ERROR=" << errorcount << std::endl;
   FitPar::log_verb = verbocount;
   LOG_VERB(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")){  GenerateEventSplines(); }
     // else if  (!rout.compare("GenerateEventWeights")) { GenerateEventWeights(); }
     // 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();
 
   }
 
 
 }
 
 //*************************************
 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 i = 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 (i % countwidth == 0) {
         LOG(REC) << "Saved " << i << "/" << nevents
                  << " nuisance events. [M, W] = ["
                  << nuisevent->Mode << ", " << nuisevent->RWWeight << "]" << std::endl;
       }
 
       // iterate
       nuisevent = input->NextNuisanceEvent();
       i++;
     }
 
     // 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::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()+1;
+    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
-      splwriterlist[ int(omp_get_thread_num()) ]->FitSplinesForEvent(weightcont[i], allcoeff[i]);
+      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::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 (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 (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.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();
     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::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 (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;
   }
 
   // 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 (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;
   }
 
   // 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/Splines/SplineWriter.cxx b/src/Splines/SplineWriter.cxx
index 5055b47..d4f8be8 100644
--- a/src/Splines/SplineWriter.cxx
+++ b/src/Splines/SplineWriter.cxx
@@ -1,765 +1,766 @@
 #include "SplineWriter.h"
 using namespace SplineUtils;
 
 // Spline reader should have access to every spline.
 // Should know when reconfigure is called what its limits are and adjust accordingly.
 // Then should pass it the index required in the stack as &xvals[index], and &pars[parindex]
 
 void SplineWriter::Write(std::string name) {
   // Create a TTree with each form and scan points in it.
   TTree* tr = new TTree(name.c_str(), name.c_str());
 
   // Loop over all splines and add a TString in the TTree for its inputs
   tr->Branch("Spline", &fSpline);
   tr->Branch("Type", &fType);
   tr->Branch("Form", &fForm);
   tr->Branch("Points", &fPoints);
   tr->Fill();
   tr->Write();
 
   delete tr;
 }
 
 void SplineWriter::AddWeightsToTree(TTree* tr) {
   // Add only the fitted spline coefficients to the ttree
   std::cout << "Saving Spline Weights to TTree = " << Form("SplineWeights[%d]/F", (int)fValList.size()) << std::endl;
   //  sleep(1);
   tr->Branch("SplineWeights", fWeightList, Form("SplineWeights[%d]/D", (int)fValList.size()));
 }
 
 void SplineWriter::ReadWeightsFromTree(TTree* tr) {
   tr->SetBranchAddress("SplineWeights", fWeightList);
 }
 
 
 void SplineWriter::AddCoefficientsToTree(TTree* tr) {
   // Add only the fitted spline coefficients to the ttree
   std::cout << "Saving Spline Coeff to TTree = " << Form("SplineCoeff[%d]/F", fNCoEff) << std::endl;
   //  sleep(1);
   tr->Branch("SplineCoeff", fCoEffStorer, Form("SplineCoeff[%d]/F", fNCoEff));
 }
 
 
 void SplineWriter::SetupSplineSet() {
   std::cout << "Setting up spline set" << std::endl;
 
   // Create the coefficients double*
   fNCoEff = 0;
   for (size_t i = 0; i < fAllSplines.size(); i++) {
     fNCoEff += fAllSplines[i].GetNPar();
   }
   fCoEffStorer = new float[fNCoEff];
 
   std::cout << "NCoeff = " << fNCoEff << std::endl;
 
   // Calculate the grid of parsets
   // Setup the list of parameter coefficients.
   std::vector<double> nomvals = fRW->GetDialValues();
   fParVect.clear();
   fSetIndex.clear();
 
   fParVect.push_back(nomvals);
   fSetIndex.push_back(0);
   // fWeightList.push_back(1.0);
   fValList.push_back(std::vector<double>(1, 0.0));
 
   // Loop over all splines.
   for (size_t i = 0; i < fAllSplines.size(); i++) {
 
     // For each dial loop over all points within a given position
     std::vector<double> newvals = nomvals;
 
     std::vector<int> pos;   // = SplineUtils::GetSplitDialPositions(fRW, fSpline[i]);
     std::vector<std::string> splitnames = GeneralUtils::ParseToStr(fSpline[i], ";");
 
     for (size_t j = 0; j < splitnames.size(); j++) {
       int temppos = fRW->GetDialPos(splitnames[j]);
       pos.push_back(temppos);
     }
 
     std::vector< std::vector<double> > vals = SplineUtils::GetSplitDialPoints(fPoints[i]);
 
     for (size_t j = 0; j < vals.size(); j++) {
 
       for (size_t k = 0; k < pos.size(); k++) {
         newvals[ pos[k] ] = vals[j][k];
       }
       fParVect.push_back(newvals);
       fValList.push_back(vals[j]);
       // fWeightList.push_back(1.0);
       fSetIndex.push_back(i + 1);
     }
   }
 
   fWeightList = new double[fValList.size()];
   for (int i = 0; i < fValList.size(); i++) {
     fWeightList[i] = 1.0;
   }
 
   // Print out the parameter set
   LOG(FIT) << "Parset | Index | Pars --- " << std::endl;
   for (size_t i = 0; i < fSetIndex.size(); i++) {
     LOG(FIT) << " Set " << i << ". | " << fSetIndex[i] << " | ";
     if (LOG_LEVEL(FIT)) {
       for (size_t j = 0; j < fParVect[i].size(); j++) {
         std::cout << " " << fParVect[i][j];
       }
       std::cout << std::endl;
     }
   }
 }
 
 void SplineWriter::GetWeightsForEvent(FitEvent* event) {
   // Get Starting Weight
   fRW->SetAllDials(&fParVect[0][0], fParVect[0].size());
   double nomweight = fRW->CalcWeight(event);
   event->RWWeight = nomweight;
 
   if (fDrawSplines) {
     std::cout << "Nominal Spline Weight = " << nomweight << std::endl;
   }
   fWeightList[0] = nomweight;
 
   // Loop over parameter sets
   for (size_t i = 1; i < fParVect.size(); i++) {
     // Update FRW
     fRW->SetAllDials(&fParVect[i][0], fParVect[i].size());
 
     // Calculate a weight for event
     double weight = fRW->CalcWeight(event);
 
 
     if (weight >= 0.0 and weight < 200) {
       // Fill Weight Set
       fWeightList[i] = weight / nomweight;
       if (fDrawSplines) std::cout << "Calculating values from weight set " << i << " " << fParVect[i][0] << " = " << weight << " " << weight / nomweight << std::endl;
     } else {
       fWeightList[i] = 1.0;
     }
   }
 }
 
 void SplineWriter::GetWeightsForEvent(FitEvent* event, double* weights) {
   // Get Starting Weight
   fRW->SetAllDials(&fParVect[0][0], fParVect[0].size());
   double nomweight = fRW->CalcWeight(event);
   event->RWWeight = nomweight;
 
   if (fDrawSplines) {
     std::cout << "Nominal Spline Weight = " << nomweight << std::endl;
   }
   weights[0] = nomweight;
 
   // Loop over parameter sets
   for (size_t i = 1; i < fParVect.size(); i++) {
     // Update FRW
     fRW->SetAllDials(&fParVect[i][0], fParVect[i].size());
 
     // Calculate a weight for event
     double weight = fRW->CalcWeight(event);
 
 
     if (weight >= 0.0 and weight < 200) {
       // Fill Weight Set
       weights[i] = weight / nomweight;
       if (fDrawSplines) std::cout << "Calculating values from weight set " << i << " " << fParVect[i][0] << " = " << weight << " " << weight / nomweight << std::endl;
     } else {
       weights[i] = 1.0;
     }
+    fWeightList[i] = weights[i];
   }
 }
 
 
 void SplineWriter::FitSplinesForEvent(double* inputweights, float* coeff) {
 
   int n = fAllSplines.size();
   int coeffcount = 0;
 
   for (int i = 0; i < n; i++) {
 
     // DialVals
     std::vector<std::vector<double> > dialvals;
     std::vector<double> weightvals;
     bool hasresponse = false;
 
     for (size_t j = 0; j <  fSetIndex.size(); j++) {
       if (fSetIndex[j] != i + 1) continue;
 
       dialvals.push_back(fValList[j]);
       double tempw = inputweights[j];
       weightvals.push_back(tempw);
 
       if (tempw != 1.0) hasresponse = true;
     }
 
     // Perform Fit
     if (hasresponse) {
       // std::cout << "Fitting Coeff" << std::endl;
       FitCoeff(&fAllSplines[i], dialvals, weightvals, &coeff[coeffcount], fDrawSplines);
     } else {
       for (int j = 0; coeffcount + j < fNCoEff; j++) {
         // std::cout << "Setting 0.0 response " << coeffcount + i << " " << fNCoEff <<  std::endl;
         coeff[coeffcount + j] = 0.0;
       }
     }
 
     // std::cout << "Adding coeffcount" << std::endl;
     // Offset coeffcount
     coeffcount += (fAllSplines[i]).GetNPar();
   }
 // std::cout << "FitEvent" << std::endl;
   return;
 }
 
 
 void SplineWriter::FitSplinesForEvent(TCanvas * fitcanvas, bool saveplot) {
 
   // Loop over splines
   //  int count = 0;
   int coeffcount = 0;
   int n = fAllSplines.size();
 
   std::vector<int> splinecounter;
   for (int i = 0; i < n; i++) {
     splinecounter.push_back(coeffcount);
     coeffcount += fAllSplines[i].GetNPar();
   }
 
   //  #pragma omp parallel for
   for (int i = 0; i < n; i++) {
 
     // Store X/Y Vals
     std::vector<std::vector<double> > dialvals;
     std::vector<double> weightvals;
     bool hasresponse = false;
     int npar = (fAllSplines[i]).GetNPar();
     coeffcount = splinecounter[i];
 
     for (size_t j = 0; j <  fSetIndex.size(); j++) {
       if (fSetIndex[j] != i + 1) continue;
 
       dialvals.push_back(fValList[j]);
       double tempw = fWeightList[j];
       weightvals.push_back(tempw);
 
       if (tempw != 1.0) hasresponse = true;
     }
 
     // Make a new graph and fit coeff if response
     if (hasresponse) {
       FitCoeff(&fAllSplines[i], dialvals, weightvals, &fCoEffStorer[coeffcount], fDrawSplines);
     } else {
       for (int i = 0; i < npar; i++) {
         fCoEffStorer[coeffcount + i] = 0.0;
       }
     }
   }
 
 
 // Check overrides
 // if (saveplot) {
 //   coeffcount = 0;
 
 //   // Make new canvas to save stuff into
 //   if (fitcanvas) delete fitcanvas;
 //   fitcanvas = new TCanvas("c1", "c1", fAllSplines.size() * 400 , 600);
 //   fitcanvas->Divide(fAllSplines.size(), 1);
 
 //   // Clear out points
 //   for (size_t i = 0; i < fAllDrawnGraphs.size(); i++) {
 //     if (fAllDrawnGraphs[i]) delete fAllDrawnGraphs[i];
 //     if (fAllDrawnHists[i]) delete fAllDrawnHists[i];
 //   }
 //   fAllDrawnGraphs.clear();
 //   fAllDrawnHists.clear();
 
 
 //   for (size_t i = 0; i < fAllSplines.size(); i++) {
 
 //     fitcanvas->cd(i + 1);
 
 //     // Store X/Y Vals
 //     std::vector<std::vector<double> > dialvals;
 //     std::vector<double> weightvals;
 //     bool hasresponse = false;
 //     int npar = (fAllSplines[i]).GetNPar();
 
 //     for (size_t j = 0; j <  fSetIndex.size(); j++) {
 //       if ((UInt_t)fSetIndex[j] != (UInt_t)i + 1) continue;
 //       dialvals.push_back(fValList[j]);
 //       weightvals.push_back(fWeightList[j] - 0.0);
 //       if (fWeightList[j] != 1.0) hasresponse = true;
 //     }
 
 //     if (hasresponse) {
 
 //       TGraph* gr = new TGraph(dialvals.size(), dialvals, weightvals);
 //       fAllDrawnGraphs.push_back(gr);
 
 //       // Get XMax Min
 //       int n = xvals.size();
 //       double xmin = 99999.9;
 //       double xmax = -99999.9;
 //       for (int j = 0; j < n; j++) {
 //         if (xvals[j] > xmax) xmax = xvals[j];
 //         if (xvals[j] < xmin) xmin = xvals[j];
 //       }
 
 //       TH1D* hist = new TH1D("temp", "temp", 100, xmin, xmax);
 //       fAllDrawnHists.push_back(hist);
 
 //       for (int k = 0; k < 100; k++) {
 //         double xtemp = hist->GetXaxis()->GetBinCenter(k + 1);
 //         fAllSplines[i].Reconfigure(xtemp);
 //         double ytemp = fAllSplines[i].DoEval(&fCoEffStorer[coeffcount]);
 //         hist->SetBinContent(k + 1, ytemp);
 //       }
 
 //       // gr->Draw("APL");
 //       hist->SetLineColor(kRed);
 //       hist->Draw("HIST C");
 //       hist->SetTitle("Spline Response");
 //       // hist->GetYaxis()->SetRangeUser(0.0, 3.0);
 
 //       // gStyle->SetOptStat(0);
 //       hist->SetStats(0);
 //       gr->SetMarkerStyle(20);
 //       gr->SetTitle("True Weight Points");
 //       gr->Draw("P SAME");
 //       gPad->BuildLegend(0.6, 0.6, 0.85, 0.85);
 //       gPad->Update();
 
 //       hist->SetTitle(fSpline[i].c_str());
 //       hist->GetXaxis()->SetTitle("Dial Variation");
 //       hist->GetYaxis()->SetTitle("Event Weight");
 //       fitcanvas->Update();
 //     }
 //     coeffcount += npar;
 //   }
 // }
 }
 
 
 
 
 // Fitting
 // ----------------------------------------------
 void SplineWriter::FitCoeff(Spline * spl, std::vector< std::vector<double> >& v, std::vector<double>& w, float * coeff, bool draw) {
 
   std::vector<double> x;
   std::vector<double> y;
   std::vector<double> z;
   for (size_t i = 0; i < v.size(); i++) {
     x.push_back(v[i][0]);
     if (v[i].size() > 1) y.push_back(v[i][1]);
     if (v[i].size() > 2) z.push_back(v[i][2]);
   }
 
   switch (spl->GetType()) {
 
   // Polynominal Graph Fits
   case k1DPol1:
   case k1DPol2:
   case k1DPol3:
   case k1DPol4:
   case k1DPol5:
   case k1DPol6:
 
 
 
     FitCoeff1DGraph(spl, v.size(), &x[0], &w[0], coeff, draw);
     break;
 
   case k1DTSpline3:
 
     GetCoeff1DTSpline3(spl, x.size(), &x[0], &w[0], coeff, draw);
     break;
 
   case k2DPol6:
   case k2DGaus:
   case k2DTSpline3:
     FitCoeff2DGraph(spl, v.size(), &x[0], &y[0], &w[0], coeff, draw);
     break;
 
   default:
     break;
   }
 
   // fSplineFCNs[spl] = new SplineFCN(spl, v, w);
   // fSplineFCNs[spl]->SaveAs("mysplinetest_" + spl->GetName() + ".pdf", coeff);
   // sleep(1);
   // delete fSplineFCNs[spl];
 
 }
 
 void SplineWriter::FitCoeff1DGraph(Spline * spl, int n, double * x, double * y, float * coeff, bool draw) {
 
   TGraph* gr = new TGraph(n, x, y);
   double xmin = 99999.9;
   double xmax = -99999.9;
   for (int i = 0; i < n; i++) {
     if (x[i] > xmax) xmax = x[i];
     if (x[i] < xmin) xmin = x[i];
   }
 
   double xwidth = xmax - xmin;
   xmin = xmin - xwidth * 0.01;
   xmax = xmax + xwidth * 0.01;
 
   // Create a new function for fitting.
   TF1* func = new TF1("f1", spl, -30.0, 30.0, spl->GetNPar());
   func->SetNpx(400);
   func->FixParameter(0, 1.0); // Fix so 1.0 at nominal
 
   // Run the actual spline fit
   StopTalking();
 
   
   // If linear fit with two points
   if (n == 2 and spl->GetType() == k1DPol1) {
 
     float m = (y[1] - y[0]) / (x[1] - x[0]);
     float c = y[0] - (0.0 - x[0]) * m;
 
     func->SetParameter(0, c);
     func->SetParameter(1, m);
 
   } else if (spl->GetType() == k1DPol1) {
     gr->Fit(func, "WQ");
   } else {
     gr->Fit(func, "FMWQ");
   }
   
 
   StartTalking();
 
   for (int i = 0; i < spl->GetNPar(); i++) {
     coeff[i] = func->GetParameter(i);
   }
 
   if (draw) {
     gr->Draw("APL");
     gPad->Update();
     gPad->SaveAs(("plot_test_" + spl->GetName() + ".pdf").c_str());
     std::cout << "Saving Graph" << std::endl;
     sleep(3);
   }
 
   delete func;
   delete gr;
 }
 
 double SplineFCN::operator()(const double * x) const {
   return DoEval(x);
 }
 
 double SplineFCN::DoEval(const double * x) const {
 
   float* fx = new float[fSpl->GetNPar()];
   for (int i = 0; i < fSpl->GetNPar(); i++) {
     fx[i] = x[i];
   }//
 
   double tot = 0;
   for (size_t i = 0; i < fVal.size(); i++) {
 
     int nonzero = 0;
     for (size_t j = 0; j < fVal[i].size(); j++) {
       fSpl->Reconfigure(fVal[i][j], j);
       // std::cout << "Reconfiguring " << fVal[i][j] << " " << j << std::endl;
       if (fVal[i][j] != 0.0) nonzero++;
     }
     if (uncorrelated and nonzero > 1) continue;
 
     double w = fSpl->DoEval(fx);
     double wdif = (w - fWeight[i]);// / (fWeight[i] * 0.05);
     tot += sqrt(wdif * wdif);
   }
 
   // delete fx;
 
   return tot;
 }
 
 void SplineFCN::UpdateWeights(std::vector<double>& w) {
   for (int i = 0; i < w.size(); i++) {
     fWeight[i] = w[i];
   }
 }
 
 void SplineFCN::SetCorrelated(bool state) {
   uncorrelated = !state;
 }
 
 
 
 void SplineFCN::SaveAs(std::string name, const float * fx) {
 
 
   if (fVal[0].size() != 2) {
     TCanvas* c1 = new TCanvas("c1", "c1", 800, 600);
     c1->Divide(2, 1);
     TH1D* histmc = new TH1D("hist", "hist", fVal.size(), 0.0, double(fVal.size()));
     TH1D* histdt = new TH1D("histdt", "histdt", fVal.size(), 0.0, double(fVal.size()));
 
     for (size_t i = 0; i < fVal.size(); i++) {
       for (size_t j = 0; j < fVal[i].size(); j++) {
         fSpl->Reconfigure(fVal[i][j], j);
       }
 
       histmc->SetBinContent( i + 1, fSpl->DoEval(fx) );
       histdt->SetBinContent( i + 1, fWeight[i] );
     }
 
     // histmc->Add(histdt,-1.0);
 
     c1->cd(1);
     histmc->SetTitle("Spline;Parameter Set;Weight");
     histmc->Draw("HIST");
     histdt->SetLineColor(kRed);
     histdt->Draw("SAME HIST");
 
     c1->cd(2);
     TH1D* histdif = (TH1D*) histmc->Clone();
     histdif->Add(histdt, -1.0);
     histdif->Draw("HIST");
 
     c1->Update();
     c1->SaveAs(name.c_str());
     delete c1;
   } else {
 
     TGraph2D* histmc = new TGraph2D();
     TGraph2D* histdt = new TGraph2D();
     TGraph2D* histdif = new TGraph2D();
 
     for (size_t i = 0; i < fVal.size(); i++) {
       for (size_t j = 0; j < fVal[i].size(); j++) {
         fSpl->Reconfigure(fVal[i][j], j);
       }
 
       histmc->SetPoint(histmc->GetN(), fVal[i][0], fVal[i][1], fSpl->DoEval(fx));
       histdt->SetPoint(histdt->GetN(), fVal[i][0], fVal[i][1], fWeight[i]);
       histdif->SetPoint(histdif->GetN(), fVal[i][0], fVal[i][1], fabs(fSpl->DoEval(fx) - fWeight[i]));
 
 
     }
     TCanvas* c1 = new TCanvas("c1", "c1", 800, 600);
     c1->Divide(3, 1);
     c1->cd(1);
     histmc->SetTitle(("Spline;" + fSpl->GetName()).c_str());
     histmc->Draw("COLZ");
     gPad->Update();
     c1->cd(2);
     histdt->SetTitle(("Raw;" + fSpl->GetName()).c_str());
     histdt->Draw("COLZ");
     c1->cd(3);
     histdif->SetTitle(("Dif;" + fSpl->GetName()).c_str());
     histdif->Draw("COLZ");
     gPad->SetRightMargin(0.15);
     // gPad->SetLogz(1);
 
     gPad->Update();
     c1->SaveAs(name.c_str());
     delete c1;
   }
 
 
 
   // gPad->SaveAs(name.c_str());
 }
 
 namespace SplineUtils {
   Spline* gSpline = NULL;
 }
 
 double SplineUtils::Func2DWrapper(double * x, double * p) {
   // std::cout << "2D Func Wrapper " << x[0] << " " << x[1] << std::endl;
   return (*gSpline)(x, p);
 }
 
 void SplineWriter::FitCoeff2DGraph(Spline * spl, int n, double * x, double * y, double * w, float * coeff, bool draw) {
 
   #pragma omp critical
   {
   //  if (gSpline != spl) gSpline = spl;
   if (SplineUtils::gSpline != spl)
     SplineUtils::gSpline = spl;
 
   TF2* f2 = new TF2("f2", Func2DWrapper, -30.0, 30.0, -30.0, 30.0, spl->GetNPar());
   TGraph2D* histmc = new TGraph2D(n, x, y, w);
   f2->SetNpx(400);
 
   StopTalking();
   histmc->Fit(f2, "FMWQ");
   StartTalking();
   
   for (int i = 0; i < spl->GetNPar(); i++) {
     coeff[i] = f2->GetParameter(i);
     //    std::cout << "Fit 2D Func " << i << " = " << coeff[i] << std::endl;
   }
 
   delete f2;
   delete histmc;
   }
 }
 
 
 void SplineWriter::FitCoeffNDGraph(Spline * spl, std::vector< std::vector<double> >& v, std::vector<double>& w, float * coeff, bool draw) {
 
   // TGraph2D* gr = new TGraph2D(n, x, y);
   // double xmin = 99999.9;
   // double xmax = -99999.9;
   // double ymin = 99999.9;
   // double ymax = -99999.9;
   // for (int i = 0; i < n; i++) {
   //   if (x[i] > xmax) xmax = x[i];
   //   if (x[i] < xmin) xmin = x[i];
   //   if (y[i] > ymax) ymax = y[i];
   //   if (y[i] < ymin) ymin = y[i];
   // }
   // double xwidth = xmax - xmin;
   // xmin = xmin - xwidth * 0.01;
   // xmax = xmax + xwidth * 0.01;
   // double ywidth = ymax - ymin;
   // ymin = ymin - ywidth * 0.01;
   // ymax = ymax + ywidth * 0.01;
 
 
   // StopTalking();
 
   // Build if not already in writer
   // if (fSplineFCNs.find(spl) != fSplineFCNs.end()) {
   //    fSplineFCNs.erase(spl);
   // }
   //    fSplineFCNs[spl] = new SplineFCN(spl, v, w);
 
 
   if (fSplineFunctors.find(spl) != fSplineFunctors.end()) {
     delete fSplineFunctors[spl];
     fSplineFunctors.erase(spl);
   }
 
   if (fSplineFCNs.find(spl) != fSplineFCNs.end()) {
     delete fSplineFCNs[spl];
     fSplineFCNs.erase(spl);
   }
 
   if (fSplineMinimizers.find(spl) != fSplineMinimizers.end()) {
     delete fSplineMinimizers[spl];
     fSplineMinimizers.erase(spl);
   }
 
 
 
   if  (fSplineMinimizers.find(spl) == fSplineMinimizers.end()) {
     std::cout << "Building new ND minimizer for " << spl << std::endl;
     fSplineFCNs[spl] = new SplineFCN(spl, v, w);
 
     // fSplineFCNs[spl] = new SplineFCN(spl, v, w);
     fSplineFunctors[spl] = new ROOT::Math::Functor( *fSplineFCNs[spl], spl->GetNPar() );
 // fitclass = "GSLSimAn"; fittype = "";
     fSplineMinimizers[spl] = ROOT::Math::Factory::CreateMinimizer("Minuit2", "Combined");
     fSplineMinimizers[spl]->SetMaxFunctionCalls(1E8);
     fSplineMinimizers[spl]->SetMaxIterations(1E8);
     fSplineMinimizers[spl]->SetTolerance(1.E-6);
     fSplineMinimizers[spl]->SetStrategy(2);
 
     for (int j = 0; j < spl->GetNPar(); j++) {
       if (j != 0) {
         fSplineMinimizers[spl]->SetVariable(j, Form("Par_%i", j), 0.1, 0.1);
         // fSplineMinimizers[spl]->SetParameter(j, Form("Par_%i", j), 0.1, 0.1, -100.0, 100.0 );
       } else {
         fSplineMinimizers[spl]->SetVariable(j, Form("Par_%i", j), 1.0, 0.1);
         // fSplineMinimizers[spl]->SetParameter(j, Form("Par_%i", j), 1.0, 0.1, -100.0, 100.0 );
         // fSplineMinimizers[spl]->FixVariable(j);
       }
     }
     // fSplineMinimizers[spl]->SetFunction(*fSplineFunctors[spl]);
     sleep(1);
   }
   // Create a new function for fitting.
   // StopTalking();
 
   // Update FCN
   fSplineFCNs[spl]->UpdateWeights(w);
   // fSplineMinimizers[spl]->SetDefaultOptions();
   // fSplineMinimizers[spl]->Clear();
   for (int j = 0; j < spl->GetNPar(); j++) {
     if (j != 0) {
       fSplineMinimizers[spl]->SetVariableValue(j, 0.1);
       // fSplineMinimizers[spl]->SetParameter(j, Form("Par_%i", j), 0.1, 0.1, -100.0, 100.0 );
 
       // fSplineMinimizers[spl]->SetVariableValue(j, 0.1);
     }
   }
   // fSplineFCNs[spl]->SetCorrelated(false);
   // fSplineFunctors[spl] = new ROOT::Math::Functor( *fSplineFCNs[spl], spl->GetNPar() );
   // fSplineMinimizers[spl]->SetFunction(*fSplineFunctors[spl]);
   // fSplineMinimizers[spl]->Minimize();
 
   fSplineFCNs[spl]->SetCorrelated(true);
   delete fSplineFunctors[spl];
   fSplineFunctors[spl] = new ROOT::Math::Functor( *fSplineFCNs[spl], spl->GetNPar() );
   fSplineMinimizers[spl]->SetFunction(*fSplineFunctors[spl]);
   // ((TFitterMinuit*)fSplineMinimizers[spl])->CreateMinimizer(TFitterMinuit::kMigrad);
   fSplineMinimizers[spl]->Minimize();
   fSplineMinimizers[spl]->Minimize();
 
   // ((TFitterMinuit*)fSplineMinimizers[spl])->CreateMinimizer(TFitterMinuit::kMigrad);
   // fSplineMinimizers[spl]->Minimize();
 
   // delete minimizer;
   // StartTalking();
 
   // Now Get Parameters
   const double *values = fSplineMinimizers[spl]->X();
   for (int i = 0; i < spl->GetNPar(); i++) {
 
     std::cout << "Updated Coeff " << i << " " << values[i] << std::endl;
     coeff[i] = values[i];
   }
 
   // Save a sample
   fSplineFCNs[spl]->SaveAs("mysplinetest_" + spl->GetName() + ".pdf", coeff);
   sleep(1);
 
   // delete values;
   // delete minimizer;
 }
 
 
 
 // Spline extraction Functions
 void SplineWriter::GetCoeff1DTSpline3(Spline * spl, int n, double * x, double * y, float * coeff, bool draw) {
 
   StopTalking();
   TSpline3 temp_spline = TSpline3("temp_spline", x, y, n);
   StartTalking();
 
   for (size_t i = 0; i < (UInt_t)n; i++) {
 
     double a, b, c, d, e;
     temp_spline.GetCoeff(i, a, b, c, d, e);
 
     coeff[i * 4]   = y[i];
     coeff[i * 4 + 1] = c;
     coeff[i * 4 + 2] = d;
     coeff[i * 4 + 3] = e;
 
     // std::cout << "Setting Spline Coeff Set " << i << " to " << y[i] << " " << c << " " << d << " " << e << std::endl;
   }
 
   if (draw) {
     TGraph* gr = new TGraph(n, x, y);
     temp_spline.Draw("CA");
     gr->Draw("PL SAME");
     gPad->Update();
     gPad->SaveAs(("plot_test_" + spl->GetName() + ".pdf").c_str());
 
     delete gr;
   }
 
   return;
 }