diff --git a/Framework/Kernel/CMakeLists.txt b/Framework/Kernel/CMakeLists.txt
index 78c1b6bb98747d4cfc6e3da3e3d1a4ad770ab00c..11b0abf40fc2d535e6639b27d138c0805f6c7831 100644
--- a/Framework/Kernel/CMakeLists.txt
+++ b/Framework/Kernel/CMakeLists.txt
@@ -166,7 +166,7 @@ set ( INC_FILES
 	inc/MantidKernel/ConfigService.h
 	inc/MantidKernel/ConfigObserver.h
 	inc/MantidKernel/ConfigPropertyObserver.h
-  inc/MantidKernel/DateAndTime.h
+        inc/MantidKernel/DateAndTime.h
 	inc/MantidKernel/DataItem.h
 	inc/MantidKernel/DataService.h
 	inc/MantidKernel/DateAndTimeHelpers.h
@@ -246,7 +246,7 @@ set ( INC_FILES
 	inc/MantidKernel/NetworkProxy.h
 	inc/MantidKernel/NeutronAtom.h
 	inc/MantidKernel/NexusDescriptor.h
-  inc/MantidKernel/normal_distribution.h
+        inc/MantidKernel/normal_distribution.h
 	inc/MantidKernel/NullValidator.h
 	inc/MantidKernel/OptionalBool.h
 	inc/MantidKernel/ParaViewVersion.h
diff --git a/Framework/Kernel/inc/MantidKernel/TimeSeriesProperty.h b/Framework/Kernel/inc/MantidKernel/TimeSeriesProperty.h
index 1f39d3d73a937a23b28dc59a6091d6c7f4b5022e..3b1e4701ef5abc19f748b28b7d297588d449bc4d 100644
--- a/Framework/Kernel/inc/MantidKernel/TimeSeriesProperty.h
+++ b/Framework/Kernel/inc/MantidKernel/TimeSeriesProperty.h
@@ -120,6 +120,7 @@ class DLLExport TimeSeriesProperty : public Property,
 public:
   /// Constructor
   explicit TimeSeriesProperty(const std::string &name);
+
   /// Virtual destructor
   ~TimeSeriesProperty() override;
   /// "Virtual" copy constructor
diff --git a/Framework/PythonInterface/inc/MantidPythonInterface/kernel/Converters/ContainerDtype.h b/Framework/PythonInterface/inc/MantidPythonInterface/kernel/Converters/ContainerDtype.h
new file mode 100644
index 0000000000000000000000000000000000000000..ba5428819b01be68143c591c6cb625844f89cbd9
--- /dev/null
+++ b/Framework/PythonInterface/inc/MantidPythonInterface/kernel/Converters/ContainerDtype.h
@@ -0,0 +1,76 @@
+#ifndef MANTID_PYTHONINTERFACE_CONVERTERS_CONTAINERDTYPE_H_
+#define MANTID_PYTHONINTERFACE_CONVERTERS_CONTAINERDTYPE_H_
+
+#include <string>
+#include <type_traits>
+
+/**
+    ContainerDtype Header File
+
+    A helper free function to allow identification of data type being used by
+    providing a numpy friendly string.
+
+    @author Lamar Moore STFC, Bhuvan Bezawada STFC
+    @date 21/06/2018
+
+    Copyright &copy; 2018 ISIS Rutherford Appleton Laboratory, NScD Oak
+    Ridge National Laboratory & European Spallation Source
+
+    This file is part of Mantid.
+
+    Mantid 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.
+
+    Mantid 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 this program.  If not, see <http://www.gnu.org/licenses/>.
+
+    File change history is stored at: <https://github.com/mantidproject/mantid>.
+    Code Documentation is available at: <http://doxygen.mantidproject.org>
+*/
+
+namespace Mantid {
+namespace PythonInterface {
+namespace Converters {
+
+// Free function to determine data type being stored in container
+template <template <class> class Container, typename HeldType>
+std::string dtype(const Container<HeldType> &) {
+  if (std::is_same<HeldType, bool>::value) {
+    return "bool_";
+  } else if (std::is_same<HeldType, short>::value) {
+    return "int16";
+  } else if (std::is_same<HeldType, std::int8_t>::value) {
+    return "int8";
+  } else if (std::is_same<HeldType, std::int16_t>::value) {
+    return "int16";
+  } else if (std::is_same<HeldType, std::int32_t>::value) {
+    return "int32";
+  } else if (std::is_same<HeldType, std::int64_t>::value) {
+    return "int64";
+  } else if (std::is_same<HeldType, long>::value) {
+    return "int_";
+  } else if (std::is_same<HeldType, long long>::value) {
+    return "int64";
+  } else if (std::is_same<HeldType, float>::value) {
+    return "float32";
+  } else if (std::is_same<HeldType, double>::value) {
+    return "float64";
+  } else if (std::is_same<HeldType, std::string>::value) {
+    return "string_";
+  } else {
+    return "object_";
+  }
+}
+
+} // namespace Converters
+} // namespace PythonInterface
+} // namespace Mantid
+
+#endif /*MANTID_PYTHONINTERFACE_CONVERTERS_CONTAINERDTYPE_H_*/
diff --git a/Framework/PythonInterface/inc/MantidPythonInterface/kernel/PropertyWithValueExporter.h b/Framework/PythonInterface/inc/MantidPythonInterface/kernel/PropertyWithValueExporter.h
index 8cc6f84d4fe6bc9e86d1c5d6ccca2c3579159c7f..7e29893342e1a550c80742ba21f8d25b81fd5d06 100644
--- a/Framework/PythonInterface/inc/MantidPythonInterface/kernel/PropertyWithValueExporter.h
+++ b/Framework/PythonInterface/inc/MantidPythonInterface/kernel/PropertyWithValueExporter.h
@@ -25,6 +25,7 @@
 */
 
 #include "MantidKernel/PropertyWithValue.h"
+#include "MantidPythonInterface/kernel/Converters/ContainerDtype.h"
 
 #ifndef Q_MOC_RUN
 #include <boost/python/class.hpp>
@@ -33,8 +34,15 @@
 #include <boost/python/return_by_value.hpp>
 #endif
 
+// Call the dtype helper function
+template <typename HeldType>
+std::string dtype(Mantid::Kernel::PropertyWithValue<HeldType> &self) {
+  return Mantid::PythonInterface::Converters::dtype(self);
+}
+
 namespace Mantid {
 namespace PythonInterface {
+
 /**
  * A helper struct to export PropertyWithValue<> types to Python.
  */
@@ -49,7 +57,8 @@ struct PropertyWithValueExporter {
         pythonClassName, no_init)
         .add_property("value",
                       make_function(&PropertyWithValue<HeldType>::operator(),
-                                    return_value_policy<ValueReturnPolicy>()));
+                                    return_value_policy<ValueReturnPolicy>()))
+        .def("dtype", &dtype<HeldType>, arg("self"));
   }
 };
 }
diff --git a/Framework/PythonInterface/mantid/kernel/CMakeLists.txt b/Framework/PythonInterface/mantid/kernel/CMakeLists.txt
index 4fa38967a53bded8bff9ee46f72f3e23812af5a7..b8ce08e9069086e3ec66795771b1c7875e46226e 100644
--- a/Framework/PythonInterface/mantid/kernel/CMakeLists.txt
+++ b/Framework/PythonInterface/mantid/kernel/CMakeLists.txt
@@ -95,6 +95,7 @@ set ( INC_FILES
   ${HEADER_DIR}/kernel/NdArray.h
   ${HEADER_DIR}/kernel/Converters/CArrayToNDArray.h
   ${HEADER_DIR}/kernel/Converters/CloneToNumpy.h
+  ${HEADER_DIR}/kernel/Converters/ContainerDtype.h
   ${HEADER_DIR}/kernel/Converters/DateAndTime.h
   ${HEADER_DIR}/kernel/Converters/MapToPyDictionary.h
   ${HEADER_DIR}/kernel/Converters/MatrixToNDArray.h
diff --git a/Framework/PythonInterface/mantid/kernel/src/Exports/ArrayProperty.cpp b/Framework/PythonInterface/mantid/kernel/src/Exports/ArrayProperty.cpp
index f6610cc09ee0ddfe61537f250d4e891d5f218cc1..32166550d26414b20b70aee9a49f0ce38511b51b 100644
--- a/Framework/PythonInterface/mantid/kernel/src/Exports/ArrayProperty.cpp
+++ b/Framework/PythonInterface/mantid/kernel/src/Exports/ArrayProperty.cpp
@@ -1,22 +1,23 @@
 #include "MantidKernel/ArrayProperty.h"
 #include "MantidKernel/NullValidator.h"
 
-#include "MantidPythonInterface/kernel/NdArray.h"
-#include "MantidPythonInterface/kernel/Policies/VectorToNumpy.h"
 #include "MantidPythonInterface/kernel/Converters/NDArrayToVector.h"
 #include "MantidPythonInterface/kernel/Converters/PySequenceToVector.h"
+#include "MantidPythonInterface/kernel/Converters/ContainerDtype.h"
+#include "MantidPythonInterface/kernel/NdArray.h"
+#include "MantidPythonInterface/kernel/Policies/VectorToNumpy.h"
 
 #include <boost/python/class.hpp>
 #include <boost/python/list.hpp>
 
-#include <boost/python/make_constructor.hpp>
 #include <boost/python/default_call_policies.hpp>
+#include <boost/python/make_constructor.hpp>
 
 using Mantid::Kernel::ArrayProperty;
-using Mantid::Kernel::PropertyWithValue;
 using Mantid::Kernel::Direction;
 using Mantid::Kernel::IValidator_sptr;
 using Mantid::Kernel::NullValidator;
+using Mantid::Kernel::PropertyWithValue;
 namespace Converters = Mantid::PythonInterface::Converters;
 namespace NumPy = Mantid::PythonInterface::NumPy;
 namespace Policies = Mantid::PythonInterface::Policies;
@@ -27,6 +28,11 @@ namespace {
 using return_cloned_numpy =
     return_value_policy<Policies::VectorRefToNumpy<Converters::Clone>>;
 
+// Call the dtype helper function
+template <typename type> std::string dtype(ArrayProperty<type> &self) {
+  return Converters::dtype(self);
+}
+
 #define EXPORT_ARRAY_PROP(type, prefix)                                        \
   class_<ArrayProperty<type>, bases<PropertyWithValue<std::vector<type>>>,     \
          boost::noncopyable>(#prefix "ArrayProperty", no_init)                 \
@@ -58,6 +64,7 @@ using return_cloned_numpy =
                (arg("name"), arg("values"),                                    \
                 arg("validator") = IValidator_sptr(new NullValidator),         \
                 arg("direction") = Direction::Input)))                         \
+      .def("dtype", &dtype<type>, arg("self"))                                 \
       .add_property("value", make_function(&ArrayProperty<type>::operator(),   \
                                            return_cloned_numpy()));
 
@@ -79,14 +86,14 @@ ArrayProperty<T> *createArrayPropertyFromList(const std::string &name,
 }
 
 /**
-  * Factory function to allow the initial values to be specified as a numpy
+ * Factory function to allow the initial values to be specified as a numpy
  * array
-  * @param name :: The name of the property
-  * @param vec :: A boost python array of initial values
-  * @param validator :: A validator object
-  * @param direction :: A direction
-  * @return
-  */
+ * @param name :: The name of the property
+ * @param vec :: A boost python array of initial values
+ * @param validator :: A validator object
+ * @param direction :: A direction
+ * @return
+ */
 template <typename T>
 ArrayProperty<T> *createArrayPropertyFromNDArray(const std::string &name,
                                                  const NumPy::NdArray &values,
@@ -95,7 +102,7 @@ ArrayProperty<T> *createArrayPropertyFromNDArray(const std::string &name,
   return new ArrayProperty<T>(name, Converters::NDArrayToVector<T>(values)(),
                               validator, direction);
 }
-}
+} // namespace
 
 void export_ArrayProperty() {
   // Match the python names to their C types
@@ -107,4 +114,4 @@ void export_ArrayProperty() {
   // Python can be seen also. Users shouldn't need this
   EXPORT_ARRAY_PROP(int, CInt);
   EXPORT_ARRAY_PROP(size_t, UnsignedInt);
-}
+}
\ No newline at end of file
diff --git a/Framework/PythonInterface/mantid/kernel/src/Exports/TimeSeriesProperty.cpp b/Framework/PythonInterface/mantid/kernel/src/Exports/TimeSeriesProperty.cpp
index a6f2f38ccae46736f58d80192fae1a0311d828a3..fc132c5a1705ca9fcc9406eb46f280e28c405e4a 100644
--- a/Framework/PythonInterface/mantid/kernel/src/Exports/TimeSeriesProperty.cpp
+++ b/Framework/PythonInterface/mantid/kernel/src/Exports/TimeSeriesProperty.cpp
@@ -1,5 +1,6 @@
 #include "MantidKernel/TimeSeriesProperty.h"
 #include "MantidPythonInterface/kernel/Converters/DateAndTime.h"
+#include "MantidPythonInterface/kernel/Converters/ContainerDtype.h"
 #include "MantidPythonInterface/kernel/GetPointer.h"
 #include "MantidPythonInterface/kernel/Policies/VectorToNumpy.h"
 
@@ -7,12 +8,12 @@
 #include <boost/python/implicit.hpp>
 #include <boost/python/init.hpp>
 #include <boost/python/make_function.hpp>
-#include <boost/python/return_value_policy.hpp>
 #include <boost/python/register_ptr_to_python.hpp>
+#include <boost/python/return_value_policy.hpp>
 
-using Mantid::Types::Core::DateAndTime;
-using Mantid::Kernel::TimeSeriesProperty;
 using Mantid::Kernel::Property;
+using Mantid::Kernel::TimeSeriesProperty;
+using Mantid::Types::Core::DateAndTime;
 using namespace boost::python;
 using boost::python::arg;
 
@@ -35,6 +36,11 @@ void addPyTimeValue(TimeSeriesProperty<TYPE> &self,
   self.addValue(*dateandtime, value);
 }
 
+// Call the dtype helper function
+template <typename TYPE> std::string dtype(TimeSeriesProperty<TYPE> &self) {
+  return Mantid::PythonInterface::Converters::dtype(self);
+}
+
 // Macro to reduce copy-and-paste
 #define EXPORT_TIMESERIES_PROP(TYPE, Prefix)                                   \
   register_ptr_to_python<TimeSeriesProperty<TYPE> *>();                        \
@@ -80,8 +86,10 @@ void addPyTimeValue(TimeSeriesProperty<TYPE> &self,
            arg("self"),                                                        \
            "returns :class:`mantid.kernel.TimeSeriesPropertyStatistics`")      \
       .def("timeAverageValue", &TimeSeriesProperty<TYPE>::timeAverageValue,    \
-           arg("self"));
-}
+           arg("self"))                                                        \
+      .def("dtype", &dtype<TYPE>, arg("self"));
+
+} // namespace
 
 void export_TimeSeriesProperty_Double() {
   EXPORT_TIMESERIES_PROP(double, Float);
diff --git a/Framework/PythonInterface/test/python/mantid/kernel/ArrayPropertyTest.py b/Framework/PythonInterface/test/python/mantid/kernel/ArrayPropertyTest.py
index 8a5d09ec6512e8920c0133f4004c3bbf91cb78f9..db5f08d0f2783b2a600c8b6c576f9a78edc110f4 100644
--- a/Framework/PythonInterface/test/python/mantid/kernel/ArrayPropertyTest.py
+++ b/Framework/PythonInterface/test/python/mantid/kernel/ArrayPropertyTest.py
@@ -129,10 +129,86 @@ class ArrayPropertyTest(unittest.TestCase):
                     FloatArrayProperty("Input", Direction.Input), "Float array")
             def PyExec(self):
                 self._input_values = self.getProperty("Input").value
-    
+
         input_values = range(1, 5)
         self._do_algorithm_test(AlgWithFloatArrayProperty, input_values)
 
+    def test_dtype_function_calls(self):
+        """
+        Tests the dtype() function call for the data types stored in the array.
+        """
+        # Set up
+        direc = Direction.Output
+        validator = NullValidator()
+
+        # Create float array
+        float_input_values = [1.1, 2.5, 5.6, 4.6, 9.0, 6.0]
+        float_arr = FloatArrayProperty("floats", float_input_values, validator, direc)
+
+        # Create int array
+        int_input_values = [1, 2, 5, 4, 9, 6]
+        int_arr = IntArrayProperty("integers", int_input_values, validator, direc)
+
+        # Create string array
+        str_input_values = ["a", "b", "c", "d", "e"]
+        str_arr = StringArrayProperty("letters", str_input_values, validator, direc)
+
+        # Test
+        self.assertEquals(float_arr.dtype(), "float64")
+        self.assertEquals(str_arr.dtype(), "string_")
+        
+        # Implementation of IntArrayProperty is based on long 
+        # (which is itself implementation defined, so a special case is needed here)
+        if sys.platform == 'win32' or sys.platform == 'darwin':
+          # Windows and macOS should return "int_"
+          self.assertEquals(int_arr.dtype(), "int_")
+        else:
+          # Linux based systems should return "int64"
+          self.assertEquals(int_arr.dtype(), "int64")
+
+    def test_construct_numpy_array_with_given_dtype_float(self):
+        # Set up
+        direc = Direction.Output
+        validator = NullValidator()
+
+        # Create float array
+        float_input_values = [1.1, 2.5, 5.6, 4.6, 9.0, 6.0]
+        float_arr = FloatArrayProperty("floats", float_input_values, validator, direc)
+        
+        # Use the returned dtype() to check it works with numpy arrays
+        x = np.arange(1, 10, dtype=float_arr.dtype())
+        self.assertIsInstance(x, np.ndarray)
+        self.assertEquals(x.dtype, float_arr.dtype()) 
+
+    def test_construct_numpy_array_with_given_dtype_int(self):
+        # Set up
+        direc = Direction.Output
+        validator = NullValidator()
+
+        # Create int array
+        int_input_values = [1, 2, 5, 4, 9, 6]
+        int_arr = IntArrayProperty("integers", int_input_values, validator, direc)
+        
+        # Use the returned dtype() to check it works with numpy arrays
+        x = np.arange(1, 10, dtype=int_arr.dtype())
+        self.assertIsInstance(x, np.ndarray)
+        self.assertEquals(x.dtype, int_arr.dtype())
+
+    def test_construct_numpy_array_with_given_dtype_string(self):
+        # Set up
+        direc = Direction.Output
+        validator = NullValidator()
+
+        # Create string array
+        str_input_values = ["hello", "testing", "word", "another word", "word"]
+        str_arr = StringArrayProperty("letters", str_input_values, validator, direc)
+        
+        # Use the returned dtype() to check it works with numpy arrays
+        x = np.array(str_input_values, dtype=str_arr.dtype())
+        self.assertIsInstance(x, np.ndarray)
+        # Expect longest string to be returned
+        self.assertEquals(x.dtype, "S12")     
+
     def test_PythonAlgorithm_setProperty_With_Ranges_String(self):
         """
             Test ArrayProperty within a python algorithm can
diff --git a/Framework/PythonInterface/test/python/mantid/kernel/PropertyWithValueTest.py b/Framework/PythonInterface/test/python/mantid/kernel/PropertyWithValueTest.py
index 773ec7871a59f5bf98d4de753c5b28297295ff42..56908e8161f3b6e592b3ba4dd07e1a8e2c46d88a 100644
--- a/Framework/PythonInterface/test/python/mantid/kernel/PropertyWithValueTest.py
+++ b/Framework/PythonInterface/test/python/mantid/kernel/PropertyWithValueTest.py
@@ -127,6 +127,9 @@ class PropertyWithValueTest(unittest.TestCase):
         self.assertEquals(result.startswith("1,2,3,"), True)
         self.assertEquals(result.endswith("98,99"), True)
 
+        # Check the dtype return value
+        self.assertEquals(det_list_prop.dtype(), "int32")
+
     def _do_vector_double_numpy_test(self, int_type=False):
         create_ws = AlgorithmManager.createUnmanaged('CreateWorkspace')
         create_ws.initialize()
diff --git a/Framework/PythonInterface/test/python/mantid/kernel/TimeSeriesPropertyTest.py b/Framework/PythonInterface/test/python/mantid/kernel/TimeSeriesPropertyTest.py
index 9e9c2410e43c21c262f3ef982b72a4470b5cca10..d162fc3f5b44c8d0ab9ef1ce8b3fbb03183d38a5 100644
--- a/Framework/PythonInterface/test/python/mantid/kernel/TimeSeriesPropertyTest.py
+++ b/Framework/PythonInterface/test/python/mantid/kernel/TimeSeriesPropertyTest.py
@@ -60,23 +60,31 @@ class TimeSeriesPropertyTest(unittest.TestCase):
         self._check_has_time_series_attributes(log_series)
         self.assertEquals(log_series.size(), self._ntemp)
         self.assertAlmostEqual(log_series.nthValue(0), -0.00161)
+        # Check the dtype return value
+        self.assertEquals(log_series.dtype(), "float64")
 
     def test_time_series_int_can_be_extracted(self):
         log_series = self._test_ws.getRun()["raw_frames"]
         self._check_has_time_series_attributes(log_series)
         self.assertEquals(log_series.size(), self._nframes)
         self.assertEquals(log_series.nthValue(1), 1436)
+        # Check the dtype return value
+        self.assertEquals(log_series.dtype(), "int64")
 
     def test_time_series_string_can_be_extracted(self):
         log_series = self._test_ws.getRun()["icp_event"]
         self._check_has_time_series_attributes(log_series, list)
         self.assertEquals(log_series.size(), 4)
         self.assertEquals(log_series.nthValue(0).strip(), 'CHANGE_PERIOD 1')
+        # Check the dtype return value
+        self.assertEquals(log_series.dtype(), "string_")
 
     def test_time_series_bool_can_be_extracted(self):
         log_series = self._test_ws.getRun()["period 1"]
         self._check_has_time_series_attributes(log_series)
         self.assertEquals(log_series.size(), 1)
+        # Check the dtype return value
+        self.assertEquals(log_series.dtype(), "bool_")
 
     def _check_has_time_series_attributes(self, log, values_type=np.ndarray):
         self.assertTrue(hasattr(log, "value"))
@@ -87,6 +95,5 @@ class TimeSeriesPropertyTest(unittest.TestCase):
         self.assertTrue(isinstance(values, values_type))
         self.assertEquals(log.size(), len(values))
 
-
 if __name__ == '__main__':
     unittest.main()