diff --git a/CMakeLists.txt b/CMakeLists.txt
index 342761b..eb7a6d1 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,82 +1,78 @@
 # Copyright 2018 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret
 
 ################################################################################
 #    This file is part of NUISANCE.
 #
 #    NUISANCE is free software: you can redistribute it and/or modify
 #    it under the terms of the GNU General Public License as published by
 #    the Free Software Foundation, either version 3 of the License, or
 #    (at your option) any later version.
 #
 #    NUISANCE is distributed in the hope that it will be useful,
 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 #    GNU General Public License for more details.
 #
 #    You should have received a copy of the GNU General Public License
 #    along with NUISANCE.  If not, see <http://www.gnu.org/licenses/>.
 ################################################################################
 cmake_minimum_required (VERSION 2.8 FATAL_ERROR)
 
 #Use the compilers found in the path
 find_program(CMAKE_C_COMPILER NAMES $ENV{CC} gcc PATHS ENV PATH NO_DEFAULT_PATH)
 find_program(CMAKE_CXX_COMPILER NAMES $ENV{CXX} g++ PATHS ENV PATH NO_DEFAULT_PATH)
 
 project(NUISANCE)
 
 include(ExternalProject)
 
 set (NUISANCE_VERSION_MAJOR 3)
 set (NUISANCE_VERSION_MINOR 0)
 set (NUISANCE_VERSION_REVISION 0)
 
 set (NUISANCE_VERSION_STRING "v${NUISANCE_VERSION_MAJOR}r${NUISANCE_VERSION_MINOR}")
 if(${NUISANCE_VERSION_REVISION} STRGREATER "0")
   set (NUISANCE_VERSION_STRING "${NUISANCE_VERSION_STRING}p${NUISANCE_VERSION_REVISION}")
 endif()
 
 #Set this to TRUE to enable build debugging messages
 set(BUILD_DEBUG_MSGS TRUE)
 
 include(${CMAKE_SOURCE_DIR}/cmake/cmessage.cmake)
 include(${CMAKE_SOURCE_DIR}/cmake/cacheVariables.cmake)
 include(${CMAKE_SOURCE_DIR}/cmake/parseConfigApp.cmake)
 include(${CMAKE_SOURCE_DIR}/cmake/StringAndListUtils.cmake)
 
 cmessage(STATUS "CMAKE_INSTALL_PREFIX: \"${CMAKE_INSTALL_PREFIX}\"")
 cmessage(STATUS "CMAKE_BUILD_TYPE: \"${CMAKE_BUILD_TYPE}\"")
 
 ################################################################################
 #                            Check Dependencies
 ################################################################################
 
 ##################################  ROOT  ######################################
 include(${CMAKE_SOURCE_DIR}/cmake/ROOTSetup.cmake)
 
 ################################# InputHandler #################################
 include(${CMAKE_SOURCE_DIR}/cmake/InputHandlerSetup.cmake)
 
 #################################  Pythia6/8 ###################################
 include(${CMAKE_SOURCE_DIR}/cmake/pythia6Setup.cmake)
 
 ################################## FHICLCPP ####################################
 include(${CMAKE_SOURCE_DIR}/cmake/fhiclcppSetup.cmake)
 
 #Want this after fhiclcpp which will add the install directory
 include_directories(${CMAKE_SOURCE_DIR}/src)
 
 ################################## COMPILER ####################################
 include(${CMAKE_SOURCE_DIR}/cmake/c++CompilerSetup.cmake)
 
 ################################################################################
 
 add_subdirectory(src)
 
-configure_file(cmake/setup.sh.in
-  "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/setup.sh" @ONLY)
-install(FILES
-  "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/setup.sh" DESTINATION
-  ${CMAKE_INSTALL_PREFIX})
+add_subdirectory(scripts)
 
 add_subdirectory(config)
 add_subdirectory(data)
diff --git a/cmake/c++CompilerSetup.cmake b/cmake/c++CompilerSetup.cmake
index 17399d9..5083311 100644
--- a/cmake/c++CompilerSetup.cmake
+++ b/cmake/c++CompilerSetup.cmake
@@ -1,57 +1,57 @@
 # Copyright 2018 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(CXX_WARNINGS -Wall -Wextra)
 
 LIST(APPEND EXTRA_CXX_FLAGS ${CXX_WARNINGS} -Werror -Wno-delete-non-virtual-dtor -Wno-unused "-D__FILENAME__=\"$(subst ${CMAKE_SOURCE_DIR}/,,$(abspath $<))\"")
 
 BuildFlagString(NUISANCE_LINK_DIRS "-L" ${EXTRA_LINK_DIRS})
 
 LIST(APPEND EXTRA_LIBS dl)
 BuildLibraryFlagString(STR_EXTRA_LIBS ${EXTRA_LIBS})
 BuildFlagString(STR_EXTRA_SHAREDOBJS " " ${EXTRA_SHAREDOBJS})
 
 #This ends up holding all of the libraries and search paths for extenal dependencies
 CatStringsIfNotEmpty(NUISANCE_DEPEND_LIBS
   ${STR_EXTRA_SHAREDOBJS}
   ${STR_EXTRA_LIBS})
 
 BuildFlagString(STR_EXTRA_LINK_FLAGS " " ${EXTRA_LINK_FLAGS})
 
 CatStringsIfNotEmpty(CMAKE_LINK_FLAGS
   ${CMAKE_LINK_FLAGS}
   ${STR_EXTRA_LINK_FLAGS})
 
 get_directory_property(NUISANCE_INCLUDE_DIRS INCLUDE_DIRECTORIES)
 
 BuildFlagString(NUISANCE_CXX_FLAGS " " ${EXTRA_CXX_FLAGS})
 CatStringsIfNotEmpty(NUISANCE_CXX_FLAGS ${CMAKE_CXX_FLAGS} ${NUISANCE_CXX_FLAGS} )
 
 if (VERBOSE)
   cmessage (STATUS "C++ Compiler      : ${CXX_COMPILER_NAME}")
   cmessage (STATUS "    Flags         : ${NUISANCE_CXX_FLAGS}")
   cmessage (STATUS "    Release Flags : ${CMAKE_CXX_FLAGS_RELEASE}")
   cmessage (STATUS "    Debug Flags   : ${CMAKE_CXX_FLAGS_DEBUG}")
-  cmessage (STATUS "    Include Dris  : ${NUISANCE_INCLUDE_DIRS}")
+  cmessage (STATUS "    Include Dirs  : ${NUISANCE_INCLUDE_DIRS}")
   cmessage (STATUS "    Linker Flags  : ${CMAKE_LINK_FLAGS}")
   cmessage (STATUS "    Link Dirs     : ${NUISANCE_LINK_DIRS}")
   cmessage (STATUS "    Lib Flags     : ${NUISANCE_DEPEND_LIBS}")
 endif()
 
 add_compile_options(${EXTRA_CXX_FLAGS})
diff --git a/scripts/CMakeLists.txt b/scripts/CMakeLists.txt
new file mode 100644
index 0000000..d6ea15b
--- /dev/null
+++ b/scripts/CMakeLists.txt
@@ -0,0 +1 @@
+add_subdirectory(to_configure)
diff --git a/scripts/to_configure/CMakeLists.txt b/scripts/to_configure/CMakeLists.txt
new file mode 100644
index 0000000..ab6657a
--- /dev/null
+++ b/scripts/to_configure/CMakeLists.txt
@@ -0,0 +1,28 @@
+configure_file(setup.sh.in
+  ${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/setup.sh @ONLY)
+configure_file(nuisbuild.in
+  ${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/nuisbuild @ONLY)
+configure_file(nuiseventprocgen.in
+  ${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/nuiseventprocgen @ONLY)
+
+install(
+  FILES
+    ${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/setup.sh
+  DESTINATION
+    ${CMAKE_INSTALL_PREFIX}
+  )
+
+install(
+  FILES
+    SimpleDataComparison.cxx.in SimpleMCStudy.cxx.in
+  DESTINATION
+    file_stubs
+  )
+
+install(
+  PROGRAMS
+    ${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/nuisbuild
+    ${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/nuiseventprocgen
+  DESTINATION
+    bin
+  )
diff --git a/scripts/to_configure/SimpleDataComparison.cxx.in b/scripts/to_configure/SimpleDataComparison.cxx.in
new file mode 100644
index 0000000..a82f398
--- /dev/null
+++ b/scripts/to_configure/SimpleDataComparison.cxx.in
@@ -0,0 +1,180 @@
+// Copyright 2018 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 "samples/SimpleDataComparison.hxx"
+
+#include "utility/EventTopologyUtility.hxx"
+#include "utility/FullEventUtility.hxx"
+#include "utility/KinematicUtility.hxx"
+#include "utility/PDGCodeUtility.hxx"
+
+using namespace nuis::event;
+using namespace nuis::utility;
+
+class __SAMPLE_NAME__ : public __SDC_TYPE__ {
+
+  //! Add any extra plots that you want to fill as data members of the
+  //! comparisons class.
+  // std::unique_ptr<TH1> Extra_plot;
+
+public:
+  __SAMPLE_NAME__() { ReadGlobalConfigDefaults(); }
+
+  std::string GetDocumentation() { return ""; }
+  fhicl::ParameterSet GetExampleConfiguration() {
+    fhicl::ParameterSet exps = __SDC_TYPE__::GetExampleConfiguration();
+
+    return exps;
+  }
+
+  void Initialize(fhicl::ParameterSet const &instance_sample_configuration) {
+
+    //! Set the verbosity of the sample logging macros.
+    if (instance_sample_configuration.has_key("verbosity")) {
+      SetSampleVerbosity(
+          instance_sample_configuration.get<std::string>("verbosity"));
+
+      //! Use these macros within member functions to log to the terminal
+      //! See src/samples/IEventProcessor.hxx for more details.
+      IEventProcessor_INFO(
+          "Verbosity set: "
+          << instance_sample_configuration.get<std::string>("verbosity"));
+    }
+
+    // Get the global configuration for this sample, if it exists.
+    fhicl::ParameterSet const &global_sample_configuration =
+        nuis::config::GetDocument().get<fhicl::ParameterSet>(
+            std::string("global.sample_configuration.") + Name(),
+            fhicl::ParameterSet());
+
+    //! This will automatically set the data histogram to be loaded.
+    // SetData(
+    //     GetDataDir() +
+    //     "path/to/data;histname");
+
+    //! Instantiate any extra plots that you want to fill
+    // Extra_plot = std::unique_ptr<TH1D>(
+    //     new TH1D("Extra_plot",
+    //              "title;xlabel;ylabel",
+    //              nbinsx,xlow,xhigh));
+
+    // Perform any per-sample configuration in the base class
+    __SDC_TYPE__::Initialize(instance_sample_configuration);
+
+    //! Define your event signal here.
+    IsSigFunc = [](FullEvent const &fev) -> bool {
+      //! See src/utility/EventTopologyUtility.hxx for more pre-defined
+      //! topological signals.
+      // if (!IsCC0Pi(fev)) {
+      //   return false;
+      // }
+
+      //! See src/event/FullEvent.hxx for the full event class definition.
+      //! See src/utility/FullEventUtility.hxx for more helper methods for
+      //! interacting with the event class.
+
+      //! Get the initial state anti-muon neutrino
+      // Particle ISNumuBar = GetHMISParticle(fev, {pdgcodes::kNuMuBar});
+      //! An nuis::event::Particle that return true for !part is invalid and
+      //! does not exist on the particle stack. i.e. here, the selection fails
+      //! if the event didn't have an initial state numubar.
+      // if (!ISNumuBar) {
+      //   return false;
+      // }
+
+      //! Get the final state anti-muon
+      // Particle FSMuPlus = GetHMFSParticle(fev, {pdgcodes::kMuPlus});
+      // if (!FSMuPlus) {
+      //   return false;
+      // }
+
+      //! Cut on kinematic properties of the true final state.
+      // if (FSMuPlus.CosTheta() < 0.84) {
+      //   return false;
+      // }
+
+      //! Select the event!
+      return true;
+    };
+
+    //! 1D Projection function
+    //! This function takes selected events and returns an array of size, the
+    //! dimensionality of the comparisons (__SDC_TYPE__::NDim)
+    CompProjFunc =
+        [](FullEvent const &fev) -> std::array<double, __SDC_TYPE__::NDim> {
+      // Particle FSMuPlus = GetHMFSParticle(fev, {pdgcodes::kMuPlus});
+      // return {FSMuPlus.P()};
+      return {
+          1,
+      };
+    };
+
+    //! Here you fill any custom histograms or TTrees that your sample handles.
+    //! Note the [&] means that the generated closure object will take a
+    //! reference to any in scope variables that are used within the lambda
+    //! body. As this method is then called outside of the scope of this
+    //! Initialize method, you should not use any method-locals within the
+    //! ProcessExtraFunc body. Class members are fine as this will only be
+    //! called when the same instance of this class is alive.
+    ProcessExtraFunc = [&](FullEvent const &fev, bool isSel,
+                           double weight) -> void {
+      //! Whether this event passed the selection function. (Saves you manually
+      //! reselecting events with the IsSigFunc)
+      if (isSel) {
+        // Particle FSMuPlus = GetHMFSParticle(fev, {pdgcodes::kMuPlus});
+        //! The TH_Helper class provides some templated helper methods for
+        //! filling histogram types that are decided at compile time, these are
+        //! used by the SimpleDataComparison base class to provide a dimension
+        //! and precision agnostic interface, but they can also be used by user
+        //! classes if you see fit. See src/utility/HistogramUtility.hxx for
+        //! more details.
+        // TH_Helper<TH1>::Fill(Extra_plot, {FSMuPlus.CosTheta()}, weight);
+      }
+    };
+  }
+
+  std::string Name() { return "__SAMPLE_NAME__"; }
+
+  //! Here you can write any custom histograms to TTrees that your sample has
+  //! been handling.
+  void Write() {
+    //! The base class writes the default MC and data histograms to the output
+    //! directory automatically, so you only have to include logic to write any
+    //! custom histograms or TTrees out here.
+    __SDC_TYPE__::Write();
+
+    //! The nuis::persistency helper methods will help write your objects to the
+    //! correct place and in a TFile that will be closed before the program
+    //! exits.
+    //! They will write a copy of the TObject that is passed, so you do not need
+    //! to release/worry about double freeing any histograms passed.
+    //! write_directory is set up by the baseclass and is configurable in the
+    //! instance configuration.
+    // nuis::persistency::WriteToOutputFile<TH1>(Extra_plot,
+    // Extra_plot->GetName(),
+    //                                           write_directory);
+    //! It probably isn't a good idea to write a TTree with the above method, instead, try using nuis::persistency::GetOutputFile() to get the TFile and then manually writing/giving ownership of your TTree to the output file.
+  }
+};
+
+//! These declarations allow your class to be loaded dynamically by NUISANCE
+DECLARE_PLUGIN(IDataComparison, __SAMPLE_NAME__);
+DECLARE_PLUGIN(IEventProcessor, __SAMPLE_NAME__);
diff --git a/scripts/to_configure/SimpleMCStudy.cxx.in b/scripts/to_configure/SimpleMCStudy.cxx.in
new file mode 100644
index 0000000..e52906a
--- /dev/null
+++ b/scripts/to_configure/SimpleMCStudy.cxx.in
@@ -0,0 +1,117 @@
+// Copyright 2018 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 "samples/SimpleMCStudy.hxx"
+
+#include "utility/EventTopologyUtility.hxx"
+#include "utility/FullEventUtility.hxx"
+#include "utility/KinematicUtility.hxx"
+#include "utility/PDGCodeUtility.hxx"
+
+using namespace nuis::event;
+using namespace nuis::utility;
+
+class __SAMPLE_NAME__ : public SimpleMCStudy {
+
+  //! Add any plots that you want to fill as data members of the
+  //! comparisons class.
+  // std::unique_ptr<TH1> myPlot;
+
+public:
+  __SAMPLE_NAME__() { ReadGlobalConfigDefaults(); }
+
+  void Initialize(fhicl::ParameterSet const &instance_sample_configuration) {
+
+    //! Set the verbosity of the sample logging macros.
+    if (instance_sample_configuration.has_key("verbosity")) {
+      SetSampleVerbosity(
+          instance_sample_configuration.get<std::string>("verbosity"));
+
+      //! Use these macros within member functions to log to the terminal
+      //! See src/samples/IEventProcessor.hxx for more details.
+      IEventProcessor_INFO(
+          "Verbosity set: "
+          << instance_sample_configuration.get<std::string>("verbosity"));
+    }
+
+    // Get the global configuration for this sample, if it exists.
+    fhicl::ParameterSet const &global_sample_configuration =
+        nuis::config::GetDocument().get<fhicl::ParameterSet>(
+            std::string("global.sample_configuration.") + Name(),
+            fhicl::ParameterSet());
+
+    //! Instantiate any plots that you want to fill
+    // myPlot = std::unique_ptr<TH1D>(
+    //     new TH1D("myPlot",
+    //              "title;xlabel;ylabel",
+    //              nbinsx,xlow,xhigh));
+
+    // Perform any per-sample configuration in the base class
+    SimpleMCStudy::Initialize(instance_sample_configuration);
+
+    //! Here you do whatever you want to do on a per-event basis.
+    //! This method will be run for every event given by the input handler, the
+    //! weight allows differential xsecs to be plotted easily and also contains
+    //! any requested reweightable parameter variations.
+    ProcessEventFunction = [&](nuis::event::FullEvent const &ev,
+                               double weight) -> void {
+      //! Select events
+      //! See src/utility/EventTopologyUtility.hxx for more pre-defined
+      //! topological signals.
+      // if (!IsCC0Pi(fev)) {
+      //   return false;
+      // }
+
+      //! Build composite variables
+      //! See src/event/FullEvent.hxx for the full event class definition.
+      //! See src/utility/FullEventUtility.hxx for more helper methods for
+      //! interacting with the event class.
+      // Particle FSMuPlus = GetHMFSParticle(fev, {pdgcodes::kMuPlus});
+
+      //! Fill your histograms!
+      // myPlot->Fill(FSMuPlus.CosTheta(), weight);
+    };
+  }
+
+  std::string Name() { return "__SAMPLE_NAME__"; }
+
+  //! Here you can write any custom histograms to TTrees that your sample has
+  //! been handling.
+  void Write() {
+    //! The nuis::persistency helper methods will help write your objects to the
+    //! correct place and in a TFile that will be closed before the program
+    //! exits.
+    //! They will write a copy of the TObject that is passed, so you do not need
+    //! to release/worry about double freeing any histograms passed.
+    //! write_directory is set up by the baseclass and is configurable in the
+    //! instance configuration.
+    // nuis::persistency::WriteToOutputFile<TH1>(Extra_plot,
+    // Extra_plot->GetName(),
+    //                                           write_directory);
+    //! It probably isn't a good idea to write a TTree with the above method,
+    //! instead, try using nuis::persistency::GetOutputFile() to get the TFile
+    //! and then manually writing/giving ownership of your TTree to the output
+    //! file.
+  }
+};
+
+//! These declarations allow your class to be loaded dynamically by NUISANCE
+DECLARE_PLUGIN(IEventProcessor, __SAMPLE_NAME__);
diff --git a/scripts/to_configure/nuisbuild.in b/scripts/to_configure/nuisbuild.in
new file mode 100644
index 0000000..316b790
--- /dev/null
+++ b/scripts/to_configure/nuisbuild.in
@@ -0,0 +1,101 @@
+# 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/>.
+################################################################################
+
+#!/bin/bash
+
+EXTRA_COMPILE_FLAGS=""
+EXTRA_LINK_FLAGS=""
+INPUT_FILE_NAME=""
+OUTPUT_LIB_NAME=""
+
+SCRIPTNAME=${0}
+
+while [[ ${#} -gt 0 ]]; do
+
+  key="$1"
+  case $key in
+
+      -i|--implementation-file)
+
+      if [[ ${#} -lt 2 ]]; then
+        echo "[ERROR]: ${1} expected a value."
+        exit 1
+      fi
+
+      INPUT_FILE_NAME="$2"
+      echo "[OPT]: Reading event processor implementation from: ${INPUT_FILE_NAME}"
+      shift # past argument
+      ;;
+
+      --compile-flags)
+
+      if [[ ${#} -lt 2 ]]; then
+        echo "[ERROR]: ${1} expected a value."
+        exit 1
+      fi
+
+      EXTRA_COMPILE_FLAGS="$2"
+      echo "[OPT]: Including extra compile flags: ${EXTRA_COMPILE_FLAGS}"
+      shift # past argument
+      ;;
+
+      --link-flags)
+
+      if [[ ${#} -lt 2 ]]; then
+        echo "[ERROR]: ${1} expected a value."
+        exit 1
+      fi
+
+      EXTRA_LINK_FLAGS="$2"
+      echo "[OPT]: Including extra linker flags: ${EXTRA_LINK_FLAGS}"
+      shift # past argument
+      ;;
+
+      -?|--help)
+
+      echo "[RUNLIKE] ${SCRIPTNAME}"
+      echo -e "\t-i|--implementation-file   : Path to IEventProcessor subclass to build into dynamically loadable shared object."
+      echo -e "\t--compile-flags            : Extra compile flags to pass to the compiler."
+      echo -e "\t--link-flags               : Extra linker flags to pass to the linker."
+      echo -e "\t-?|--help                  : Print this message."
+      exit 0
+      ;;
+
+      *)
+              # unknown option
+      echo "Unknown option $1"
+      exit 1
+      ;;
+
+  esac
+  shift
+done
+
+OUTPUT_LIB_NAME=${INPUT_FILE_NAME%.*}.so
+
+#Removes the NUISANCE filename descriptor that uses a gmake trick to insert the file name into the compiler options
+NUISANCE_CXX_FLAGS_GMAKE_SCRUB=$(echo '@NUISANCE_CXX_FLAGS@' | sed s/-D__FILENAME__=\".*\"//g)
+
+echo "@CMAKE_CXX_COMPILER@ ${INPUT_FILE_NAME} -shared -fPIC -o ${OUTPUT_LIB_NAME} ${NUISANCE_CXX_FLAGS_GMAKE_SCRUB} ${EXTRA_COMPILE_FLAGS} -D__FILENAME__=\"${INPUT_FILE_NAME##*/}\" -I. -I@CMAKE_INSTALL_PREFIX@/include  @CMAKE_LINK_FLAGS@ ${EXTRA_LINK_FLAGS} -L@CMAKE_INSTALL_PREFIX@/lib @NUISANCE_LINK_DIRS@  @NUISANCE_DEPEND_LIBS@"
+
+if ! @CMAKE_CXX_COMPILER@ ${INPUT_FILE_NAME} -shared -fPIC -o ${OUTPUT_LIB_NAME} ${NUISANCE_CXX_FLAGS_GMAKE_SCRUB} ${EXTRA_COMPILE_FLAGS} -D__FILENAME__=\"${INPUT_FILE_NAME##*/}\" -I. -I@CMAKE_INSTALL_PREFIX@/include  @CMAKE_LINK_FLAGS@ ${EXTRA_LINK_FLAGS} -L@CMAKE_INSTALL_PREFIX@/lib @NUISANCE_LINK_DIRS@  @NUISANCE_DEPEND_LIBS@; then
+  echo "[ERROR]: Failed to compile ${INPUT_FILE_NAME} -> ${OUTPUT_LIB_NAME}"
+else
+  echo "[INFO]: Successfully build: ${OUTPUT_LIB_NAME}."
+fi
diff --git a/scripts/to_configure/nuiseventprocgen.in b/scripts/to_configure/nuiseventprocgen.in
new file mode 100644
index 0000000..fb60275
--- /dev/null
+++ b/scripts/to_configure/nuiseventprocgen.in
@@ -0,0 +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/>.
+################################################################################
+
+#!/bin/bash
+
+CLASS_NAME=""
+NDIMS="0"
+INPUT_FILE_NAME=""
+USE_POLY="0"
+SDC_TYPE=""
+
+while [[ ${#} -gt 0 ]]; do
+
+  key="$1"
+  case $key in
+
+      -c|--class-name)
+
+      if [[ ${#} -lt 2 ]]; then
+        echo "[ERROR]: ${1} expected a value."
+        exit 1
+      fi
+
+      CLASS_NAME="$2"
+      echo "[OPT]: Generating class named: ${CLASS_NAME} in implementation file: ${CLASS_NAME}.cxx"
+      shift # past argument
+      ;;
+
+      --MC)
+
+      INPUT_FILE_NAME="SimpleMCStudy.cxx.in"
+      echo "[OPT]: Generating simple MC study stub class."
+      ;;
+
+      --data)
+
+      INPUT_FILE_NAME="SimpleDataComparison.cxx.in"
+      echo "[OPT]: Generating data comparison stub class."
+      NDIMS="1"
+      ;;
+
+      -n|--n-dimensions)
+
+      if [[ ${#} -lt 2 ]]; then
+        echo "[ERROR]: ${1} expected a value."
+        exit 1
+      fi
+
+      NDIMS="${2}"
+      echo "[OPT]: Using a ${NDIMS} dimensional comparison"
+      shift # past argument
+      ;;
+
+      --poly)
+
+      USE_POLY="1"
+      echo "[OPT]: Using a TH2Poly comparion."
+      ;;
+
+      -?|--help)
+
+      echo "[RUNLIKE] ${SCRIPTNAME}"
+      echo -e "\t-c|--class-name            : Name of generated event processor"
+      echo -e "\t                             class."
+      echo -e "\t--MC                       : Generate a simple MC study shell."
+      echo -e "\t--data                     : Generate a 'sample' shell."
+      echo -e "\t-n|--n-dimensions          : Dimension of the data comparison"
+      echo -e "\t                             <default = 1>. Only valid for"
+      echo -e "\t                             --data (Currently can only be 1"
+      echo -e "\t                             or 2)."
+      echo -e "\t--poly                     : Build data comparison using"
+      echo -e "\t                             TH2Poly. Only valid for --data "
+      echo -e "\t                             -n 2"
+      echo -e "\t-?|--help                  : Print this message."
+      exit 0
+      ;;
+
+      *)
+              # unknown option
+      echo "Unknown option $1"
+      exit 1
+      ;;
+
+  esac
+  shift
+done
+
+if [ ${INPUT_FILE_NAME} == "SimpleDataComparison.cxx.in" ]; then
+  if [ ${NDIMS} == "1" ]; then
+    SDC_TYPE=SimpleDataComparison_1D
+  elif [ ${NDIMS} == "2" ]; then
+    if [ ${USE_POLY} == "1" ]; then
+      SDC_TYPE=SimpleDataComparison_2DPoly
+    else
+      SDC_TYPE=SimpleDataComparison_2D
+    fi
+  else
+    echo "[ERROR]: Can only currently set dimensionality to 1 or 2 dimensions."
+    exit 1
+  fi
+fi
+
+if [ -e ${CLASS_NAME}.cxx ]; then
+  echo "[ERROR]: ${CLASS_NAME}.cxx already exists, not overwriting. Please use a different class name."
+  exit 2
+fi
+
+cp @CMAKE_INSTALL_PREFIX@/file_stubs/${INPUT_FILE_NAME} ${CLASS_NAME}.cxx
+
+sed -i "s/__SAMPLE_NAME__/${CLASS_NAME}/g" ${CLASS_NAME}.cxx
+if [ ! -z ${SDC_TYPE} ]; then
+  sed -i "s/__SDC_TYPE__/${SDC_TYPE}/g" ${CLASS_NAME}.cxx
+fi
+
+echo "[INFO]: Generated ${CLASS_NAME}.cxx"
diff --git a/cmake/setup.sh.in b/scripts/to_configure/setup.sh.in
similarity index 100%
rename from cmake/setup.sh.in
rename to scripts/to_configure/setup.sh.in
diff --git a/scripts/dumpgenieconfig.py b/scripts_old/dumpgenieconfig.py
similarity index 100%
rename from scripts/dumpgenieconfig.py
rename to scripts_old/dumpgenieconfig.py
diff --git a/scripts/maketarball.sh b/scripts_old/maketarball.sh
similarity index 100%
rename from scripts/maketarball.sh
rename to scripts_old/maketarball.sh
diff --git a/scripts/nuiscardgen b/scripts_old/nuiscardgen
similarity index 100%
rename from scripts/nuiscardgen
rename to scripts_old/nuiscardgen
diff --git a/scripts/nuissamples b/scripts_old/nuissamples
similarity index 100%
rename from scripts/nuissamples
rename to scripts_old/nuissamples
diff --git a/scripts/plotlimitdist.py b/scripts_old/plotlimitdist.py
similarity index 100%
rename from scripts/plotlimitdist.py
rename to scripts_old/plotlimitdist.py
diff --git a/scripts/plotnuiscomp.py b/scripts_old/plotnuiscomp.py
similarity index 100%
rename from scripts/plotnuiscomp.py
rename to scripts_old/plotnuiscomp.py
diff --git a/scripts/plotnuismin.py b/scripts_old/plotnuismin.py
similarity index 100%
rename from scripts/plotnuismin.py
rename to scripts_old/plotnuismin.py
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index b615e75..d5b8f1d 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,15 +1,16 @@
 add_subdirectory(config)
 add_subdirectory(event)
+add_subdirectory(exception)
+add_subdirectory(generator)
 add_subdirectory(input)
+add_subdirectory(parameters)
+add_subdirectory(persistency)
 add_subdirectory(plugins)
+add_subdirectory(samples)
 add_subdirectory(utility)
-add_subdirectory(generator)
-add_subdirectory(persistency)
-add_subdirectory(parameters)
 add_subdirectory(variation)
 
-add_subdirectory(samples)
 SET(INuADataComparisons_List ${INuADataComparisons_List} PARENT_SCOPE)
 SET(INuADataComparisons_FHiCL ${INuADataComparisons_FHiCL} PARENT_SCOPE)
 
 add_subdirectory(app)
diff --git a/src/samples/CMakeLists.txt b/src/samples/CMakeLists.txt
index a31710c..6313da0 100644
--- a/src/samples/CMakeLists.txt
+++ b/src/samples/CMakeLists.txt
@@ -1,23 +1,24 @@
 set(samples_header_files
   IEventProcessor.hxx
   IDataComparison.hxx
-  SimpleDataComparison.hxx)
+  SimpleDataComparison.hxx
+  SimpleMCStudy.hxx)
 
 install(FILES ${samples_header_files} DESTINATION include/samples)
 
 add_subdirectory(MCTools)
 
 add_subdirectory(nuA)
 
 cmessage(DEBUG "INuADataComparisons: ${INuADataComparisons}")
 
 SET(INuADataComparisons_List)
 if(NOT IDataComparisons STREQUAL "")
   string(REPLACE ";" ", " INuADataComparisons_List "${INuADataComparisons}")
 endif()
 
 cmessage(DEBUG "INuADataComparisons_List: ${INuADataComparisons_List}")
 
 
 SET(INuADataComparisons_List ${INuADataComparisons_List} PARENT_SCOPE)
 SET(INuADataComparisons_FHiCL ${INuADataComparisons_FHiCL} PARENT_SCOPE)
diff --git a/src/samples/SimpleDataComparison.hxx b/src/samples/SimpleDataComparison.hxx
index 36f8e7a..a63e4df 100644
--- a/src/samples/SimpleDataComparison.hxx
+++ b/src/samples/SimpleDataComparison.hxx
@@ -1,424 +1,426 @@
 // Copyright 2018 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 SAMPLES_SIMPLEDATACOMPARISON_HXX_SEEN
-#define SAMPLES_SIMPLEDATACOMPARISON_HXX_SEEN
+#pragma once
 
 #include "samples/IDataComparison.hxx"
 
 #include "event/FullEvent.hxx"
 
 #include "input/InputManager.hxx"
 
 #include "persistency/ROOTOutput.hxx"
 
 #include "utility/FileSystemUtility.hxx"
 #include "utility/HistogramUtility.hxx"
 #include "utility/KinematicUtility.hxx"
 #include "utility/ROOTUtility.hxx"
 #include "utility/StatsUtility.hxx"
 
 #include <array>
 #include <functional>
 #include <limits>
 #include <memory>
 #include <vector>
 
-template <size_t NDim, typename NumericT = double,
-          typename HT = typename nuis::utility::HType_Helper<NDim, void>::type>
+template <size_t nd, typename NumericT = double,
+          typename HT = typename nuis::utility::HType_Helper<nd, void>::type>
 class SimpleDataComparison : public IDataComparison {
 
   NEW_NUIS_EXCEPT(invalid_SimpleDataComparison_initialization);
   NEW_NUIS_EXCEPT(SimpleDataComparison_already_finalized);
 
 protected:
   using HistType = HT;
   using TH_Help = typename nuis::utility::TH_Helper<HistType>;
 
+  static size_t const NDim = nd;
+
   nuis::input::InputManager::Input_id_t fIH_id;
   std::string write_directory;
   size_t NMaxSample_override;
   int fIsShapeOnly;
   int fIsFluxUnfolded;
 
   std::vector<bool> fSignalCache;
   std::vector<std::array<NumericT, NDim>> fProjectionCache;
 
   std::string fDataInputDescriptor;
   std::unique_ptr<HistType> fData;
   std::string fMaskInputDescriptor;
   std::unique_ptr<HistType> fMask;
   std::string fCovarianceInputDescriptor;
   std::unique_ptr<TH2> fCovariance;
   std::unique_ptr<HistType> fPrediction;
   std::unique_ptr<HistType> fPrediction_xsec;
   std::unique_ptr<HistType> fPrediction_shape;
   std::unique_ptr<HistType> fPrediction_comparison;
   bool fComparisonFinalized;
 
   std::string fJournalReference;
   std::string fTargetMaterial;
   std::string fFluxDescription;
   std::string fSignalDescription;
 
   nuis::utility::ENuRange energy_cut;
 
   std::function<bool(nuis::event::FullEvent const &)> IsSigFunc;
   std::function<std::array<NumericT, NDim>(nuis::event::FullEvent const &)>
       CompProjFunc;
 
   // If assigned by subclass will be called on for all events, bool signifies
   // whether the event was selected.
   std::function<void(nuis::event::FullEvent const &, bool, double)>
       ProcessExtraFunc;
 
 public:
   SimpleDataComparison() {
     fIH_id = std::numeric_limits<nuis::input::InputManager::Input_id_t>::max();
     write_directory = "";
     NMaxSample_override = std::numeric_limits<size_t>::max();
     fDataInputDescriptor = "";
     fData = nullptr;
     fMaskInputDescriptor = "";
     fMask = nullptr;
     fCovarianceInputDescriptor = "";
     fCovariance = nullptr;
     fPrediction = nullptr;
     fPrediction_xsec = nullptr;
     fPrediction_shape = nullptr;
     fPrediction_comparison = nullptr;
     fComparisonFinalized = false;
     IsSigFunc = [](nuis::event::FullEvent const &) -> bool { return true; };
     CompProjFunc =
         [](nuis::event::FullEvent const &) -> std::array<NumericT, NDim> {
       std::array<NumericT, NDim> arr;
       for (NumericT &el : arr) {
         el = 0;
       }
       return arr;
     };
 
     ProcessExtraFunc =
         std::function<void(nuis::event::FullEvent const &, bool, double)>();
 
     fJournalReference = "";
     fTargetMaterial = "";
     fFluxDescription = "";
     fSignalDescription = "";
     fIsShapeOnly = -1;
     fIsFluxUnfolded = -1;
 
     energy_cut = nuis::utility::ENuRange{std::numeric_limits<double>::max(),
                                          std::numeric_limits<double>::max()};
   }
 
   fhicl::ParameterSet fGlobalConfig;
   fhicl::ParameterSet fInstanceConfig;
 
   void ReadGlobalConfigDefaults() {
     fGlobalConfig = nuis::config::GetDocument().get<fhicl::ParameterSet>(
         std::string("global.sample_configuration.") + Name(),
         fhicl::ParameterSet());
 
     if (!fJournalReference.length()) {
       fJournalReference = fGlobalConfig.get<std::string>("journal_reference",
                                                          fJournalReference);
     }
     if (!fTargetMaterial.length()) {
       fTargetMaterial =
           fGlobalConfig.get<std::string>("target_material", fTargetMaterial);
     }
     if (!fFluxDescription.length()) {
       fFluxDescription =
           fGlobalConfig.get<std::string>("flux_description", fFluxDescription);
     }
     if (!fSignalDescription.length()) {
       fSignalDescription = fGlobalConfig.get<std::string>("signal_description",
                                                           fSignalDescription);
     }
 
     if (fIsShapeOnly == -1) {
       fIsShapeOnly = fGlobalConfig.get<bool>("shape_only", false);
     }
     if (fIsFluxUnfolded == -1) {
       fIsFluxUnfolded = fGlobalConfig.get<bool>("flux_unfolded", false);
     }
 
     if ((energy_cut.first == std::numeric_limits<double>::max()) &&
         (fGlobalConfig.has_key("enu_range"))) {
       energy_cut = fGlobalConfig.get<std::pair<double, double>>("enu_range");
     }
   }
 
   virtual std::string GetJournalReference() { return fJournalReference; }
   virtual std::string GetTargetMaterial() { return fTargetMaterial; }
   virtual std::string GetFluxDescription() { return fFluxDescription; }
   virtual std::string GetSignalDescription() { return fSignalDescription; }
 
   void SetShapeOnly(bool iso) { fIsShapeOnly = iso; }
   void SetFluxUnfolded(bool ifo) { fIsFluxUnfolded = ifo; }
 
   void SetData(std::string const &data_descriptor) {
     fDataInputDescriptor = data_descriptor;
   }
 
   void SetMask(std::string const &mask_descriptor) {
     fMaskInputDescriptor = mask_descriptor;
   }
 
   void SetCovariance(std::string const &cov_descriptor) {
     fCovarianceInputDescriptor = cov_descriptor;
   }
 
   virtual void FillProjection(std::array<NumericT, NDim> const &proj,
                               NumericT event_weight) {
     TH_Help::Fill(fPrediction, proj, event_weight);
   }
 
   virtual void FinalizeComparison() {
     if (fComparisonFinalized) {
       throw SimpleDataComparison_already_finalized()
           << "[ERROR]: Attempted to re-finalize a comparison for "
              "SimpleDataComparison: "
           << std::quoted(Name());
     }
     fPrediction_xsec =
         nuis::utility::Clone(fPrediction, false, "Prediction_xsec");
 
     IInputHandler const &IH =
         nuis::input::InputManager::Get().GetInputHandler(fIH_id);
 
     TH_Help::Scale(fPrediction_xsec, 1.0, "width");
 
     // If we have a flux cut
     if (energy_cut.first != std::numeric_limits<double>::max()) {
       TH_Help::Scale(fPrediction_xsec, IH.GetXSecScaleFactor(energy_cut));
     }
 
     fPrediction_shape =
         nuis::utility::Clone(fPrediction_xsec, false, "Prediction_shape");
     if (fData) {
       TH_Help::Scale(fPrediction_shape,
                      TH_Help::Integral(fData, "width") /
                          TH_Help::Integral(fPrediction_shape, "width"));
 
     } else {
       IEventProcessor_WARN(
           "When Finalizing comparison, no Data histogram available.");
     }
 
     if (fIsFluxUnfolded) {
       // fPrediction_comparison
     } else if (fIsShapeOnly) {
       fPrediction_comparison = nuis::utility::Clone(fPrediction_shape, false,
                                                     "Prediction_comparison");
     } else {
       fPrediction_comparison = nuis::utility::Clone(fPrediction_xsec, false,
                                                     "Prediction_comparison");
     }
     fComparisonFinalized = true;
   }
 
   void Initialize(fhicl::ParameterSet const &instance_sample_configuration) {
 
     fInstanceConfig = instance_sample_configuration;
 
     if (fInstanceConfig.has_key("verbosity")) {
       SetSampleVerbosity(fInstanceConfig.get<std::string>("verbosity"));
     } else {
       SetSampleVerbosity("Reticent");
     }
 
     ReadGlobalConfigDefaults();
 
     if (fInstanceConfig.has_key("fake_data")) {
       fData = nuis::utility::GetHistogram<HistType>(
           fInstanceConfig.get<std::string>("fake_data_histogram"));
     } else if (!fGlobalConfig.get<bool>("has_data", true) ||
                !fInstanceConfig.get<bool>("has_data", true)) {
       // Explicitly not expecting data
     } else {
       if (!fDataInputDescriptor.length()) {
         if (!fGlobalConfig.has_key("data_descriptor")) {
           throw invalid_SimpleDataComparison_initialization()
               << "[ERROR]: SimpleDataComparison::Initialize for "
                  "IDataComparison: "
               << std::quoted(Name())
               << " failed as no input data was set by a call to "
                  "SimpleDataComparison::SetData and no data_descriptor for "
                  "this SimpleDataComparison could be found in the global "
                  "configuration.";
         }
         fDataInputDescriptor =
             fGlobalConfig.get<std::string>("data_descriptor");
       }
       fData = nuis::utility::GetHistogram<HistType>(fDataInputDescriptor);
     }
 
     if (!fPrediction) {
       if (!fData) {
         throw invalid_SimpleDataComparison_initialization()
             << "[ERROR]: SimpleDataComparison::Initialize for "
                "IDataComparison: "
             << std::quoted(Name())
             << " failed. As `has_data: false` was set in the configuration  "
                "(global: "
             << (!fGlobalConfig.get<bool>("has_data", true))
             << ", instance: " << !fInstanceConfig.get<bool>("has_data", true)
             << "), the instance constructor must supply the fPrediction "
                "binning, and it wasn't.";
       }
       fPrediction = nuis::utility::Clone(fData, true, "Prediction");
     }
 
     if (fCovarianceInputDescriptor.length()) {
       fCovariance =
           nuis::utility::GetHistogram<TH2D>(fCovarianceInputDescriptor);
     } else if (fGlobalConfig.has_key("covariance_descriptor")) {
       fCovariance = nuis::utility::GetHistogram<TH2D>(
           fGlobalConfig.get<std::string>("covariance_descriptor"));
     }
 
     if (fMaskInputDescriptor.length()) {
       fMask = nuis::utility::GetHistogram<HistType>(fMaskInputDescriptor);
     } else if (fGlobalConfig.has_key("mask_descriptor")) {
       fMask = nuis::utility::GetHistogram<HistType>(
           fGlobalConfig.get<std::string>("mask_descriptor"));
     }
 
     if (fInstanceConfig.has_key("verbosity")) {
       SetSampleVerbosity(fInstanceConfig.get<std::string>("verbosity"));
     }
 
     NMaxSample_override =
         fInstanceConfig.get<size_t>("nmax", std::numeric_limits<size_t>::max());
 
     write_directory =
         fInstanceConfig.get<std::string>("write_directory", Name());
 
     fIH_id =
         nuis::input::InputManager::Get().EnsureInputLoaded(fInstanceConfig);
   }
 
   void ProcessSample(size_t nmax = std::numeric_limits<size_t>::max()) {
     if (fIH_id ==
         std::numeric_limits<nuis::input::InputManager::Input_id_t>::max()) {
       throw uninitialized_IEventProcessor();
     }
     IInputHandler const &IH =
         nuis::input::InputManager::Get().GetInputHandler(fIH_id);
 
     nmax = std::min(NMaxSample_override, nmax);
 
     size_t NEvsToProcess = std::min(nmax, IH.GetNEvents());
 
     double nmax_scaling = double(IH.GetNEvents()) / double(NEvsToProcess);
 
     size_t NToShout = NEvsToProcess / 10;
     IEventProcessor_INFO("Sample " << std::quoted(Name()) << " processing "
                                    << NEvsToProcess << " events.");
 
     IInputHandler::ev_index_t ev_idx = 0;
 
     bool DetermineSignalEvents = !fSignalCache.size();
 
     nuis::utility::Clear<HistType>(*fPrediction);
     fComparisonFinalized = false;
 
     size_t cache_ctr = 0;
 
     while (ev_idx < NEvsToProcess) {
       if (DetermineSignalEvents) {
         nuis::event::FullEvent const &fev = IH.GetFullEvent(ev_idx);
         bool is_sig = IsSigFunc(fev);
         fSignalCache.push_back(is_sig);
         if (is_sig) {
           fProjectionCache.push_back(CompProjFunc(fev));
         }
         if (ProcessExtraFunc) {
           ProcessExtraFunc(fev, is_sig,
                            IH.GetEventWeight(ev_idx) * nmax_scaling);
         }
       }
 
       if (NToShout && !(ev_idx % NToShout)) {
         IEventProcessor_INFO("\tProcessed " << ev_idx << "/" << NEvsToProcess
                                             << " events.");
       }
 
       if (fSignalCache[ev_idx]) {
         FillProjection(fProjectionCache[cache_ctr++],
                        IH.GetEventWeight(ev_idx) * nmax_scaling);
       }
 
       ev_idx++;
     }
     IEventProcessor_INFO("\t" << fProjectionCache.size() << "/" << NEvsToProcess
                               << " events passed selection.");
   }
   void Write() {
     if (!fComparisonFinalized) {
       FinalizeComparison();
     }
 
     nuis::persistency::WriteToOutputFile<HistType>(
         fPrediction_comparison, "Prediction", write_directory);
     nuis::persistency::WriteToOutputFile<HistType>(
         fPrediction_xsec, "Prediction_xsec", write_directory);
 
     if (fData) {
       nuis::persistency::WriteToOutputFile<HistType>(fData, "Data",
                                                      write_directory);
       nuis::persistency::WriteToOutputFile<HistType>(
           fPrediction_shape, "Prediction_shape", write_directory);
     }
   }
 
   double GetGOF() {
     if (!fComparisonFinalized) {
       FinalizeComparison();
     }
     if (fData && fPrediction_comparison) {
       return nuis::utility::GetChi2(fData, fPrediction_comparison);
     } else
       return std::numeric_limits<double>::max();
   }
   double GetNDOGuess() {
     if (fData) {
       return TH_Help::Nbins(fData);
     }
     return 0;
   }
 
   fhicl::ParameterSet GetExampleConfiguration() {
     fhicl::ParameterSet exps;
     exps.put<std::string>("name", Name());
     exps.put<std::string>("input_type", "Generator");
     exps.put<std::string>("file", "Events.root");
     exps.put<std::string>("write_directory", Name());
     exps.put<std::string>("fake_data_histogram", "/path/to/file.root;h_name");
 
     return exps;
   }
 };
 
-typedef SimpleDataComparison<1> SimpleDataComparison_1D;
-typedef SimpleDataComparison<2> SimpleDataComparison_2D;
-
-#endif
+typedef SimpleDataComparison<1, double, TH1D> SimpleDataComparison_1D;
+typedef SimpleDataComparison<2, double, TH2D> SimpleDataComparison_2D;
+typedef SimpleDataComparison<1, float, TH1F> SimpleDataComparison_1F;
+typedef SimpleDataComparison<2, float, TH2F> SimpleDataComparison_2F;
+typedef SimpleDataComparison<2, double, TH2Poly> SimpleDataComparison_2DPoly;
diff --git a/src/samples/SimpleMCStudy.hxx b/src/samples/SimpleMCStudy.hxx
new file mode 100644
index 0000000..c8a55d5
--- /dev/null
+++ b/src/samples/SimpleMCStudy.hxx
@@ -0,0 +1,108 @@
+// Copyright 2018 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/>.
+ *******************************************************************************/
+
+#pragma once
+
+#include "samples/IEventProcessor.hxx"
+
+#include "event/FullEvent.hxx"
+
+#include "input/InputManager.hxx"
+
+#include <functional>
+
+class SimpleMCStudy : public IEventProcessor {
+protected:
+  nuis::input::InputManager::Input_id_t fIH_id;
+  std::string write_directory;
+  size_t NMaxSample_override;
+
+  std::function<void(nuis::event::FullEvent const &, double)>
+      ProcessEventFunction;
+
+public:
+  SimpleMCStudy() {
+    fIH_id = std::numeric_limits<nuis::input::InputManager::Input_id_t>::max();
+    write_directory = "";
+    NMaxSample_override = std::numeric_limits<size_t>::max();
+
+    ProcessEventFunction = std::function<void(nuis::event::FullEvent const &, double)>();
+  }
+
+  fhicl::ParameterSet fGlobalConfig;
+  fhicl::ParameterSet fInstanceConfig;
+
+  void ReadGlobalConfigDefaults() {
+    fGlobalConfig = nuis::config::GetDocument().get<fhicl::ParameterSet>(
+        std::string("global.sample_configuration.") + Name(),
+        fhicl::ParameterSet());
+  }
+
+  void Initialize(fhicl::ParameterSet const &instance_sample_configuration) {
+
+    fInstanceConfig = instance_sample_configuration;
+
+    if (fInstanceConfig.has_key("verbosity")) {
+      SetSampleVerbosity(fInstanceConfig.get<std::string>("verbosity"));
+    } else {
+      SetSampleVerbosity("Reticent");
+    }
+
+    ReadGlobalConfigDefaults();
+
+    NMaxSample_override =
+        fInstanceConfig.get<size_t>("nmax", std::numeric_limits<size_t>::max());
+
+    write_directory =
+        fInstanceConfig.get<std::string>("write_directory", Name());
+
+    fIH_id =
+        nuis::input::InputManager::Get().EnsureInputLoaded(fInstanceConfig);
+  }
+
+  void ProcessSample(size_t nmax = std::numeric_limits<size_t>::max()) {
+    if (fIH_id ==
+        std::numeric_limits<nuis::input::InputManager::Input_id_t>::max()) {
+      throw uninitialized_IEventProcessor();
+    }
+    IInputHandler const &IH =
+        nuis::input::InputManager::Get().GetInputHandler(fIH_id);
+
+    nmax = std::min(NMaxSample_override, nmax);
+
+    size_t NEvsToProcess = std::min(nmax, IH.GetNEvents());
+
+    double nmax_scaling = double(IH.GetNEvents()) / double(NEvsToProcess);
+
+    size_t NToShout = NEvsToProcess / 10;
+    IEventProcessor_INFO("Sample " << std::quoted(Name()) << " processing "
+                                   << NEvsToProcess << " events.");
+
+    IInputHandler::ev_index_t ev_idx = 0;
+
+    while (ev_idx < NEvsToProcess) {
+      nuis::event::FullEvent const &fev = IH.GetFullEvent(ev_idx);
+      ProcessEventFunction(fev, IH.GetEventWeight(ev_idx) * nmax_scaling);
+      ev_idx++;
+    }
+
+    IEventProcessor_INFO("Sample " << std::quoted(Name()) << " processed "
+                                   << NEvsToProcess << " events.");
+  }
+};