diff --git a/scripts/Diffraction/isis_powder/gem.py b/scripts/Diffraction/isis_powder/gem.py
index 553b1b0e9f4f41ed5754d2e02e0e0f335da49c21..13b7c018e1ea956631e643239b5856096f68f9a2 100644
--- a/scripts/Diffraction/isis_powder/gem.py
+++ b/scripts/Diffraction/isis_powder/gem.py
@@ -2,7 +2,7 @@ from __future__ import (absolute_import, division, print_function)
 
 from isis_powder.abstract_inst import AbstractInst
 from isis_powder.gem_routines import gem_advanced_config, gem_algs, gem_param_mapping
-from isis_powder.routines import common, instrument_settings
+from isis_powder.routines import common, instrument_settings, sample_details
 
 
 class Gem(AbstractInst):
@@ -16,6 +16,9 @@ class Gem(AbstractInst):
                                   output_dir=self._inst_settings.output_dir, inst_prefix="GEM")
 
         self._cached_run_details = {}
+        self._sample_details = None
+
+    # Public API
 
     def focus(self, **kwargs):
         self._inst_settings.update_attributes(kwargs=kwargs)
@@ -28,6 +31,18 @@ class Gem(AbstractInst):
         return self._create_vanadium(run_number_string=self._inst_settings.run_in_range,
                                      do_absorb_corrections=self._inst_settings.do_absorb_corrections)
 
+    def set_sample_details(self, **kwargs):
+        sample_details_obj = common.dictionary_key_helper(
+            dictionary=kwargs, key="new_sample_details",
+            exception_msg="The argument containing sample details was not found. Please"
+                          " set the following argument: new_sample_details")
+        if not isinstance(sample_details_obj, sample_details.SampleDetails):
+            raise ValueError("The object passed was not a SampleDetails object. Please create a"
+                             " SampleDetails object and set the relevant properties to use on this method")
+        self._sample_details = sample_details_obj
+
+    # Private methods
+
     def _get_run_details(self, run_number_string):
         run_number_string_key = run_number_string + str(self._inst_settings.file_extension)
         if run_number_string_key in self._cached_run_details:
diff --git a/scripts/Diffraction/isis_powder/polaris.py b/scripts/Diffraction/isis_powder/polaris.py
index 1f841dd02984d7daf47b279d213ab5c9e5ce0ffb..56bb5fab00300d4daf458cc3e1b7b98563ffd7a9 100644
--- a/scripts/Diffraction/isis_powder/polaris.py
+++ b/scripts/Diffraction/isis_powder/polaris.py
@@ -2,7 +2,7 @@ from __future__ import (absolute_import, division, print_function)
 
 import os
 
-from isis_powder.routines import common, instrument_settings
+from isis_powder.routines import common, instrument_settings, sample_details
 from isis_powder.abstract_inst import AbstractInst
 from isis_powder.polaris_routines import polaris_advanced_config, polaris_algs, polaris_param_mapping
 
@@ -19,6 +19,9 @@ class Polaris(AbstractInst):
 
         # Hold the last dictionary later to avoid us having to keep parsing the YAML
         self._run_details_cached_obj = {}
+        self._sample_details = None
+
+    # Public API
 
     def focus(self, **kwargs):
         self._inst_settings.update_attributes(kwargs=kwargs)
@@ -30,6 +33,16 @@ class Polaris(AbstractInst):
         return self._create_vanadium(run_number_string=self._inst_settings.run_in_range,
                                      do_absorb_corrections=self._inst_settings.do_absorb_corrections)
 
+    def set_sample_details(self, **kwargs):
+        sample_details_obj = common.dictionary_key_helper(
+            dictionary=kwargs, key="new_sample_details",
+            exception_msg="The argument containing sample details was not found. Please"
+                          " set the following argument: new_sample_details")
+        if not isinstance(sample_details_obj, sample_details.SampleDetails):
+            raise ValueError("The object passed was not a SampleDetails object. Please create a"
+                             " SampleDetails object and set the relevant properties to use on this method")
+        self._sample_details = sample_details_obj
+
     # Overrides
     def _apply_absorb_corrections(self, run_details, van_ws):
         return polaris_algs.calculate_absorb_corrections(ws_to_correct=van_ws,
diff --git a/scripts/Diffraction/isis_powder/routines/absorb_corrections.py b/scripts/Diffraction/isis_powder/routines/absorb_corrections.py
index 9544d17a12c3ed3beaad6560d21d62cfbadbf397..dfef2920da4aa9ecc13250337024bb69cadadcb1 100644
--- a/scripts/Diffraction/isis_powder/routines/absorb_corrections.py
+++ b/scripts/Diffraction/isis_powder/routines/absorb_corrections.py
@@ -2,22 +2,15 @@ from __future__ import (absolute_import, division, print_function)
 
 import mantid.simpleapi as mantid
 
-from isis_powder.routines import common
+from isis_powder.routines import common, sample_details
 
 
-def run_cylinder_absorb_corrections(ws_to_correct, multiple_scattering, config_dict):
+def create_vanadium_sample_details_obj(config_dict):
     """
-    Sets a cylindrical sample from the user specified config dictionary and performs Mayers
-    sample correction on the workspace. The config dictionary must be for a cylinder and contain
-    the keys "cylinder_sample_height", "cylinder_sample_radius", "cylinder_position" and
-    "chemical_formula". If any of these keys are not found an exception is raise informing
-    the user that the key was not in the advanced configuration file.
-    Additionally it checks the value of multiple_scattering to determine whether to take
-    into account the effects of multiple scattering.
-    :param ws_to_correct: The workspace to perform Mayers sample correction on
-    :param multiple_scattering: Boolean of whether to account for the effects of multiple scattering
-    :param config_dict: A dictionary containing the required keys to set a cylinder sample
-    :return: The corrected workspace
+    Creates a SampleDetails object based on a vanadium sample which is found
+    in the advanced config of an instrument.
+    :param config_dict: The advanced config dictionary of the instrument for the vanadium sample
+    :return: A sample details object which holds properties used in sample corrections
     """
     height_key = "cylinder_sample_height"
     radius_key = "cylinder_sample_radius"
@@ -30,18 +23,37 @@ def run_cylinder_absorb_corrections(ws_to_correct, multiple_scattering, config_d
     height = common.dictionary_key_helper(dictionary=config_dict, key=height_key, exception_msg=e_msg + height_key)
     radius = common.dictionary_key_helper(dictionary=config_dict, key=radius_key, exception_msg=e_msg + radius_key)
     pos = common.dictionary_key_helper(dictionary=config_dict, key=pos_key, exception_msg=e_msg + pos_key)
-
     formula = common.dictionary_key_helper(dictionary=config_dict, key=formula_key, exception_msg=e_msg + formula_key)
-    if len(formula) > 1:
-        # Not a trivial element so we need them to manually specify number density as Mantid
-        # struggles to calculate it
-        number_density = common.dictionary_key_helper(
-            dictionary=config_dict, key=number_density_key,
-            exception_msg="The number density is required as the chemical formula (" + str(formula) + ")"
-            " is not a single element. The number density was not found. Please add the following key: " +
-                          number_density_key)
-    else:
-        number_density = None
+    number_density = common.dictionary_key_helper(dictionary=config_dict, key=number_density_key, throws=False)
+
+    vanadium_sample_details = sample_details.SampleDetails(height=height, radius=radius, pos=pos)
+    vanadium_sample_details.set_material(chemical_formula=formula, number_density=number_density)
+    return vanadium_sample_details
+
+
+def run_cylinder_absorb_corrections(ws_to_correct, multiple_scattering, sample_details_obj):
+    """
+    Sets a cylindrical sample from the user specified config dictionary and performs Mayers
+    sample correction on the workspace. The SampleDetails object defines the sample, material
+    and associated properties. Additionally it checks the value of multiple_scattering to
+    determine whether to take into account the effects of multiple scattering.
+    :param ws_to_correct: The workspace to perform Mayers sample correction on
+    :param multiple_scattering: Boolean of whether to account for the effects of multiple scattering
+    :param sample_details_obj: The object containing the sample details
+    :return: The corrected workspace
+    """
+
+    height = sample_details_obj.height
+    radius = sample_details_obj.radius
+    pos = sample_details_obj.center
+
+    # Get the underlying material object
+    if not sample_details_obj.is_material_set():
+        raise RuntimeError("The material for this sample has not been set yet. Please call"
+                           " set_material on the SampleDetails object to set the material")
+    material_obj = sample_details_obj.material_object
+    formula = material_obj.chemical_formula
+    number_density = material_obj.number_density
 
     ws_to_correct = _calculate__cylinder_absorb_corrections(
         ws_to_correct=ws_to_correct, multiple_scattering=multiple_scattering,
diff --git a/scripts/Diffraction/isis_powder/routines/sample_details.py b/scripts/Diffraction/isis_powder/routines/sample_details.py
index 041d4da5a839bff6dd32c3ffa91e8af99dd85381..3247e3e7286bd0fb61d5845e13b4f11b7b9c8d08 100644
--- a/scripts/Diffraction/isis_powder/routines/sample_details.py
+++ b/scripts/Diffraction/isis_powder/routines/sample_details.py
@@ -20,13 +20,16 @@ class SampleDetails(object):
         self.radius = float(radius)
         self.center = [float(i) for i in center]  # List of X, Y, Z position
 
-        self._material_object = None
+        self.material_object = None
+
+    def is_material_set(self):
+        return self.material_object is not None
 
     def print_sample_details(self):
         self._print()
 
     def reset_sample_material(self):
-        self._material_object = None
+        self.material_object = None
 
     def set_material(self, **kwargs):
         chemical_formula = common.dictionary_key_helper(dictionary=kwargs, key="chemical_formula",
@@ -34,13 +37,13 @@ class SampleDetails(object):
                                                                       " passed: chemical_formula")
         number_density = common.dictionary_key_helper(dictionary=kwargs, key="number_density", throws=False)
 
-        if self._material_object is not None:
+        if self.material_object is not None:
             self.print_sample_details()
             raise RuntimeError("The material has already been set to the above details. If the properties"
                                " have not been set they can be modified with 'set_material_properties()'. Otherwise"
                                " to change the material call 'reset_sample_material()'")
 
-        self._material_object = _Material(chemical_formula=chemical_formula, numeric_density=number_density)
+        self.material_object = _Material(chemical_formula=chemical_formula, numeric_density=number_density)
 
     def set_material_properties(self, **kwargs):
         err_msg = "The following argument is required but was not set or passed: "
@@ -48,12 +51,12 @@ class SampleDetails(object):
                                                                 exception_msg=err_msg + "absorption_cross_section")
         scattering_cross_section = common.dictionary_key_helper(dictionary=kwargs, key="scattering_cross_section",
                                                                 exception_msg=err_msg + "scattering_cross_section")
-        if self._material_object is None:
+        if self.material_object is None:
             raise RuntimeError("The material has not been set (or reset). Please set it by calling"
                                " 'set_material()' to set the material details of the sample.")
 
-        self._material_object.set_material_properties(abs_cross_sect=absorption_cross_section,
-                                                      scattering_cross_sect=scattering_cross_section)
+        self.material_object.set_material_properties(abs_cross_sect=absorption_cross_section,
+                                                     scattering_cross_sect=scattering_cross_section)
 
     def _print(self):
         print("Sample Details:")
@@ -63,10 +66,10 @@ class SampleDetails(object):
         print("Radius: {}".format(self.radius))
         print("Center X:{}, Y:{}, Z{}".format(self.center[0], self.center[1], self.center[2]))
         print("------------------------")
-        if self._material_object is None:
+        if self.material_object is None:
             print("Material has not been set (or has been reset).")
         else:
-            self._material_object.print_material()
+            self.material_object.print_material()
         print()  # Newline for visual spacing
 
     @staticmethod
@@ -93,7 +96,7 @@ class SampleDetails(object):
 
 class _Material(object):
     def __init__(self, chemical_formula, numeric_density=None):
-        self._chemical_formula = chemical_formula
+        self.chemical_formula = chemical_formula
 
         # If it is not an element Mantid requires us to provide the numeric density
         # which is required for absorption corrections.
@@ -105,11 +108,11 @@ class _Material(object):
             # Always check value is sane if user has given one
             _check_value_is_physical(property_name="numeric_density", value=numeric_density)
 
-        self._numeric_density = numeric_density
+        self.numeric_density = numeric_density
 
         # Advanced material properties
-        self._absorption_cross_section = None
-        self._scattering_cross_section = None
+        self.absorption_cross_section = None
+        self.scattering_cross_section = None
 
         # Internal flags so we are only allowed to set the material properties once
         self._is_material_props_set = False
@@ -117,18 +120,18 @@ class _Material(object):
     def print_material(self):
         print("Material properties:")
         print("------------------------")
-        print("Chemical formula: {}".format(self._chemical_formula))
+        print("Chemical formula: {}".format(self.chemical_formula))
 
-        if self._numeric_density:
-            print("Numeric Density: {}".format(self._numeric_density))
+        if self.numeric_density:
+            print("Numeric Density: {}".format(self.numeric_density))
         else:
             print("Numeric Density: Set from elemental properties by Mantid")
         self._print_material_properties()
 
     def _print_material_properties(self):
         if self._is_material_props_set:
-            print("Absorption cross section: {}".format(self._absorption_cross_section))
-            print("Scattering cross section: {}".format(self._scattering_cross_section))
+            print("Absorption cross section: {}".format(self.absorption_cross_section))
+            print("Scattering cross section: {}".format(self.scattering_cross_section))
         else:
             print("Absorption cross section: Calculated by Mantid based on chemical/elemental formula")
             print("Scattering cross section: Calculated by Mantid based on chemical/elemental formula")
@@ -143,8 +146,8 @@ class _Material(object):
 
         _check_value_is_physical("absorption_cross_section", abs_cross_sect)
         _check_value_is_physical("scattering_cross_section", scattering_cross_sect)
-        self._absorption_cross_section = float(abs_cross_sect)
-        self._scattering_cross_section = float(scattering_cross_sect)
+        self.absorption_cross_section = float(abs_cross_sect)
+        self.scattering_cross_section = float(scattering_cross_sect)
         self._is_material_props_set = True
 
 
diff --git a/scripts/test/ISISPowderSampleDetailsTest.py b/scripts/test/ISISPowderSampleDetailsTest.py
index 20fb2e828bee6f7d3734e1745f5dd4a02a923ba6..c997f14795fe100bb638579c7df960236af95f85 100644
--- a/scripts/test/ISISPowderSampleDetailsTest.py
+++ b/scripts/test/ISISPowderSampleDetailsTest.py
@@ -112,7 +112,7 @@ class ISISPowderSampleDetailsTest(unittest.TestCase):
 
         # Check that we can only set a material once. We will test the underlying class elsewhere
         sample_details_obj.set_material(chemical_formula='V')
-        self.assertIsNotNone(sample_details_obj._material_object)
+        self.assertIsNotNone(sample_details_obj.material_object)
 
         # Check that the material is now immutable
         with assertRaisesRegex(self, RuntimeError, "The material has already been set to the above details"):
@@ -120,16 +120,16 @@ class ISISPowderSampleDetailsTest(unittest.TestCase):
 
         # Check resetting it works
         sample_details_obj.reset_sample_material()
-        self.assertIsNone(sample_details_obj._material_object)
+        self.assertIsNone(sample_details_obj.material_object)
 
         # And ensure setting it for a second time works
         sample_details_obj.set_material(chemical_formula='V')
-        self.assertIsNotNone(sample_details_obj._material_object)
+        self.assertIsNotNone(sample_details_obj.material_object)
 
     def test_set_material_properties(self):
         sample_details_obj = sample_details.SampleDetails(height=1.0, radius=1.0, center=[2, 3, 5])
 
-        self.assertIsNone(sample_details_obj._material_object)
+        self.assertIsNone(sample_details_obj.material_object)
 
         # Check we cannot set a material property without setting the underlying material
         with assertRaisesRegex(self, RuntimeError, "The material has not been set"):
@@ -148,24 +148,24 @@ class ISISPowderSampleDetailsTest(unittest.TestCase):
 
         material_obj_one_char = sample_details._Material(chemical_formula=chemical_formula_one_char_element)
         self.assertIsNotNone(material_obj_one_char)
-        self.assertEqual(material_obj_one_char._chemical_formula, chemical_formula_one_char_element)
-        self.assertIsNone(material_obj_one_char._numeric_density)
+        self.assertEqual(material_obj_one_char.chemical_formula, chemical_formula_one_char_element)
+        self.assertIsNone(material_obj_one_char.numeric_density)
 
         # Also check that the absorption and scattering X sections have not been set
-        self.assertIsNone(material_obj_one_char._absorption_cross_section)
-        self.assertIsNone(material_obj_one_char._scattering_cross_section)
+        self.assertIsNone(material_obj_one_char.absorption_cross_section)
+        self.assertIsNone(material_obj_one_char.scattering_cross_section)
         self.assertFalse(material_obj_one_char._is_material_props_set)
 
         # Check if it accepts two character elements without numeric density
         material_obj_two_char = sample_details._Material(chemical_formula=chemical_formula_two_char_element)
         self.assertIsNotNone(material_obj_two_char)
-        self.assertEqual(material_obj_two_char._chemical_formula, chemical_formula_two_char_element)
-        self.assertIsNone(material_obj_two_char._numeric_density)
+        self.assertEqual(material_obj_two_char.chemical_formula, chemical_formula_two_char_element)
+        self.assertIsNone(material_obj_two_char.numeric_density)
 
         # Check it stores numeric density if passed
         material_obj_numeric_density = sample_details._Material(chemical_formula=chemical_formula_two_char_element,
                                                                 numeric_density=numeric_density_sample)
-        self.assertEqual(material_obj_numeric_density._numeric_density, numeric_density_sample)
+        self.assertEqual(material_obj_numeric_density.numeric_density, numeric_density_sample)
 
         # Check that it raises an error if we have a non-elemental formula without numeric density
         with assertRaisesRegex(self, ValueError, "A numeric density formula must be set on a chemical formula"):
@@ -174,8 +174,8 @@ class ISISPowderSampleDetailsTest(unittest.TestCase):
         # Check it constructs if it is given the numeric density too
         material_obj_num_complex_formula = sample_details._Material(chemical_formula=chemical_formula_complex,
                                                                     numeric_density=numeric_density_sample)
-        self.assertEqual(material_obj_num_complex_formula._chemical_formula, chemical_formula_complex)
-        self.assertEqual(material_obj_num_complex_formula._numeric_density, numeric_density_sample)
+        self.assertEqual(material_obj_num_complex_formula.chemical_formula, chemical_formula_complex)
+        self.assertEqual(material_obj_num_complex_formula.numeric_density, numeric_density_sample)
 
     def test_material_set_properties(self):
         bad_absorb = '-1'
@@ -196,20 +196,20 @@ class ISISPowderSampleDetailsTest(unittest.TestCase):
             material_obj.set_material_properties(abs_cross_sect=good_absorb, scattering_cross_sect=bad_scattering)
 
         # Check nothing has been set yet
-        self.assertIsNone(material_obj._absorption_cross_section)
-        self.assertIsNone(material_obj._scattering_cross_section)
+        self.assertIsNone(material_obj.absorption_cross_section)
+        self.assertIsNone(material_obj.scattering_cross_section)
 
         # Set the object this time
         material_obj.set_material_properties(abs_cross_sect=good_absorb, scattering_cross_sect=good_scattering)
         self.assertTrue(material_obj._is_material_props_set)
-        self.assertEqual(material_obj._absorption_cross_section, float(good_absorb))
-        self.assertEqual(material_obj._scattering_cross_section, float(good_scattering))
+        self.assertEqual(material_obj.absorption_cross_section, float(good_absorb))
+        self.assertEqual(material_obj.scattering_cross_section, float(good_scattering))
 
         # Check we cannot set it twice and fields do not change
         with assertRaisesRegex(self, RuntimeError, "The material properties have already been set"):
             material_obj.set_material_properties(abs_cross_sect=999, scattering_cross_sect=999)
-        self.assertEqual(material_obj._absorption_cross_section, float(good_absorb))
-        self.assertEqual(material_obj._scattering_cross_section, float(good_scattering))
+        self.assertEqual(material_obj.absorption_cross_section, float(good_absorb))
+        self.assertEqual(material_obj.scattering_cross_section, float(good_scattering))
 
     def test_print_sample_details(self):
         expected_height = 1