diff --git a/Framework/DataHandling/src/LoadSpiceXML2DDet.cpp b/Framework/DataHandling/src/LoadSpiceXML2DDet.cpp
index 583264085f922631fb3505eb62e172d38e053824..5defd4a05be97697762812dec559c5e255ca7bf5 100644
--- a/Framework/DataHandling/src/LoadSpiceXML2DDet.cpp
+++ b/Framework/DataHandling/src/LoadSpiceXML2DDet.cpp
@@ -602,6 +602,9 @@ bool LoadSpiceXML2DDet::getHB3AWavelength(MatrixWorkspace_sptr dataws,
       if (fabs(m1pos - (-25.870000)) < 0.2) {
         wavelength = 1.003;
         haswavelength = true;
+      } else if (fabs(m1pos - (-39.17)) < 0.2) {
+        wavelength = 1.5424;
+        haswavelength = true;
       } else {
         g_log.warning() << "m1 position " << m1pos
                         << " does not have defined mapping to "
@@ -615,6 +618,9 @@ bool LoadSpiceXML2DDet::getHB3AWavelength(MatrixWorkspace_sptr dataws,
       if (fabs(m1pos - (-25.870000)) < 0.2) {
         wavelength = 1.003;
         haswavelength = true;
+      } else if (fabs(m1pos - (-39.17)) < 0.2) {
+        wavelength = 1.5424;
+        haswavelength = true;
       } else {
         g_log.warning() << "m1 position " << m1pos
                         << " does not have defined mapping to "
diff --git a/Framework/MDAlgorithms/CMakeLists.txt b/Framework/MDAlgorithms/CMakeLists.txt
index d52d54087d1ee9ad8e3c019dbc931d490c2f9416..f3e9e4d04a2db2271f828af463f363f2364f2462 100644
--- a/Framework/MDAlgorithms/CMakeLists.txt
+++ b/Framework/MDAlgorithms/CMakeLists.txt
@@ -19,6 +19,7 @@ set ( SRC_FILES
 	src/ConvToMDSelector.cpp
 	src/ConvertCWPDMDToSpectra.cpp
 	src/ConvertCWSDExpToMomentum.cpp
+	src/ConvertCWSDMDtoHKL.cpp
 	src/ConvertMDHistoToMatrixWorkspace.cpp
 	src/ConvertSpiceDataToRealSpace.cpp
 	src/ConvertToDetectorFaceMD.cpp
@@ -138,6 +139,7 @@ set ( INC_FILES
 	inc/MantidMDAlgorithms/ConvToMDBase.h
 	inc/MantidMDAlgorithms/ConvertCWPDMDToSpectra.h
 	inc/MantidMDAlgorithms/ConvertCWSDExpToMomentum.h
+	inc/MantidMDAlgorithms/ConvertCWSDMDtoHKL.h
 	inc/MantidMDAlgorithms/ConvertMDHistoToMatrixWorkspace.h
 	inc/MantidMDAlgorithms/ConvertSpiceDataToRealSpace.h
 	inc/MantidMDAlgorithms/ConvertToDetectorFaceMD.h
@@ -257,6 +259,7 @@ set ( TEST_FILES
 	CompareMDWorkspacesTest.h
 	ConvertCWPDMDToSpectraTest.h
 	ConvertCWSDExpToMomentumTest.h
+	ConvertCWSDMDtoHKLTest.h
 	ConvertEventsToMDTest.h
 	ConvertMDHistoToMatrixWorkspaceTest.h
 	ConvertSpiceDataToRealSpaceTest.h
diff --git a/Framework/MDAlgorithms/inc/MantidMDAlgorithms/ConvertCWSDMDtoHKL.h b/Framework/MDAlgorithms/inc/MantidMDAlgorithms/ConvertCWSDMDtoHKL.h
new file mode 100644
index 0000000000000000000000000000000000000000..6879be0456ee797b4df6442510d5ad6894024197
--- /dev/null
+++ b/Framework/MDAlgorithms/inc/MantidMDAlgorithms/ConvertCWSDMDtoHKL.h
@@ -0,0 +1,107 @@
+#ifndef MANTID_MDALGORITHMS_CONVERTCWSDMDTOHKL_H_
+#define MANTID_MDALGORITHMS_CONVERTCWSDMDTOHKL_H_
+
+#include "MantidMDAlgorithms/DllConfig.h"
+#include "MantidKernel/System.h"
+#include "MantidAPI/Algorithm.h"
+#include "MantidAPI/IMDEventWorkspace_fwd.h"
+#include "MantidDataObjects/PeaksWorkspace.h"
+#include "MantidKernel/Matrix.h"
+#include "MantidKernel/V3D.h"
+
+namespace Mantid {
+namespace MDAlgorithms {
+
+/** ConvertCWSDMDtoHKL : TODO: DESCRIPTION
+
+  Copyright &copy; 2015 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>
+*/
+class MANTID_MDALGORITHMS_DLL ConvertCWSDMDtoHKL : public API::Algorithm {
+public:
+  ConvertCWSDMDtoHKL();
+  virtual ~ConvertCWSDMDtoHKL();
+
+  /// Algorithm's name
+  virtual const std::string name() const { return "ConvertCWSDMDtoHKL"; }
+
+  /// Summary of algorithms purpose
+  virtual const std::string summary() const {
+    return "Convert constant wavelength single crystal diffractomer's data"
+           "in MDEventWorkspace and in unit of Q-sample to the HKL space "
+           "by UB matrix.";
+  }
+
+  /// Algorithm's version
+  virtual int version() const { return (1); }
+
+  /// Algorithm's category for identification
+  virtual const std::string category() const {
+    return "Diffraction;MDAlgorithms";
+  }
+
+private:
+  /// Initialisation code
+  void init();
+
+  /// Execution code
+  void exec();
+
+  void exportEvents(API::IMDEventWorkspace_sptr mdws,
+                    std::vector<Kernel::V3D> &vec_event_qsample,
+                    std::vector<signal_t> &vec_event_signal,
+                    std::vector<detid_t> &vec_event_det);
+
+  void convertFromQSampleToHKL(const std::vector<Kernel::V3D> &q_vectors,
+                               std::vector<Kernel::V3D> &miller_indices);
+
+  API::IMDEventWorkspace_sptr
+  createHKLMDWorkspace(const std::vector<Kernel::V3D> &vec_hkl,
+                       const std::vector<signal_t> &vec_signal,
+                       const std::vector<detid_t> &vec_detid);
+
+  void addMDEvents(std::vector<std::vector<coord_t>> &vec_q_sample,
+                   std::vector<float> &vec_signal);
+
+  void
+  saveMDToFile(std::vector<std::vector<Mantid::coord_t>> &vec_event_qsample,
+               std::vector<float> &vec_event_signal);
+
+  void saveEventsToFile(const std::string &filename,
+                        std::vector<Kernel::V3D> &vec_event_pos,
+                        std::vector<signal_t> &vec_event_signal,
+                        std::vector<detid_t> &vec_event_detid);
+
+  void getUBMatrix();
+
+  void getRange(const std::vector<Kernel::V3D> vec_hkl,
+                std::vector<double> &extentMins,
+                std::vector<double> &extentMaxs);
+
+  API::IMDEventWorkspace_sptr m_outputWS;
+
+  Kernel::Matrix<double> m_UB;
+};
+
+} // namespace MDAlgorithms
+} // namespace Mantid
+
+#endif /* MANTID_MDALGORITHMS_CONVERTCWSDMDTOHKL_H_ */
diff --git a/Framework/MDAlgorithms/src/ConvertCWSDMDtoHKL.cpp b/Framework/MDAlgorithms/src/ConvertCWSDMDtoHKL.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ebee9b77c9e84a78b80ef741ee177271aab55475
--- /dev/null
+++ b/Framework/MDAlgorithms/src/ConvertCWSDMDtoHKL.cpp
@@ -0,0 +1,403 @@
+#include "MantidMDAlgorithms/ConvertCWSDMDtoHKL.h"
+
+#include "MantidAPI/WorkspaceProperty.h"
+#include "MantidAPI/IMDEventWorkspace.h"
+#include "MantidAPI/IMDIterator.h"
+
+#include "MantidGeometry/Crystal/IndexingUtils.h"
+#include "MantidGeometry/Crystal/OrientedLattice.h"
+#include "MantidKernel/BoundedValidator.h"
+#include "MantidKernel/ArrayProperty.h"
+
+#include "MantidDataObjects/MDEventFactory.h"
+#include "MantidAPI/ExperimentInfo.h"
+#include "MantidGeometry/Instrument/ComponentHelper.h"
+#include "MantidMDAlgorithms/MDWSDescription.h"
+#include "MantidMDAlgorithms/MDWSTransform.h"
+#include "MantidAPI/FileProperty.h"
+#include "MantidDataObjects/MDBoxBase.h"
+#include "MantidDataObjects/MDEventInserter.h"
+
+#include <fstream>
+
+namespace Mantid {
+namespace MDAlgorithms {
+
+using namespace Mantid::API;
+using namespace Mantid::Kernel;
+using namespace Mantid::MDAlgorithms;
+using namespace Mantid::DataObjects;
+using namespace Mantid::Geometry;
+
+DECLARE_ALGORITHM(ConvertCWSDMDtoHKL)
+
+//----------------------------------------------------------------------------------------------
+/** Constructor
+ */
+ConvertCWSDMDtoHKL::ConvertCWSDMDtoHKL() {}
+
+//----------------------------------------------------------------------------------------------
+/** Destructor
+ */
+ConvertCWSDMDtoHKL::~ConvertCWSDMDtoHKL() {}
+
+//----------------------------------------------------------------------------------------------
+/** Init
+ */
+void ConvertCWSDMDtoHKL::init() {
+  declareProperty(new WorkspaceProperty<IMDEventWorkspace>("InputWorkspace", "",
+                                                           Direction::Input),
+                  "Name of the input MDEventWorkspace that stores detectors "
+                  "counts from a constant-wave powder diffraction experiment.");
+
+  declareProperty(new WorkspaceProperty<PeaksWorkspace>("PeaksWorkspace", "",
+                                                        Direction::Input,
+                                                        PropertyMode::Optional),
+                  "Input Peaks Workspace");
+
+  declareProperty(
+      new ArrayProperty<double>("UBMatrix"),
+      "A comma seperated list of doubles for UB matrix from (0,0), (0,1)"
+      "... (2,1),(2,2)");
+
+  declareProperty(new WorkspaceProperty<IMDEventWorkspace>(
+                      "OutputWorkspace", "", Direction::Output),
+                  "Name of the output MDEventWorkspace in HKL-space.");
+
+  std::vector<std::string> exts;
+  exts.push_back(".dat");
+  declareProperty(
+      new FileProperty("QSampleFileName", "", API::FileProperty::OptionalSave),
+      "Name of file for sample sample.");
+
+  declareProperty(
+      new FileProperty("HKLFileName", "", API::FileProperty::OptionalSave),
+      "Name of file for HKL.");
+}
+
+//----------------------------------------------------------------------------------------------
+/** Exec
+ */
+void ConvertCWSDMDtoHKL::exec() {
+  // Get inputs
+  IMDEventWorkspace_sptr inputWS = getProperty("InputWorkspace");
+  if (inputWS->getSpecialCoordinateSystem() != Mantid::Kernel::QSample) {
+    std::stringstream errmsg;
+    errmsg << "Input MDEventWorkspace's coordinate system is not QSample but "
+           << inputWS->getSpecialCoordinateSystem() << ".";
+    throw std::invalid_argument(errmsg.str());
+  }
+
+  getUBMatrix();
+
+  // Test indexing.  Will be delete soon
+  if (true) {
+    Kernel::V3D qsample; // [1.36639,-2.52888,-4.77349]
+    qsample.setX(1.36639);
+    qsample.setY(-2.52888);
+    qsample.setZ(-4.77349);
+
+    std::vector<Kernel::V3D> vec_qsample;
+    vec_qsample.push_back(qsample);
+    std::vector<Kernel::V3D> vec_mindex(0);
+
+    convertFromQSampleToHKL(vec_qsample, vec_mindex);
+    g_log.notice() << "[DB Number of returned Miller Index = "
+                   << vec_mindex.size() << "\n";
+    g_log.notice() << "[DB] Output HKL = " << vec_mindex[0].toString() << "\n";
+  }
+
+  // Get events information for future processing
+  std::vector<Kernel::V3D> vec_event_qsample;
+  std::vector<signal_t> vec_event_signal;
+  std::vector<detid_t> vec_event_det;
+  exportEvents(inputWS, vec_event_qsample, vec_event_signal, vec_event_det);
+
+  std::string qsamplefilename = getPropertyValue("QSampleFileName");
+  // Abort with an empty string
+  if (qsamplefilename.size() > 0)
+    saveEventsToFile(qsamplefilename, vec_event_qsample, vec_event_signal,
+                     vec_event_det);
+
+  // Convert to HKL
+  std::vector<Kernel::V3D> vec_event_hkl;
+  convertFromQSampleToHKL(vec_event_qsample, vec_event_hkl);
+
+  // Get file name
+  std::string hklfilename = getPropertyValue("HKLFileName");
+  // Abort mission if no file name is given
+  if (hklfilename.size() > 0)
+    saveEventsToFile(hklfilename, vec_event_hkl, vec_event_signal,
+                     vec_event_det);
+
+  // Create output workspace
+  m_outputWS =
+      createHKLMDWorkspace(vec_event_hkl, vec_event_signal, vec_event_det);
+
+  setProperty("OutputWorkspace", m_outputWS);
+}
+
+void ConvertCWSDMDtoHKL::getUBMatrix() {
+  std::string peakwsname = getPropertyValue("PeaksWorkspace");
+  if (peakwsname.size() > 0 &&
+      AnalysisDataService::Instance().doesExist(peakwsname)) {
+    // Get from peak works
+    DataObjects::PeaksWorkspace_sptr peakws = getProperty("PeaksWorkspace");
+    m_UB =
+        Kernel::Matrix<double>(peakws->sample().getOrientedLattice().getUB());
+  } else {
+    // Get from ...
+    std::vector<double> ub_array = getProperty("UBMatrix");
+    if (ub_array.size() != 9)
+      throw std::invalid_argument("Input UB matrix must have 9 elements");
+
+    m_UB = Kernel::Matrix<double>(3, 3);
+    for (size_t i = 0; i < 3; ++i) {
+      for (size_t j = 0; j < 3; ++j) {
+        m_UB[i][j] = ub_array[i * 3 + j];
+      }
+    }
+  }
+
+  return;
+}
+
+//--------------------------------------------------------------------------
+/** Export events from an MDEventWorkspace for future processing
+ * It is a convenient algorithm if number of events are few relative to
+ * number of detectors
+ */
+void ConvertCWSDMDtoHKL::exportEvents(
+    IMDEventWorkspace_sptr mdws, std::vector<Kernel::V3D> &vec_event_qsample,
+    std::vector<signal_t> &vec_event_signal,
+    std::vector<detid_t> &vec_event_det) {
+  // Set the size of the output vectors
+  size_t numevents = mdws->getNEvents();
+  g_log.information() << "Number of events = " << numevents << "\n";
+
+  vec_event_qsample.resize(numevents);
+  vec_event_signal.resize(numevents);
+  vec_event_det.resize(numevents);
+
+  // Go through to get value
+  IMDIterator *mditer = mdws->createIterator();
+  size_t nextindex = 1;
+  bool scancell = true;
+  size_t currindex = 0;
+  while (scancell) {
+    size_t numevent_cell = mditer->getNumEvents();
+    for (size_t iev = 0; iev < numevent_cell; ++iev) {
+      // Check
+      if (currindex >= vec_event_qsample.size())
+        throw std::runtime_error("Logic error in event size!");
+
+      float tempx = mditer->getInnerPosition(iev, 0);
+      float tempy = mditer->getInnerPosition(iev, 1);
+      float tempz = mditer->getInnerPosition(iev, 2);
+      signal_t signal = mditer->getInnerSignal(iev);
+      detid_t detid = mditer->getInnerDetectorID(iev);
+      Kernel::V3D qsample(tempx, tempy, tempz);
+      vec_event_qsample[currindex] = qsample;
+      vec_event_signal[currindex] = signal;
+      vec_event_det[currindex] = detid;
+
+      ++currindex;
+    }
+
+    // Advance to next cell
+    if (mditer->next()) {
+      // advance to next cell
+      mditer->jumpTo(nextindex);
+      ++nextindex;
+    } else {
+      // break the loop
+      scancell = false;
+    }
+  }
+
+  return;
+}
+
+//--------------------------------------------------------------------------
+/** Save Q-sample to file
+ */
+void ConvertCWSDMDtoHKL::saveMDToFile(
+    std::vector<std::vector<coord_t>> &vec_event_qsample,
+    std::vector<float> &vec_event_signal) {
+  // Get file name
+  std::string filename = getPropertyValue("QSampleFileName");
+
+  // Abort with an empty string
+  if (filename.size() == 0)
+    return;
+  if (vec_event_qsample.size() != vec_event_signal.size())
+    throw std::runtime_error(
+        "Input vectors of Q-sample and signal have different sizes.");
+
+  // Write to file
+  std::ofstream ofile;
+  ofile.open(filename.c_str());
+
+  size_t numevents = vec_event_qsample.size();
+  for (size_t i = 0; i < numevents; ++i) {
+    ofile << vec_event_qsample[i][0] << ", " << vec_event_qsample[i][1] << ", "
+          << vec_event_qsample[i][2] << ", " << vec_event_signal[i] << "\n";
+  }
+  ofile.close();
+
+  return;
+}
+
+//--------------------------------------------------------------------------
+/** Save HKL to file for 3D visualization
+ */
+void ConvertCWSDMDtoHKL::saveEventsToFile(
+    const std::string &filename, std::vector<Kernel::V3D> &vec_event_pos,
+    std::vector<signal_t> &vec_event_signal,
+    std::vector<detid_t> &vec_event_detid) {
+  // Check
+  if (vec_event_detid.size() != vec_event_pos.size() ||
+      vec_event_pos.size() != vec_event_signal.size())
+    throw std::invalid_argument(
+        "Input vectors for HKL, signal and detector ID have different size.");
+
+  std::ofstream ofile;
+  ofile.open(filename.c_str());
+
+  size_t numevents = vec_event_pos.size();
+  for (size_t i = 0; i < numevents; ++i) {
+    ofile << vec_event_pos[i].X() << ", " << vec_event_pos[i].Y() << ", "
+          << vec_event_pos[i].Z() << ", " << vec_event_signal[i] << ", "
+          << vec_event_detid[i] << "\n";
+  }
+  ofile.close();
+
+  return;
+}
+
+//--------------------------------------------------------------------------
+/** Convert from Q-sample to HKL
+ */
+void ConvertCWSDMDtoHKL::convertFromQSampleToHKL(
+    const std::vector<V3D> &q_vectors, std::vector<V3D> &miller_indices) {
+
+  Matrix<double> tempUB(m_UB);
+
+  int original_indexed = 0;
+  double original_error = 0;
+  double tolerance = 0.55; // to make sure no output is invalid
+  original_indexed = IndexingUtils::CalculateMillerIndices(
+      tempUB, q_vectors, tolerance, miller_indices, original_error);
+
+  g_log.notice() << "[DB] " << original_indexed << " peaks are indexed."
+                 << "\n";
+
+  return;
+}
+
+//----------------------------------------------------------------------------------------------
+/** Create output workspace
+ * @brief ConvertCWSDExpToMomentum::createExperimentMDWorkspace
+ * @return
+ */
+API::IMDEventWorkspace_sptr ConvertCWSDMDtoHKL::createHKLMDWorkspace(
+    const std::vector<Kernel::V3D> &vec_hkl,
+    const std::vector<signal_t> &vec_signal,
+    const std::vector<detid_t> &vec_detid) {
+  // Check
+  if (vec_hkl.size() != vec_signal.size() ||
+      vec_signal.size() != vec_detid.size())
+    throw std::invalid_argument("Input vectors for HKL, signal and detector "
+                                "IDs are of different size!");
+
+  // Create workspace in Q_sample with dimenion as 3
+  size_t nDimension = 3;
+  IMDEventWorkspace_sptr mdws =
+      MDEventFactory::CreateMDWorkspace(nDimension, "MDEvent");
+
+  // Extract Dimensions and add to the output workspace.
+  std::vector<std::string> vec_ID(3);
+  vec_ID[0] = "H";
+  vec_ID[1] = "K";
+  vec_ID[2] = "L";
+
+  std::vector<std::string> dimensionNames(3);
+  dimensionNames[0] = "H";
+  dimensionNames[1] = "K";
+  dimensionNames[2] = "L";
+
+  Mantid::Kernel::SpecialCoordinateSystem coordinateSystem =
+      Mantid::Kernel::HKL;
+
+  // Add dimensions
+  std::vector<double> m_extentMins(3);
+  std::vector<double> m_extentMaxs(3);
+  std::vector<size_t> m_numBins(3, 100);
+  getRange(vec_hkl, m_extentMins, m_extentMaxs);
+
+  for (size_t i = 0; i < nDimension; ++i) {
+    std::string id = vec_ID[i];
+    std::string name = dimensionNames[i];
+    // std::string units = "A^-1";
+    std::string units = "";
+    mdws->addDimension(
+        Geometry::MDHistoDimension_sptr(new Geometry::MDHistoDimension(
+            id, name, units, static_cast<coord_t>(m_extentMins[i]),
+            static_cast<coord_t>(m_extentMaxs[i]), m_numBins[i])));
+  }
+
+  // Set coordinate system
+  mdws->setCoordinateSystem(coordinateSystem);
+
+  // Creates a new instance of the MDEventInserter to output workspace
+  MDEventWorkspace<MDEvent<3>, 3>::sptr mdws_mdevt_3 =
+      boost::dynamic_pointer_cast<MDEventWorkspace<MDEvent<3>, 3>>(mdws);
+  MDEventInserter<MDEventWorkspace<MDEvent<3>, 3>::sptr> inserter(mdws_mdevt_3);
+
+  // Go though each spectrum to conver to MDEvent
+  for (size_t iq = 0; iq < vec_hkl.size(); ++iq) {
+    Kernel::V3D hkl = vec_hkl[iq];
+    std::vector<Mantid::coord_t> millerindex(3);
+    millerindex[0] = static_cast<float>(hkl.X());
+    millerindex[1] = static_cast<float>(hkl.Y());
+    millerindex[2] = static_cast<float>(hkl.Z());
+
+    signal_t signal = vec_signal[iq];
+    signal_t error = std::sqrt(signal);
+    uint16_t runnumber = 1;
+    detid_t detid = vec_detid[iq];
+
+    // Insert
+    inserter.insertMDEvent(
+        static_cast<float>(signal), static_cast<float>(error * error),
+        static_cast<uint16_t>(runnumber), detid, millerindex.data());
+  }
+
+  return mdws;
+}
+
+void ConvertCWSDMDtoHKL::getRange(const std::vector<Kernel::V3D> vec_hkl,
+                                  std::vector<double> &extentMins,
+                                  std::vector<double> &extentMaxs) {
+  assert(extentMins.size() == 3);
+  assert(extentMaxs.size() == 3);
+
+  for (size_t i = 0; i < 3; ++i) {
+    double minvalue = vec_hkl[0][i];
+    double maxvalue = vec_hkl[0][i];
+    for (size_t j = 1; j < vec_hkl.size(); ++j) {
+      double thisvalue = vec_hkl[j][i];
+      if (thisvalue < minvalue)
+        minvalue = thisvalue;
+      else if (thisvalue > maxvalue)
+        maxvalue = thisvalue;
+    }
+    extentMins[i] = minvalue;
+    extentMaxs[i] = maxvalue;
+  }
+
+  return;
+}
+
+} // namespace MDAlgorithms
+} // namespace Mantid
diff --git a/Framework/MDAlgorithms/test/ConvertCWSDMDtoHKLTest.h b/Framework/MDAlgorithms/test/ConvertCWSDMDtoHKLTest.h
new file mode 100644
index 0000000000000000000000000000000000000000..d4044fec95e162a24b7145d0c042364eebd9943a
--- /dev/null
+++ b/Framework/MDAlgorithms/test/ConvertCWSDMDtoHKLTest.h
@@ -0,0 +1,131 @@
+#ifndef MANTID_MDALGORITHMS_CONVERTCWSDMDTOHKLTEST_H_
+#define MANTID_MDALGORITHMS_CONVERTCWSDMDTOHKLTEST_H_
+
+#include <cxxtest/TestSuite.h>
+
+#include "MantidMDAlgorithms/ConvertCWSDMDtoHKL.h"
+#include "MantidTestHelpers/ComponentCreationHelper.h"
+#include "MantidTestHelpers/WorkspaceCreationHelper.h"
+#include "MantidAPI/IMDEventWorkspace.h"
+#include "MantidAPI/FrameworkManager.h"
+#include "MantidGeometry/Instrument.h"
+
+using Mantid::MDAlgorithms::ConvertCWSDMDtoHKL;
+
+using namespace Mantid::API;
+using namespace Mantid::MDAlgorithms;
+using namespace Mantid::DataObjects;
+using Mantid::Geometry::Instrument_sptr;
+using Mantid::Kernel::PropertyWithValue;
+
+class ConvertCWSDMDtoHKLTest : public CxxTest::TestSuite {
+public:
+  // This pair of boilerplate methods prevent the suite being created statically
+  // This means the constructor isn't called when running other tests
+  static ConvertCWSDMDtoHKLTest *createSuite() {
+    return new ConvertCWSDMDtoHKLTest();
+  }
+  static void destroySuite(ConvertCWSDMDtoHKLTest *suite) { delete suite; }
+
+  //-------------------------------------------------------------------------------
+  void test_init() {
+    createMDEW();
+
+    ConvertCWSDMDtoHKL alg;
+    alg.initialize();
+    TS_ASSERT(alg.isInitialized());
+  }
+
+  //-------------------------------------------------------------------------------
+  void test_convertToHKL() {
+    ConvertCWSDMDtoHKL alg;
+    alg.initialize();
+
+    TS_ASSERT_THROWS_NOTHING(
+        alg.setPropertyValue("InputWorkspace", m_qsampleWS->name()));
+    TS_ASSERT_THROWS_NOTHING(alg.setPropertyValue(
+        "UBMatrix", "1.0, 0.5, 0., -0.2, 2.0, 0.4, 0., 1.11, 3.9"));
+    TS_ASSERT_THROWS_NOTHING(alg.setPropertyValue("OutputWorkspace", "HKLMD"));
+
+    alg.execute();
+    TS_ASSERT(alg.isExecuted());
+
+    IMDEventWorkspace_sptr hklws =
+        boost::dynamic_pointer_cast<IMDEventWorkspace>(
+            AnalysisDataService::Instance().retrieve("HKLMD"));
+    TS_ASSERT(hklws);
+
+    size_t numevents = hklws->getNEvents();
+    TS_ASSERT_EQUALS(numevents, 100);
+
+    TS_ASSERT_EQUALS(hklws->getSpecialCoordinateSystem(),
+                     Mantid::Kernel::SpecialCoordinateSystem::HKL);
+  }
+
+private:
+  //-------------------------------------------------------------------------------
+  /** Create the (blank) MDEW */
+  void createMDEW() {
+    // ---- Start with empty MDEW ----
+    FrameworkManager::Instance().exec(
+        "CreateMDWorkspace", 18, "Dimensions", "3", "EventType", "MDEvent",
+        "Extents", "-10,10,-10,10,-10,10", "Names",
+        "Q_sample_x,Q_sample_y,Q_sample_z", "Units",
+        "Q_Sample_X,Q_Sample_Y,Q_Sample_Z", "SplitInto", "5", "SplitThreshold",
+        "20", "MaxRecursionDepth", "15", "OutputWorkspace", "MDEWS");
+
+    // Give it an instrument
+    Instrument_sptr inst =
+        ComponentCreationHelper::createTestInstrumentRectangular2(1, 100, 0.05);
+
+    TS_ASSERT_THROWS_NOTHING(
+        m_qsampleWS =
+            AnalysisDataService::Instance().retrieveWS<IMDEventWorkspace>(
+                "MDEWS"));
+    ExperimentInfo_sptr ei(new ExperimentInfo());
+    ei->setInstrument(inst);
+    // Give it a run number
+    ei->mutableRun().addProperty(
+        new PropertyWithValue<std::string>("run_number", "12345"), true);
+    m_qsampleWS->addExperimentInfo(ei);
+
+    // Add events
+    size_t num_events = 100;
+    double peakcentre_x = 0.4;
+    double peakcentre_y = -1.2;
+    double peakcentre_z = -1.0;
+    double radius = 0.5;
+
+    // Add half of the events
+    std::ostringstream mess;
+    mess << num_events / 2 << ", " << peakcentre_x << ", " << peakcentre_y
+         << ", " << peakcentre_z << ", " << radius;
+    std::cout << mess.str() << "\n";
+    FrameworkManager::Instance().exec("FakeMDEventData", 4, "InputWorkspace",
+                                      "MDEWS", "PeakParams",
+                                      mess.str().c_str());
+
+    // Add a center with more events (half radius, half the total), to create a
+    // "peak"
+    std::ostringstream mess2;
+    mess2 << num_events / 2 << ", " << peakcentre_x << ", " << peakcentre_y
+          << ", " << peakcentre_z << ", " << radius * 0.25;
+    std::cout << mess2.str() << "\n";
+    FrameworkManager::Instance().exec("FakeMDEventData", 4, "InputWorkspace",
+                                      "MDEWS", "PeakParams",
+                                      mess2.str().c_str());
+
+    // Check
+    size_t numevents = m_qsampleWS->getNEvents();
+    TS_ASSERT_EQUALS(numevents, 100);
+
+    m_qsampleWS->setCoordinateSystem(
+        Mantid::Kernel::SpecialCoordinateSystem::QSample);
+
+    return;
+  }
+
+  IMDEventWorkspace_sptr m_qsampleWS;
+};
+
+#endif /* MANTID_MDALGORITHMS_CONVERTCWSDMDTOHKLTEST_H_ */
diff --git a/Testing/Data/DocTest/HB3A_exp0406_scan0298.dat.md5 b/Testing/Data/DocTest/HB3A_exp0406_scan0298.dat.md5
new file mode 100644
index 0000000000000000000000000000000000000000..1d23995b3815a9e8457c03d0277dbe8457626dbe
--- /dev/null
+++ b/Testing/Data/DocTest/HB3A_exp0406_scan0298.dat.md5
@@ -0,0 +1 @@
+82a989552a9d6b41fb0d477b3e26b57a
diff --git a/Testing/Data/DocTest/HB3A_exp406_scan0298_0022.xml.md5 b/Testing/Data/DocTest/HB3A_exp406_scan0298_0022.xml.md5
new file mode 100644
index 0000000000000000000000000000000000000000..b02a2cacffa806501e5c08426083152fa419e1f8
--- /dev/null
+++ b/Testing/Data/DocTest/HB3A_exp406_scan0298_0022.xml.md5
@@ -0,0 +1 @@
+9891ad8c3a37213308ccb8ba9500989f
diff --git a/docs/source/algorithms/ConvertCWSDMDtoHKL-v1.rst b/docs/source/algorithms/ConvertCWSDMDtoHKL-v1.rst
new file mode 100644
index 0000000000000000000000000000000000000000..9c0672885f008b441c70c8aad1285801ff1aa9e5
--- /dev/null
+++ b/docs/source/algorithms/ConvertCWSDMDtoHKL-v1.rst
@@ -0,0 +1,108 @@
+.. algorithm::
+
+.. summary::
+
+.. alias::
+
+.. properties::
+
+Description
+-----------
+
+This algorithms is to convert an MDEventWorkspace in Q-sample coordinate 
+to HKL coordindate for a reactor-based four-circle single crystal diffractometer.
+Meanwhile, the algorithm is able to export the MDEvents to file.
+
+Outline of algorithm
+####################
+
+1. Convert MDEvent's coordinate system
+
+2. Export MDEvent in Q-sample coordinate and HKL coordinate.
+
+
+Inputs
+######
+
+**InputWorkspace** is an MDEventWorkspace ???.
+
+**PeakWorkspace** is an optional input as in many cases especially after calculating UB matrix, ... 
+
+**UBMatrix** is ???. 
+
+
+Outputs
+#######
+
+The output is an MDEventWorkspace that... .. 
+
+MDEvent
++++++++
+
+Each MDEvent in output MDEventWorkspace contain 
+* *H*
+* *K*
+* *L*
+* Signal
+* Error
+* Detector ID
+* Run Number
+
+Compare with ConvertMD
+======================
+
+Comparing with ????
+
+Usage
+-----
+
+**Example - Convert detector counts of an HB3A's measurement to HKL.**
+
+.. testcode:: ExConvertHB3AToHKL
+
+  # Create input table workspaces for experiment information and virtual instrument parameters
+  CollectHB3AExperimentInfo(ExperimentNumber='406', ScanList='298', PtLists='-1,22', 
+      DataDirectory='',
+      GenerateVirtualInstrument=False,
+      OutputWorkspace='ExpInfoTable', DetectorTableWorkspace='VirtualInstrumentTable')
+
+  # Convert to MDWorkspace
+  ConvertCWSDExpToMomentum(InputWorkspace='ExpInfoTable', CreateVirtualInstrument=False, 
+      OutputWorkspace='QSampleMD',
+      Directory='')
+      
+  ConvertCWSDMDtoHKL(InputWorkspace='QSampleMD', 
+                UBMatrix='0.13329061, 0.07152342, -0.04215966, 0.01084569, -0.1620849, 0.0007607, -0.14018499, -0.07841385, -0.04002737',
+                OutputWorkspace='HKLMD')
+              
+  
+  # Examine
+  mdws = mtd['QSampleMD']
+  print 'Output MDEventWorkspace has %d events.'%(mdws.getNEvents())
+  
+  hklws = mtd['HKLMD']
+  print 'H: range from %.5f to %.5f.' % (hklws.getXDimension().getMinimum(), hklws.getXDimension().getMaximum())
+  print 'K: range from %.5f to %.5f.' % (hklws.getYDimension().getMinimum(), hklws.getYDimension().getMaximum())
+  print 'L: range from %.5f to %.5f.' % (hklws.getZDimension().getMinimum(), hklws.getZDimension().getMaximum())
+
+.. testcleanup::  ExConvertHB3AToHKL
+
+  DeleteWorkspace(Workspace='QSampleMD')
+  DeleteWorkspace(Workspace='ExpInfoTable')
+  DeleteWorkspace(Workspace='VirtualInstrumentTable')
+  DeleteWorkspace(Workspace='HKLMD')
+  DeleteWorkspace(Workspace='HB3A_exp0406_scan0298')
+  DeleteWorkspace(Workspace='spicematrixws')
+
+Output:
+
+.. testoutput:: ExConvertHB3AToHKL
+
+  Output MDEventWorkspace has 1631 events.
+  H: range from -0.24012 to 0.29856.
+  K: range from -0.41417 to 0.42250.
+  L: range from 4.83863 to 7.23861.
+
+.. categories::
+
+.. sourcelink::