diff --git a/scripts/Diffraction/isis_powder/abstract_inst.py b/scripts/Diffraction/isis_powder/abstract_inst.py
index 62748c1bbc608e4d26b09413a8a49c714f2c7c82..fdde4b4384d088ea9b83b5c936807db9abbd45d6 100644
--- a/scripts/Diffraction/isis_powder/abstract_inst.py
+++ b/scripts/Diffraction/isis_powder/abstract_inst.py
@@ -213,7 +213,7 @@ class AbstractInst(object):
 
         common_output.save_focused_data(d_spacing_group=d_spacing_group, tof_group=tof_group,
                                         output_paths=output_paths, inst_prefix=self._inst_prefix,
-                                        run_number_string=run_details.user_input_run_number)
+                                        run_number_string=run_details.output_run_string)
 
         return d_spacing_group, tof_group
 
@@ -227,7 +227,7 @@ class AbstractInst(object):
         """
         output_directory = os.path.join(self._output_dir, run_details.label, self._user_name)
         output_directory = os.path.abspath(os.path.expanduser(output_directory))
-        file_name = str(self._generate_output_file_name(run_number_string=run_details.user_input_run_number))
+        file_name = str(self._generate_output_file_name(run_number_string=run_details.output_run_string))
         nxs_file = os.path.join(output_directory, (file_name + ".nxs"))
         gss_file = os.path.join(output_directory, (file_name + ".gsas"))
         tof_xye_file = os.path.join(output_directory, (file_name + "_tof_xye.dat"))
diff --git a/scripts/Diffraction/isis_powder/gem.py b/scripts/Diffraction/isis_powder/gem.py
index e98c0de52bf31323fd666fc390ed837f2a222727..30b461217f7e991c679f98a9bbfef498aaf85c4d 100644
--- a/scripts/Diffraction/isis_powder/gem.py
+++ b/scripts/Diffraction/isis_powder/gem.py
@@ -62,6 +62,9 @@ class Gem(AbstractInst):
     def _crop_van_to_expected_tof_range(self, van_ws_to_crop):
         return common.crop_banks_using_crop_list(van_ws_to_crop, self._inst_settings.vanadium_cropping_values)
 
+    def _get_input_batching_mode(self):
+        return self._inst_settings.input_batching
+
     def _get_sample_empty(self):
         sample_empty = self._inst_settings.sample_empty
         if sample_empty:
diff --git a/scripts/Diffraction/isis_powder/gem_routines/gem_advanced_config.py b/scripts/Diffraction/isis_powder/gem_routines/gem_advanced_config.py
index 68e2ae0e2faaafd22a32990f7531677bcdbc9421..1f0ba9ce0b775fcb9fb7f18eb8e8c11a51e6f443 100644
--- a/scripts/Diffraction/isis_powder/gem_routines/gem_advanced_config.py
+++ b/scripts/Diffraction/isis_powder/gem_routines/gem_advanced_config.py
@@ -8,7 +8,7 @@ absorption_correction_params = {
     "cylinder_position": [0., 0., 0.],
 
     "chemical_formula": "V0.9486 Nb0.0514",  # V 94.86% Nb 5.14%
-    "number_density": 0.07216
+    "number_density": 0.071
 }
 
 
diff --git a/scripts/Diffraction/isis_powder/gem_routines/gem_algs.py b/scripts/Diffraction/isis_powder/gem_routines/gem_algs.py
index bd55d63e15d6e3f7b9c41891b593d3c68b6ad9f6..b372b05df7140d3442aa137d61b494761c632774 100644
--- a/scripts/Diffraction/isis_powder/gem_routines/gem_algs.py
+++ b/scripts/Diffraction/isis_powder/gem_routines/gem_algs.py
@@ -46,7 +46,7 @@ def get_run_details(run_number_string, inst_settings):
     run_details.empty_runs = empty_runs
     # Rarely used attribute so we will leave it as optional
     run_details.sample_empty = inst_settings.sample_empty if hasattr(inst_settings, "sample_empty") else None
-    run_details.user_input_run_number = run_number_string
+    run_details.output_run_string = run_number_string
     run_details.label = label
     run_details.vanadium_run_numbers = vanadium_runs
 
diff --git a/scripts/Diffraction/isis_powder/gem_routines/gem_param_mapping.py b/scripts/Diffraction/isis_powder/gem_routines/gem_param_mapping.py
index 0d23b3a0874b13507e10d140628cea7a6052749c..2ba72497b9c7292e2dbcf259d2685af50ad27438 100644
--- a/scripts/Diffraction/isis_powder/gem_routines/gem_param_mapping.py
+++ b/scripts/Diffraction/isis_powder/gem_routines/gem_param_mapping.py
@@ -13,8 +13,8 @@ attr_mapping = \
      ParamMapEntry(ext_name="do_absorb_corrections",     int_name="do_absorb_corrections"),
      ParamMapEntry(ext_name="focused_cropping_values",   int_name="focused_cropping_values"),
      ParamMapEntry(ext_name="grouping_file_name",        int_name="grouping_file_name"),
-     ParamMapEntry(ext_name="input_mode", int_name="input_batching", enum_class=INPUT_BATCHING),
-     ParamMapEntry(ext_name="mode", int_name="mode", enum_class=GEM_CHOPPER_MODES),
+     ParamMapEntry(ext_name="input_mode",                int_name="input_batching", enum_class=INPUT_BATCHING),
+     ParamMapEntry(ext_name="mode",                      int_name="mode", enum_class=GEM_CHOPPER_MODES),
      ParamMapEntry(ext_name="multiple_scattering",       int_name="multiple_scattering"),
      ParamMapEntry(ext_name="raw_tof_cropping_values",   int_name="raw_tof_cropping_values"),
      ParamMapEntry(ext_name="run_in_range",              int_name="run_in_range"),
@@ -22,8 +22,8 @@ attr_mapping = \
      ParamMapEntry(ext_name="sample_empty",              int_name="sample_empty", optional=True),
      ParamMapEntry(ext_name="spline_coefficient",        int_name="spline_coeff"),
      ParamMapEntry(ext_name="output_directory",          int_name="output_dir"),
-     ParamMapEntry(ext_name="unit_to_keep", int_name="unit_to_keep",
-                   enum_class=WORKSPACE_UNITS, optional=True),
+     ParamMapEntry(ext_name="unit_to_keep",              int_name="unit_to_keep",
+                   enum_class=WORKSPACE_UNITS,           optional=True),
      ParamMapEntry(ext_name="user_name",                 int_name="user_name"),
      ParamMapEntry(ext_name="vanadium_cropping_values",  int_name="vanadium_cropping_values"),
      ParamMapEntry(ext_name="vanadium_normalisation",    int_name="do_van_norm")
diff --git a/scripts/Diffraction/isis_powder/pearl.py b/scripts/Diffraction/isis_powder/pearl.py
index 4b33c9dd59811e8e3adfda1396558dfe64bbe8c0..e27a6e3600ad3077a9c38471332d874e835347cf 100644
--- a/scripts/Diffraction/isis_powder/pearl.py
+++ b/scripts/Diffraction/isis_powder/pearl.py
@@ -103,7 +103,7 @@ class Pearl(AbstractInst):
             pearl_output.generate_and_save_focus_output(self, processed_spectra=processed_spectra,
                                                         run_details=run_details, focus_mode=output_mode,
                                                         perform_attenuation=self._inst_settings.perform_atten)
-        group_name = "PEARL" + str(run_details.user_input_run_number)
+        group_name = "PEARL" + str(run_details.output_run_string)
         group_name += '_' + self._inst_settings.tt_mode + "-Results-D-Grp"
         grouped_d_spacing = mantid.GroupWorkspaces(InputWorkspaces=output_spectra, OutputWorkspace=group_name)
         return grouped_d_spacing, None
diff --git a/scripts/Diffraction/isis_powder/pearl_routines/pearl_algs.py b/scripts/Diffraction/isis_powder/pearl_routines/pearl_algs.py
index 770159e86d255ba97f03fefbe34bb9f19fa11d4c..5d0e4cea4d5327123d9c4520eec7fc925558b946 100644
--- a/scripts/Diffraction/isis_powder/pearl_routines/pearl_algs.py
+++ b/scripts/Diffraction/isis_powder/pearl_routines/pearl_algs.py
@@ -99,7 +99,7 @@ def get_run_details(run_number_string, inst_settings):
     splined_vanadium_path = os.path.join(cycle_calibration_dir, splined_vanadium_name)
 
     run_details = RunDetails(run_number=first_run_number)
-    run_details.user_input_run_number = run_number_string
+    run_details.output_run_string = run_number_string
     run_details.offset_file_path = calibration_file_path
     run_details.grouping_file_path = grouping_file_path
     run_details.empty_runs = empty_run_numbers
diff --git a/scripts/Diffraction/isis_powder/polaris_routines/polaris_algs.py b/scripts/Diffraction/isis_powder/polaris_routines/polaris_algs.py
index 5610edae2dd52d73c73bc677c89ed5c9a90dfff4..e8bedd0bcee4d16d50027e58deb169951c901929 100644
--- a/scripts/Diffraction/isis_powder/polaris_routines/polaris_algs.py
+++ b/scripts/Diffraction/isis_powder/polaris_routines/polaris_algs.py
@@ -3,8 +3,8 @@ from __future__ import (absolute_import, division, print_function)
 import mantid.simpleapi as mantid
 import os
 
-from isis_powder.routines import absorb_corrections, common, yaml_parser
-from isis_powder.routines.RunDetails import RunDetails
+from isis_powder.routines import absorb_corrections, common
+from isis_powder.routines.RunDetails import RunDetailsFuncWrapper, get_cal_mapping, cal_map_dictionary_key_helper_wrapper
 from isis_powder.polaris_routines import polaris_advanced_config
 
 
@@ -17,45 +17,57 @@ def calculate_absorb_corrections(ws_to_correct, multiple_scattering):
     return ws_to_correct
 
 
-def get_run_details(run_number_string, inst_settings):
-    run_number = common.get_first_run_number(run_number_string=run_number_string)
-    cal_mapping = yaml_parser.get_run_dictionary(run_number_string=run_number, file_path=inst_settings.cal_mapping_file)
-
-    label = common.cal_map_dictionary_key_helper(cal_mapping, "label")
-    offset_file_name = common.cal_map_dictionary_key_helper(cal_mapping, "offset_file_name")
+def get_chopper_config(forwarded_value, inst_settings):
+    # The previous result is a cal_mapping
+    cal_mapping = forwarded_value
 
     if inst_settings.chopper_on:
         chopper_config = common.cal_map_dictionary_key_helper(cal_mapping, "chopper_on")
     else:
         chopper_config = common.cal_map_dictionary_key_helper(cal_mapping, "chopper_off")
 
-    err_message = "This must be under the relevant chopper_on / chopper_off section."
-    empty_runs = common.cal_map_dictionary_key_helper(chopper_config, "empty_run_numbers", err_message)
-    vanadium_runs = common.cal_map_dictionary_key_helper(chopper_config, "vanadium_run_numbers", err_message)
+    return chopper_config
 
-    grouping_full_path = os.path.normpath(os.path.expanduser(inst_settings.calibration_dir))
-    grouping_full_path = os.path.join(grouping_full_path, inst_settings.grouping_file_name)
 
-    in_calib_dir = os.path.join(inst_settings.calibration_dir, label)
-    offsets_file_full_path = os.path.join(in_calib_dir, offset_file_name)
+def get_run_details(run_number_string, inst_settings):
+    # Forward result from get_cal_mapping to get_chopper_config
+    chopper_config_callable = RunDetailsFuncWrapper().\
+        add_to_func_chain(function=get_cal_mapping, run_number_string=run_number_string, inst_settings=inst_settings).\
+        add_to_func_chain(function=get_chopper_config, inst_settings=inst_settings)
 
-    # Generate the name of the splined file we will either be loading or saving
-    chopper_status = "ChopperOn" if inst_settings.chopper_on else "ChopperOff"
-    splined_vanadium_name = common.generate_splined_name(vanadium_runs, chopper_status, offset_file_name)
+    err_message = "This must be under the relevant chopper_on / chopper_off section."
+    empty_runs_callable = chopper_config_callable.add_to_func_chain(cal_map_dictionary_key_helper_wrapper,
+                                                                    "empty_run_numbers", err_message)
 
-    splined_vanadium = os.path.join(in_calib_dir, splined_vanadium_name)
+    vanadium_runs_callable = chopper_config_callable.add_to_func_chain(cal_map_dictionary_key_helper_wrapper,
+                                                                       "vanadium_run_numbers", err_message)
 
-    run_details = RunDetails(run_number=run_number)
-    run_details.user_input_run_number = run_number_string
-    run_details.empty_runs = empty_runs
-    run_details.vanadium_run_numbers = vanadium_runs
-    run_details.label = label
+    empty_runs = empty_runs_callable.get_result()
+    van_runs = vanadium_runs_callable.get_result()
 
-    run_details.offset_file_path = offsets_file_full_path
-    run_details.grouping_file_path = grouping_full_path
-    run_details.splined_vanadium_file_path = splined_vanadium
+    grouping_full_path = os.path.normpath(os.path.expanduser(inst_settings.calibration_dir))
+    grouping_full_path = os.path.join(grouping_full_path, inst_settings.grouping_file_name)
 
-    return run_details
+    #in_calib_dir = os.path.join(inst_settings.calibration_dir, label)
+    #offsets_file_full_path = os.path.join(in_calib_dir, offset_file_name)
+#
+    ## Generate the name of the splined file we will either be loading or saving
+    #chopper_status = "ChopperOn" if inst_settings.chopper_on else "ChopperOff"
+    #splined_vanadium_name = common.generate_splined_name(vanadium_runs, chopper_status, offset_file_name)
+#
+    #splined_vanadium = os.path.join(in_calib_dir, splined_vanadium_name)
+#
+    #run_details = RunDetails(run_number=run_number)
+    #run_details.output_run_string = run_number_string
+    #run_details.empty_runs = empty_runs
+    #run_details.vanadium_run_numbers = vanadium_runs
+    #run_details.label = label
+#
+    #run_details.offset_file_path = offsets_file_full_path
+    #run_details.grouping_file_path = grouping_full_path
+    #run_details.splined_vanadium_file_path = splined_vanadium
+#
+    #return run_details
 
 
 def process_vanadium_for_focusing(bank_spectra, mask_path, spline_number):
diff --git a/scripts/Diffraction/isis_powder/polaris_routines/polaris_param_mapping.py b/scripts/Diffraction/isis_powder/polaris_routines/polaris_param_mapping.py
index e7b9be85d85a2ab865c96a17fa6d7ea9821a409a..e5634b076f621807c7a69fe02a2c58c55d0d1dca 100644
--- a/scripts/Diffraction/isis_powder/polaris_routines/polaris_param_mapping.py
+++ b/scripts/Diffraction/isis_powder/polaris_routines/polaris_param_mapping.py
@@ -14,7 +14,7 @@ attr_mapping = \
      ParamMapEntry(ext_name="do_van_normalisation",     int_name="do_van_normalisation"),
      ParamMapEntry(ext_name="focused_cropping_values",  int_name="focused_cropping_values"),
      ParamMapEntry(ext_name="grouping_file_name",       int_name="grouping_file_name"),
-     ParamMapEntry(ext_name="input_mode", int_name="input_mode", enum_class=INPUT_BATCHING),
+     ParamMapEntry(ext_name="input_mode",               int_name="input_mode", enum_class=INPUT_BATCHING),
      ParamMapEntry(ext_name="masking_file_name",        int_name="masking_file_name"),
      ParamMapEntry(ext_name="multiple_scattering",      int_name="multiple_scattering"),
      ParamMapEntry(ext_name="raw_data_cropping_values", int_name="raw_data_crop_values"),
diff --git a/scripts/Diffraction/isis_powder/routines/RunDetails.py b/scripts/Diffraction/isis_powder/routines/RunDetails.py
index 4f1be4178e3060913378f4e19c0b3a4cf3d10392..c3256eda4b80209be3eaac650386df5f48427ec2 100644
--- a/scripts/Diffraction/isis_powder/routines/RunDetails.py
+++ b/scripts/Diffraction/isis_powder/routines/RunDetails.py
@@ -1,23 +1,95 @@
 from __future__ import (absolute_import, division, print_function)
 
+from isis_powder.routines import common, yaml_parser
+
+
+def create_run_details_object(run_number_string, inst_settings):
+    pass
+
+
+def get_cal_mapping(run_number_string, inst_settings):
+    # Get the python dictionary from the YAML mapping
+    run_number = common.get_first_run_number(run_number_string=run_number_string)
+    cal_mapping_dict = yaml_parser.get_run_dictionary(run_number_string=run_number,
+                                                      file_path=inst_settings.cal_mapping_file)
+
+    return cal_mapping_dict
+
+
+def cal_map_dictionary_key_helper_wrapper(*args, **kwargs):
+    forwarded_value = kwargs.pop("forwarded_value")
+    return common.cal_map_dictionary_key_helper(forwarded_value, *args, **kwargs)
+
+
+class RunDetailsFuncWrapper(object):
+    # Holds a callable method, associated args and return value so we can pass it in
+    # as a single method
+
+    def __init__(self, function=None, func_args=None, func_kwargs=None):
+        self.function = function
+        self.function_args = func_args
+        self.function_kwargs = func_kwargs
+
+        self._previous_callable = None
+        self._returned_value = None
+        self._function_is_executed = False
+
+    def _exec_func(self):
+        forwarded_value = self._previous_callable.get_result() if self._previous_callable else None
+
+        if not self.function:
+            # We maybe are the 0th case just return any values we hold
+            return forwarded_value
+
+        if forwarded_value:
+            self.function_kwargs["forwarded_value"] = forwarded_value
+            self._returned_value = self.function(*self.function_args, **self.function_kwargs)
+        else:
+            self._returned_value = self.function(*self.function_args, **self.function_kwargs)
+
+        self._function_is_executed = True
+
+    def _set_previous_callable(self, previous_callable):
+        if not previous_callable:
+            return None
+        elif not isinstance(previous_callable, RunDetailsFuncWrapper):
+            raise ValueError("previous callable is not a RunDetailsFuncWrapper type")
+
+        self._previous_callable = previous_callable
+
+    def add_to_func_chain(self, function, *args, **kwargs):
+        # Construct a new object that will be the next in line
+        next_in_chain = RunDetailsFuncWrapper(function=function, func_args=args, func_kwargs=kwargs)
+        next_in_chain._set_previous_callable(self)
+        return next_in_chain
+
+    def get_result(self):
+        if not self._function_is_executed:
+            self._exec_func()
+        return self._returned_value
+
 
 class RunDetails(object):
     """
     This class holds the full file paths associated with each run and various other useful attributes
     """
 
-    def __init__(self, run_number):
+    def __init__(self, empty_run_number, run_number, output_run_string, label,
+                 offset_file_path, grouping_file_path, splined_vanadium_path, vanadium_run_number,
+                 sample_empty=None, vanadium_abs_path=None):
         # Essential attribute
+        self.empty_runs = empty_run_number
         self.run_number = run_number
-        self.user_input_run_number = None
+        self.output_run_string = output_run_string
+
+        self.label = label
 
-        self.empty_runs = None
-        self.sample_empty = None
-        self.label = None
+        self.offset_file_path = offset_file_path
+        self.grouping_file_path = grouping_file_path
 
-        self.offset_file_path = None
-        self.grouping_file_path = None
+        self.splined_vanadium_file_path = splined_vanadium_path
+        self.vanadium_run_numbers = vanadium_run_number
 
-        self.splined_vanadium_file_path = None
-        self.vanadium_absorption_path = None
-        self.vanadium_run_numbers = None
+        # Optional
+        self.sample_empty = sample_empty
+        self.vanadium_absorption_path = vanadium_abs_path
diff --git a/scripts/Diffraction/isis_powder/routines/common_output.py b/scripts/Diffraction/isis_powder/routines/common_output.py
index e1870604f7a8112234a43a551e5e16f9a418a542..20c00396e6f8597abb8abc3110baa0c9fbd9f4ce 100644
--- a/scripts/Diffraction/isis_powder/routines/common_output.py
+++ b/scripts/Diffraction/isis_powder/routines/common_output.py
@@ -7,7 +7,7 @@ import os
 def split_into_tof_d_spacing_groups(run_details, processed_spectra):
     d_spacing_output = []
     tof_output = []
-    run_number = str(run_details.user_input_run_number)
+    run_number = str(run_details.output_run_string)
     for name_index, ws in enumerate(processed_spectra):
         d_spacing_out_name = run_number + "-ResultD-" + str(name_index + 1)
         tof_out_name = run_number + "-ResultTOF-" + str(name_index + 1)