diff --git a/Framework/Algorithms/src/GetAllEi.cpp b/Framework/Algorithms/src/GetAllEi.cpp
index 60418d5071ea437e50237e3f826e2d099efadc9e..2ba9d8bff8c4935ae69d7d8aa3eb1b2b7efa5590 100644
--- a/Framework/Algorithms/src/GetAllEi.cpp
+++ b/Framework/Algorithms/src/GetAllEi.cpp
@@ -754,7 +754,7 @@ bool refineEGuess(const MantidVec &eBins, const MantidVec &signal,
 struct peakKeeper2 {
   double left_rng;
   double right_rng;
-  peakKeeper2(){};
+  peakKeeper2() : left_rng(.0), right_rng(.0){};
   peakKeeper2(double left, double right) : left_rng(left), right_rng(right) {}
 };
 }
@@ -985,6 +985,12 @@ GetAllEi::getAvrgLogValue(const API::MatrixWorkspace_sptr &inputWS,
   auto pTimeSeries =
       dynamic_cast<Kernel::TimeSeriesProperty<double> *>(pIProperty);
 
+  if (!pTimeSeries) {
+    throw std::runtime_error(
+        "Could not retrieve a time series property for the property name " +
+        propertyName);
+  }
+
   if (splitter.size() == 0) {
     auto TimeStart = inputWS->run().startTime();
     auto TimeEnd = inputWS->run().endTime();
diff --git a/Framework/Algorithms/src/IdentifyNoisyDetectors.cpp b/Framework/Algorithms/src/IdentifyNoisyDetectors.cpp
index 8970268ec6e453b2326086689c3977de04cf60a3..754509ce3c9bb695d51fcf4ecd33c927b2509ffd 100644
--- a/Framework/Algorithms/src/IdentifyNoisyDetectors.cpp
+++ b/Framework/Algorithms/src/IdentifyNoisyDetectors.cpp
@@ -137,6 +137,11 @@ void IdentifyNoisyDetectors::getStdDev(MatrixWorkspace_sptr valid,
     }
   }
 
+  if (0 == count) {
+    // all values are zero, no need to loop
+    return;
+  }
+
   mean = mean / count;
   double stddev = sqrt((mean2 / count) - std::pow(mean, 2));
 
diff --git a/Framework/Algorithms/src/ResizeRectangularDetector.cpp b/Framework/Algorithms/src/ResizeRectangularDetector.cpp
index 564cb8d85ce64d5dbc79efe15edefc9ad619458e..9378f6e68407b8b0936036727b89c9c895ab4cb9 100644
--- a/Framework/Algorithms/src/ResizeRectangularDetector.cpp
+++ b/Framework/Algorithms/src/ResizeRectangularDetector.cpp
@@ -74,8 +74,21 @@ void ResizeRectangularDetector::exec() {
   Instrument_sptr inst;
   if (inputW) {
     inst = boost::const_pointer_cast<Instrument>(inputW->getInstrument());
+    if (!inst)
+      throw std::runtime_error("Could not get a valid instrument from the "
+                               "MatrixWorkspace provided as input");
+
   } else if (inputP) {
     inst = boost::const_pointer_cast<Instrument>(inputP->getInstrument());
+    if (!inst)
+      throw std::runtime_error("Could not get a valid instrument from the "
+                               "PeaksWorkspace provided as input");
+  } else {
+    if (!inst)
+      throw std::runtime_error("Could not get a valid instrument from the "
+                               "workspace and it does not seem to be valid as "
+                               "input (must be either MatrixWorkspace or "
+                               "PeaksWorkspace");
   }
 
   std::string ComponentName = getPropertyValue("ComponentName");
diff --git a/Framework/Crystal/src/IntegratePeakTimeSlices.cpp b/Framework/Crystal/src/IntegratePeakTimeSlices.cpp
index 9828bea2f54bfa54db588459eca4c19b2d772842..92558503c80fd9fed7c50e719f19c17ddd805321 100644
--- a/Framework/Crystal/src/IntegratePeakTimeSlices.cpp
+++ b/Framework/Crystal/src/IntegratePeakTimeSlices.cpp
@@ -595,7 +595,8 @@ void IntegratePeakTimeSlices::exec() {
 
             lastRow = (int)(params[i] + .5);
             i = find("Mcol", names);
-            lastCol = (int)(params[i] + .5);
+            if (i >= 0)
+              lastCol = (int)(params[i] + .5);
             prog.report();
 
           } else if (dir > 0)
diff --git a/Framework/CurveFitting/src/Algorithms/FitPowderDiffPeaks.cpp b/Framework/CurveFitting/src/Algorithms/FitPowderDiffPeaks.cpp
index 87801460543315e7aaccd4501e43e74facf27e8f..71021ad4567b7bbed8fc34f07954ebad74a60fa3 100644
--- a/Framework/CurveFitting/src/Algorithms/FitPowderDiffPeaks.cpp
+++ b/Framework/CurveFitting/src/Algorithms/FitPowderDiffPeaks.cpp
@@ -2081,7 +2081,8 @@ bool FitPowderDiffPeaks::doFitMultiplePeaks(
     bool fitgood = doFitNPeaksSimple(dataws, wsindex, peaksfunc, peakfuncs,
                                      "Levenberg-MarquardtMD", 1000, chi2);
 
-    evergood = evergood || fitgood;
+    // not required. before loop starts, evergood=fitgood WITH fitgood==true
+    // evergood = evergood || fitgood;
 
     // c) Process the result
     if (!fitgood)
@@ -2098,7 +2099,8 @@ bool FitPowderDiffPeaks::doFitMultiplePeaks(
   storeFunctionParameters(peaksfunc, peaksfuncparams);
   fitgood = doFitNPeaksSimple(dataws, wsindex, peaksfunc, peakfuncs,
                               "Levenberg-MarquardtMD", 1000, chi2);
-  evergood = evergood || fitgood;
+  // not required. before, evergood=fitgood WITH fitgood==true
+  // evergood = evergood || fitgood;
 
   if (!fitgood)
     restoreFunctionParameters(peaksfunc, peaksfuncparams);
diff --git a/Framework/CurveFitting/src/Algorithms/SplineBackground.cpp b/Framework/CurveFitting/src/Algorithms/SplineBackground.cpp
index a19fa51061060d39206dd760f8a1d8db453d9fb0..c9ba83eb4f203689aa8651bdf57762652a205b0c 100644
--- a/Framework/CurveFitting/src/Algorithms/SplineBackground.cpp
+++ b/Framework/CurveFitting/src/Algorithms/SplineBackground.cpp
@@ -66,8 +66,8 @@ void SplineBackground::exec() {
   bool isMasked = inWS->hasMaskedBins(spec);
   std::vector<int> masked(Y.size());
   if (isMasked) {
-    for (auto it = inWS->maskedBins(spec).begin();
-         it != inWS->maskedBins(spec).end(); ++it)
+    auto maskedBins = inWS->maskedBins(spec);
+    for (auto it = maskedBins.begin(); it != maskedBins.end(); ++it)
       masked[it->first] = 1;
     n -= static_cast<int>(inWS->maskedBins(spec).size());
   }
diff --git a/Framework/DataHandling/inc/MantidDataHandling/LoadIsawDetCal.h b/Framework/DataHandling/inc/MantidDataHandling/LoadIsawDetCal.h
index 7c789334c19d420896d82e3c754599dfc9ef10f7..65dce045094d0c534654bed7749e496ba0c94b40 100644
--- a/Framework/DataHandling/inc/MantidDataHandling/LoadIsawDetCal.h
+++ b/Framework/DataHandling/inc/MantidDataHandling/LoadIsawDetCal.h
@@ -5,6 +5,8 @@
 // Includes
 //----------------------------------------------------------------------
 #include "MantidAPI/Algorithm.h"
+#include "MantidGeometry/Instrument.h"
+
 #include <gsl/gsl_statistics.h>
 #include <gsl/gsl_multifit_nlin.h>
 #include <gsl/gsl_multimin.h>
@@ -70,6 +72,8 @@ private:
   // Overridden Algorithm methods
   void init();
   void exec();
+
+  Geometry::Instrument_sptr getCheckInst(API::Workspace_sptr ws);
 };
 
 } // namespace DataHandling
diff --git a/Framework/DataHandling/src/GroupDetectors2.cpp b/Framework/DataHandling/src/GroupDetectors2.cpp
index 7567cc8e6da22794430ce706cb97c7f5d4c1aeca..8e9b3d0d0927e0d5a746f0cf5c994dfbc6a40d3c 100644
--- a/Framework/DataHandling/src/GroupDetectors2.cpp
+++ b/Framework/DataHandling/src/GroupDetectors2.cpp
@@ -353,8 +353,9 @@ void GroupDetectors2::getGroups(API::MatrixWorkspace_const_sptr workspace,
     }
     // check we don't have an index that is too high for the workspace
     size_t maxIn = static_cast<size_t>(workspace->getNumberHistograms() - 1);
-    auto it = m_GroupSpecInds[0].begin();
-    for (; it != m_GroupSpecInds[0].end(); ++it) {
+    auto indices0 = m_GroupSpecInds[0];
+    auto it = indices0.begin();
+    for (; it != indices0.end(); ++it) {
       if (*it > maxIn) {
         g_log.error() << "Spectra index " << *it
                       << " doesn't exist in the input workspace, the highest "
@@ -375,8 +376,9 @@ void GroupDetectors2::getGroups(API::MatrixWorkspace_const_sptr workspace,
 
   // up date unUsedSpec, this is used to find duplicates and when the user has
   // set KeepUngroupedSpectra
-  auto index = m_GroupSpecInds[0].begin();
-  for (; index != m_GroupSpecInds[0].end();
+  auto indices0 = m_GroupSpecInds[0];
+  auto index = indices0.begin();
+  for (; index != indices0.end();
        ++index) { // the vector<int> m_GroupSpecInds[0] must not index contain
                   // numbers that don't exist in the workspaace
     if (unUsedSpec[*index] != USED) {
diff --git a/Framework/DataHandling/src/LoadIsawDetCal.cpp b/Framework/DataHandling/src/LoadIsawDetCal.cpp
index 2fc3168b716430b093a5fd2da80f0ef2f1aa17fa..02828ea742261cedb9b45d808a59049f4846d0fc 100644
--- a/Framework/DataHandling/src/LoadIsawDetCal.cpp
+++ b/Framework/DataHandling/src/LoadIsawDetCal.cpp
@@ -40,52 +40,6 @@ LoadIsawDetCal::LoadIsawDetCal() : API::Algorithm() {}
 /// Destructor
 LoadIsawDetCal::~LoadIsawDetCal() {}
 
-/**
- * The intensity function calculates the intensity as a function of detector
- * position and angles
- * @param x :: The shift along the X-axis
- * @param y :: The shift along the Y-axis
- * @param z :: The shift along the Z-axis
- * @param detname :: The detector name
- * @param ws :: The workspace
- */
-
-void LoadIsawDetCal::center(double x, double y, double z, std::string detname,
-                            API::Workspace_sptr ws) {
-  MatrixWorkspace_sptr inputW =
-      boost::dynamic_pointer_cast<MatrixWorkspace>(ws);
-  PeaksWorkspace_sptr inputP = boost::dynamic_pointer_cast<PeaksWorkspace>(ws);
-
-  // Get some stuff from the input workspace
-  Instrument_sptr inst;
-  if (inputW) {
-    inst = boost::const_pointer_cast<Instrument>(inputW->getInstrument());
-  } else if (inputP) {
-    inst = boost::const_pointer_cast<Instrument>(inputP->getInstrument());
-  }
-
-  IComponent_const_sptr comp = inst->getComponentByName(detname);
-  if (comp == 0) {
-    std::ostringstream mess;
-    mess << "Component with name " << detname << " was not found.";
-    g_log.error(mess.str());
-    throw std::runtime_error(mess.str());
-  }
-
-  // Do the move
-  using namespace Geometry::ComponentHelper;
-  TransformType positionType = Absolute;
-  if (inputW) {
-    Geometry::ParameterMap &pmap = inputW->instrumentParameters();
-    Geometry::ComponentHelper::moveComponent(*comp, pmap, V3D(x, y, z),
-                                             positionType);
-  } else if (inputP) {
-    Geometry::ParameterMap &pmap = inputP->instrumentParameters();
-    Geometry::ComponentHelper::moveComponent(*comp, pmap, V3D(x, y, z),
-                                             positionType);
-  }
-}
-
 /** Initialisation method
 */
 void LoadIsawDetCal::init() {
@@ -118,13 +72,7 @@ void LoadIsawDetCal::exec() {
       boost::dynamic_pointer_cast<MatrixWorkspace>(ws);
   PeaksWorkspace_sptr inputP = boost::dynamic_pointer_cast<PeaksWorkspace>(ws);
 
-  // Get some stuff from the input workspace
-  Instrument_sptr inst;
-  if (inputW) {
-    inst = boost::const_pointer_cast<Instrument>(inputW->getInstrument());
-  } else if (inputP) {
-    inst = boost::const_pointer_cast<Instrument>(inputP->getInstrument());
-  }
+  Instrument_sptr inst = getCheckInst(ws);
 
   std::string instname = inst->getName();
 
@@ -437,5 +385,82 @@ void LoadIsawDetCal::exec() {
   return;
 }
 
+/**
+ * The intensity function calculates the intensity as a function of detector
+ * position and angles
+ * @param x :: The shift along the X-axis
+ * @param y :: The shift along the Y-axis
+ * @param z :: The shift along the Z-axis
+ * @param detname :: The detector name
+ * @param ws :: The workspace
+ */
+
+void LoadIsawDetCal::center(double x, double y, double z, std::string detname,
+                            API::Workspace_sptr ws) {
+
+  Instrument_sptr inst = getCheckInst(ws);
+
+  IComponent_const_sptr comp = inst->getComponentByName(detname);
+  if (comp == 0) {
+    std::ostringstream mess;
+    mess << "Component with name " << detname << " was not found.";
+    g_log.error(mess.str());
+    throw std::runtime_error(mess.str());
+  }
+
+  // Do the move
+  using namespace Geometry::ComponentHelper;
+  TransformType positionType = Absolute;
+  MatrixWorkspace_sptr inputW =
+      boost::dynamic_pointer_cast<MatrixWorkspace>(ws);
+  PeaksWorkspace_sptr inputP = boost::dynamic_pointer_cast<PeaksWorkspace>(ws);
+  if (inputW) {
+    Geometry::ParameterMap &pmap = inputW->instrumentParameters();
+    Geometry::ComponentHelper::moveComponent(*comp, pmap, V3D(x, y, z),
+                                             positionType);
+  } else if (inputP) {
+    Geometry::ParameterMap &pmap = inputP->instrumentParameters();
+    Geometry::ComponentHelper::moveComponent(*comp, pmap, V3D(x, y, z),
+                                             positionType);
+  }
+}
+
+/**
+ * Gets the instrument of the workspace, checking that the workspace
+ * and the instrument are as expected.
+ *
+ * @param ws workspace (expected Matrix or Peaks Workspace)
+ *
+ * @throw std::runtime_error if there's any problem with the workspace or it is
+ * not possible to get an instrument object from it
+ */
+Instrument_sptr LoadIsawDetCal::getCheckInst(API::Workspace_sptr ws) {
+  MatrixWorkspace_sptr inputW =
+      boost::dynamic_pointer_cast<MatrixWorkspace>(ws);
+  PeaksWorkspace_sptr inputP = boost::dynamic_pointer_cast<PeaksWorkspace>(ws);
+
+  // Get some stuff from the input workspace
+  Instrument_sptr inst;
+  if (inputW) {
+    inst = boost::const_pointer_cast<Instrument>(inputW->getInstrument());
+    if (!inst)
+      throw std::runtime_error("Could not get a valid instrument from the "
+                               "MatrixWorkspace provided as input");
+  } else if (inputP) {
+    inst = boost::const_pointer_cast<Instrument>(inputP->getInstrument());
+    if (!inst)
+      throw std::runtime_error("Could not get a valid instrument from the "
+                               "PeaksWorkspace provided as input");
+  } else {
+    if (!inst)
+      throw std::runtime_error("Could not get a valid instrument from the "
+                               "workspace which does not seem to be valid as "
+                               "input (must be either MatrixWorkspace or "
+                               "PeaksWorkspace");
+  }
+
+  return inst;
+}
+
 } // namespace Algorithm
 } // namespace Mantid
diff --git a/Framework/DataHandling/src/RotateInstrumentComponent.cpp b/Framework/DataHandling/src/RotateInstrumentComponent.cpp
index 8cb5b36d8803563a9ccf23cb0b265edaaca362dd..adf61ef3c061e495d3f8ea629a531897fccae69a 100644
--- a/Framework/DataHandling/src/RotateInstrumentComponent.cpp
+++ b/Framework/DataHandling/src/RotateInstrumentComponent.cpp
@@ -61,8 +61,20 @@ void RotateInstrumentComponent::exec() {
   Instrument_sptr inst;
   if (inputW) {
     inst = boost::const_pointer_cast<Instrument>(inputW->getInstrument());
+    if (!inst)
+      throw std::runtime_error("Could not get a valid instrument from the "
+                               "MatrixWorkspace provided as input");
   } else if (inputP) {
     inst = boost::const_pointer_cast<Instrument>(inputP->getInstrument());
+    if (!inst)
+      throw std::runtime_error("Could not get a valid instrument from the "
+                               "PeaksWorkspace provided as input");
+  } else {
+    if (!inst)
+      throw std::runtime_error("Could not get a valid instrument from the "
+                               "workspace and it does not seem to be valid as "
+                               "input (must be either MatrixWorkspace or "
+                               "PeaksWorkspace");
   }
 
   const std::string ComponentName = getProperty("ComponentName");
diff --git a/Framework/DataObjects/inc/MantidDataObjects/MDGridBox.tcc b/Framework/DataObjects/inc/MantidDataObjects/MDGridBox.tcc
index 4de121711232aa6c6a24fd477c7118097ca62778..779c3a641cc521b38ff68c8af3193c88f37c4e64 100644
--- a/Framework/DataObjects/inc/MantidDataObjects/MDGridBox.tcc
+++ b/Framework/DataObjects/inc/MantidDataObjects/MDGridBox.tcc
@@ -1462,8 +1462,8 @@ TMDE(void MDGridBox)::integrateCylinder(
       // Distance from center to the peak integration center
       coord_t out[nd];
       radiusTransform.apply(boxCenter, out);
-      if (out[0] < std::sqrt(diagonalSquared * 0.72 + radius * radius) &&
-          (nd >= 1 &&
+      if ((nd >= 1) && out[0] < std::sqrt(diagonalSquared * 0.72 + radius * radius) &&
+          (nd >= 2 &&
            std::fabs(out[1]) <
                std::sqrt(diagonalSquared * 0.72 + 0.25 * length * length))) {
         // If the center is closer than the size of the box, then it MIGHT be
diff --git a/Framework/Geometry/src/Instrument/InstrumentDefinitionParser.cpp b/Framework/Geometry/src/Instrument/InstrumentDefinitionParser.cpp
index f4c9afef815111745fea386715ae9a79b4d531ea..547f95e5a70e134f2a68d069a107be1b9c194574 100644
--- a/Framework/Geometry/src/Instrument/InstrumentDefinitionParser.cpp
+++ b/Framework/Geometry/src/Instrument/InstrumentDefinitionParser.cpp
@@ -1502,8 +1502,16 @@ void InstrumentDefinitionParser::populateIdList(Poco::XML::Element *pE,
     if (pE->hasAttribute("step"))
       increment = atoi((pE->getAttribute("step")).c_str());
 
+    if (0 == increment) {
+      std::stringstream ss;
+      ss << "The step element cannot be zero, got start: " << startID
+         << ", end: " << endID << ", step: " << increment;
+      throw Kernel::Exception::InstrumentDefinitionError(ss.str(), filename);
+    }
+
     // check the start end and increment values are sensible
-    if (((endID - startID) / increment) < 0) {
+    int steps = (endID - startID) / increment;
+    if (steps < 0) {
       std::stringstream ss;
       ss << "The start, end, and step elements do not allow a single id in the "
             "idlist entry - ";
@@ -1513,7 +1521,7 @@ void InstrumentDefinitionParser::populateIdList(Poco::XML::Element *pE,
       throw Kernel::Exception::InstrumentDefinitionError(ss.str(), filename);
     }
 
-    idList.vec.reserve((endID - startID) / increment);
+    idList.vec.reserve(steps);
     for (int i = startID; i != endID + increment; i += increment) {
       idList.vec.push_back(i);
     }
diff --git a/Framework/ICat/src/GSoap/stdsoap2.cpp b/Framework/ICat/src/GSoap/stdsoap2.cpp
index 252bc7ae6514f1f8380bd35f9c89fcc5e46abd54..d351d6dcbe205759e64022794e4a7dcbbd5662d5 100644
--- a/Framework/ICat/src/GSoap/stdsoap2.cpp
+++ b/Framework/ICat/src/GSoap/stdsoap2.cpp
@@ -312,9 +312,21 @@ static const char *soap_strerror(struct soap *);
     ioctl(fd, 0 /*FIONBIO*/, &nonblocking);                                    \
   }
 #else
-#define SOAP_SOCKBLOCK(fd) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) & ~O_NONBLOCK);
+#define SOAP_SOCKBLOCK(fd)                                                     \
+  {                                                                            \
+    int retv = fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) & ~O_NONBLOCK);           \
+    if (retv < 0) {                                                            \
+      DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SOAP_SOCKBLOCK (fcntl) failed\n"));   \
+    }                                                                          \
+  }
 #define SOAP_SOCKNONBLOCK(fd)                                                  \
-  fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
+  {                                                                            \
+    int retv = fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);            \
+    if (retv < 0) {                                                            \
+      DBGLOG(TEST,                                                             \
+             SOAP_MESSAGE(fdebug, "SOAP_SOCNONKBLOCK (fcntl) failed\n"));      \
+    }                                                                          \
+  }
 #endif
 
 #endif
@@ -2348,7 +2360,8 @@ int SOAP_FMAC2 soap_resolve(struct soap *soap) {
       } else if (*ip->id == '#') {
         DBGLOG(TEST,
                SOAP_MESSAGE(fdebug, "Missing data for id='%s'\n", ip->id));
-        strncpy(soap->id, ip->id + 1, sizeof(soap->id));
+        strncpy(soap->id, ip->id + 1, sizeof(soap->id) - 1);
+        soap->id[sizeof(soap->id) - 1] = '\0';
         return soap->error = SOAP_MISSING_ID;
       }
     }
@@ -3206,9 +3219,10 @@ const char *SOAP_FMAC2 soap_ssl_error(struct soap *soap, int ret) {
 #ifdef WITH_OPENSSL
   int err = SSL_get_error(soap->ssl, ret);
   const char *msg = soap_code_str(h_ssl_error_codes, err);
-  if (msg)
-    strncpy(soap->msgbuf, msg, sizeof(soap->msgbuf));
-  else
+  if (msg) {
+    strncpy(soap->msgbuf, msg, sizeof(soap->msgbuf) - 1);
+    soap->msgbuf[sizeof(soap->msgbuf) - 1] = '\0';
+  } else
     return ERR_error_string(err, soap->msgbuf);
   if (ERR_peek_error()) {
     unsigned long r;
@@ -3715,10 +3729,11 @@ int SOAP_FMAC2 soap_ssl_accept(struct soap *soap) {
     }
   }
 #endif
-  if (soap->recv_timeout || soap->send_timeout)
+  if (soap->recv_timeout || soap->send_timeout) {
     SOAP_SOCKNONBLOCK(sk)
-  else
+  } else {
     SOAP_SOCKBLOCK(sk)
+  }
   soap->imode |= SOAP_ENC_SSL;
   soap->omode |= SOAP_ENC_SSL;
   return SOAP_OK;
@@ -4615,10 +4630,11 @@ again:
     return SOAP_INVALID_SOCKET;
 #endif
   }
-  if (soap->recv_timeout || soap->send_timeout)
+  if (soap->recv_timeout || soap->send_timeout) {
     SOAP_SOCKNONBLOCK(sk)
-  else
+  } else {
     SOAP_SOCKBLOCK(sk)
+  }
   return sk;
 }
 #endif
@@ -5169,10 +5185,11 @@ soap_accept(struct soap *soap) {
         }
       }
     }
-    if (soap->accept_timeout)
+    if (soap->accept_timeout) {
       SOAP_SOCKNONBLOCK(soap->master)
-    else
+    } else {
       SOAP_SOCKBLOCK(soap->master)
+    }
     soap->socket =
         soap->faccept(soap, soap->master, (struct sockaddr *)&soap->peer, &n);
     soap->peerlen = (size_t)n;
@@ -5266,10 +5283,12 @@ soap_accept(struct soap *soap) {
 #endif
       soap->keep_alive =
           (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) != 0);
-      if (soap->send_timeout || soap->recv_timeout)
+
+      if (soap->send_timeout || soap->recv_timeout) {
         SOAP_SOCKNONBLOCK(soap->socket)
-      else
+      } else {
         SOAP_SOCKBLOCK(soap->socket)
+      }
       return soap->socket;
     }
     err = soap_socket_errno(soap->socket);
@@ -6049,7 +6068,10 @@ static int http_post(struct soap *soap, const char *endpoint, const char *host,
       sprintf(soap->tmpbuf, "[%s]", host); /* RFC 2732 */
     else
 #endif
-      strncpy(soap->tmpbuf, host, sizeof(soap->tmpbuf));
+    {
+      strncpy(soap->tmpbuf, host, sizeof(soap->tmpbuf) - 1);
+      soap->tmpbuf[sizeof(soap->tmpbuf) - 1] = '\0';
+    }
   }
   if ((err = soap->fposthdr(soap, "Host", soap->tmpbuf)))
     return err;
@@ -8161,7 +8183,8 @@ void *SOAP_FMAC2 soap_id_lookup(struct soap *soap, const char *id, void **p,
                         "Resolved href='%s' type=%d location=%p (%u bytes)\n",
                         id, t, ip->ptr, (unsigned int)n));
     if (ip->type != t) {
-      strncpy(soap->id, id, sizeof(soap->id));
+      strncpy(soap->id, id, sizeof(soap->id) - 1);
+      soap->id[sizeof(soap->id) - 1] = '\0';
       soap->error = SOAP_HREF;
       DBGLOG(TEST,
              SOAP_MESSAGE(
@@ -8265,7 +8288,8 @@ void *SOAP_FMAC2 soap_id_forward(struct soap *soap, const char *href, void *p,
                                 "size=%lu level=%u got type=%d size=%lu\n",
                         href, ip->type, (unsigned long)ip->size, k, st,
                         (unsigned long)n));
-    strncpy(soap->id, href, sizeof(soap->id));
+    strncpy(soap->id, href, sizeof(soap->id) - 1);
+    soap->id[sizeof(soap->id) - 1] = '\0';
     soap->error = SOAP_HREF;
     return NULL;
   }
@@ -8357,12 +8381,14 @@ soap_id_enter(struct soap *soap, const char *id, void *p, int t, size_t n,
                                 "size=%lu level=%u got type=%d size=%lu\n",
                         id, ip->type, (unsigned long)ip->size, k, t,
                         (unsigned long)n));
-    strncpy(soap->id, id, sizeof(soap->id));
+    strncpy(soap->id, id, sizeof(soap->id) - 1);
+    soap->id[sizeof(soap->id) - 1] = '\0';
     soap->error = SOAP_HREF;
     return NULL;
   } else if (ip->ptr) {
     DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Multiply defined id='%s'\n", id));
-    strncpy(soap->id, id, sizeof(soap->id));
+    strncpy(soap->id, id, sizeof(soap->id) - 1);
+    soap->id[sizeof(soap->id) - 1] = '\0';
     soap->error = SOAP_DUPLICATE_ID;
     return NULL;
   } else {
@@ -16431,14 +16457,48 @@ int SOAP_FMAC2 soap_send_fault(struct soap *soap) {
       soap_serializefault(soap);
       soap_begin_count(soap);
       if (soap->mode & SOAP_IO_LENGTH) {
-        soap_envelope_begin_out(soap);
-        soap_putheader(soap);
-        soap_body_begin_out(soap);
-        soap_putfault(soap);
-        soap_body_end_out(soap);
-        soap_envelope_end_out(soap);
+        int retv = soap_envelope_begin_out(soap);
+        if (retv < 0) {
+          DBGLOG(
+              TEST,
+              SOAP_MESSAGE(
+                  fdebug,
+                  "soap_envelope_begin_out() failed in soap_send_fault()\n"));
+        }
+        retv = soap_putheader(soap);
+        if (retv < 0) {
+          DBGLOG(TEST,
+                 SOAP_MESSAGE(
+                     fdebug, "soap_putheader() failed in soap_send_fault()\n"));
+        }
+        retv = soap_body_begin_out(soap);
+        if (retv < 0) {
+          DBGLOG(TEST,
+                 SOAP_MESSAGE(
+                     fdebug,
+                     "soap_body_begin_out() failed in soap_send_fault()\n"));
+        }
+        retv = soap_putfault(soap);
+        if (retv < 0) {
+          DBGLOG(TEST,
+                 SOAP_MESSAGE(fdebug,
+                              "soap_putfault() failed in soap_send_fault()\n"));
+        }
+        retv = soap_body_end_out(soap);
+        if (retv < 0) {
+          DBGLOG(
+              TEST,
+              SOAP_MESSAGE(
+                  fdebug, "soap_body_end_out() failed in soap_send_fault()\n"));
+        }
+        retv = soap_envelope_end_out(soap);
+      }
+      int retv = soap_end_count(soap);
+      if (retv < 0) {
+        DBGLOG(TEST,
+               SOAP_MESSAGE(fdebug,
+                            "soap_end_count() failed in soap_send_fault()\n"));
       }
-      soap_end_count(soap);
       if (soap_response(soap, status) || soap_envelope_begin_out(soap) ||
           soap_putheader(soap) || soap_body_begin_out(soap) ||
           soap_putfault(soap) || soap_body_end_out(soap) ||
@@ -16500,7 +16560,11 @@ int SOAP_FMAC2 soap_recv_fault(struct soap *soap, int check) {
     if (!soap_body_end_in(soap))
       soap_envelope_end_in(soap);
   }
-  soap_end_recv(soap);
+  int recvsts = soap_end_recv(soap);
+  if (recvsts < 0) {
+    DBGLOG(TEST, SOAP_MESSAGE(fdebug, "soap_end_recv() failed with status %d\n",
+                              status));
+  }
   soap->error = status;
   return soap_closesock(soap);
 }
@@ -16531,9 +16595,16 @@ int SOAP_FMAC2 soap_send_empty_response(struct soap *soap, int httpstatuscode) {
 SOAP_FMAC1
 int SOAP_FMAC2 soap_recv_empty_response(struct soap *soap) {
   if (!(soap->omode & SOAP_IO_UDP)) {
-    if (!soap_begin_recv(soap))
+    if (!soap_begin_recv(soap)) {
       soap_end_recv(soap);
-    else if (soap->error == SOAP_NO_DATA || soap->error == 202)
+      int recvsts = soap_end_recv(soap);
+      if (recvsts < 0) {
+        DBGLOG(TEST,
+               SOAP_MESSAGE(
+                   fdebug,
+                   "soap_end_recv() failed in soap_recv_empty_response()\n"));
+      }
+    } else if (soap->error == SOAP_NO_DATA || soap->error == 202)
       soap->error = SOAP_OK;
   }
   return soap_closesock(soap);
diff --git a/Framework/Kernel/src/DateValidator.cpp b/Framework/Kernel/src/DateValidator.cpp
index 5362fb247e217211a577736781841c1057ccacfe..4f7eee94a2965d71a42716a384035b05ade82914 100644
--- a/Framework/Kernel/src/DateValidator.cpp
+++ b/Framework/Kernel/src/DateValidator.cpp
@@ -30,6 +30,7 @@ struct tm getTimeValue(const std::string &sDate, std::string &error) {
   timeinfo.tm_isdst = -1;
 #ifndef _WIN32
   timeinfo.tm_gmtoff = 0;
+  timeinfo.tm_zone = 0;
 #endif
 
   std::basic_string<char>::size_type index, off = 0;
diff --git a/Framework/Kernel/src/VectorHelper.cpp b/Framework/Kernel/src/VectorHelper.cpp
index 52144d225aa4f454563c018cefb3c214ad817445..8764accf4f6cab5eefa4949cb3e9d311c35507aa 100644
--- a/Framework/Kernel/src/VectorHelper.cpp
+++ b/Framework/Kernel/src/VectorHelper.cpp
@@ -533,6 +533,7 @@ void linearlyInterpolateY(const std::vector<double> &x, std::vector<double> &y,
     step++;
   }
 }
+
 namespace {
 /** internal function converted from Lambda to identify interval around
 * specified  point and  run average around this point
@@ -551,7 +552,7 @@ double runAverage(size_t index, size_t startIndex, size_t endIndex,
                   std::vector<double> const *const binBndrs) {
 
   size_t iStart, iEnd;
-  double weight0(0), weight1(0), start, end;
+  double weight0(0), weight1(0), start(0.0), end(0.0);
   //
   if (binBndrs) {
     // identify initial and final bins to
@@ -607,12 +608,21 @@ double runAverage(size_t index, size_t startIndex, size_t endIndex,
     if (iEnd != endIndex)
       avrg += input[iEnd] * weight1;
 
-    return avrg / (end - start);
+    double div = end - start;
+    if (.0 == div)
+      return 0;
+    else
+      return avrg / (end - start);
   } else {
-    return avrg / double(ic);
+    if (0 == ic) {
+      return 0;
+    } else {
+      return avrg / double(ic);
+    }
   }
 }
 }
+
 /** Basic running average of input vector within specified range, considering
 *  variable bin-boundaries if such boundaries are provided.
 * The algorithm performs trapezium integration, so some peak shift
@@ -683,11 +693,11 @@ void smoothInRange(const std::vector<double> &input,
     output[i - startIndex] =
         runAverage(i, startIndex, endIndex, halfWidth, input, binBndrs) *
         binSize;
-    if (outBins) {
+    if (outBins && binBndrs) {
       outBins->operator[](i - startIndex) = binBndrs->operator[](i);
     }
   }
-  if (outBins) {
+  if (outBins && binBndrs) {
     outBins->operator[](endIndex - startIndex) = binBndrs->operator[](endIndex);
   }
 }
diff --git a/Framework/MDAlgorithms/src/ConvertCWSDExpToMomentum.cpp b/Framework/MDAlgorithms/src/ConvertCWSDExpToMomentum.cpp
index 5bb6cc662e53abe742bfb355143983a89573ce5d..22507befa430a047f4f1cb757bc943df762b53df 100644
--- a/Framework/MDAlgorithms/src/ConvertCWSDExpToMomentum.cpp
+++ b/Framework/MDAlgorithms/src/ConvertCWSDExpToMomentum.cpp
@@ -415,6 +415,13 @@ void ConvertCWSDExpToMomentum::convertSpiceMatrixToMomentumMDEvents(
   }
   expinfo->mutableRun().setGoniometer(dataws->run().getGoniometer(), false);
   expinfo->mutableRun().addProperty("run_number", runnumber);
+  // Add all the other propertys from original data workspace
+  const std::vector<Kernel::Property *> vec_property =
+      dataws->run().getProperties();
+  for (size_t i = 0; i < vec_property.size(); ++i) {
+    expinfo->mutableRun().addProperty(vec_property[i]->clone());
+  }
+
   m_outputWS->addExperimentInfo(expinfo);
 
   return;
diff --git a/Framework/MDAlgorithms/test/CompactMDTest.h b/Framework/MDAlgorithms/test/CompactMDTest.h
index 2dc03cfe8ee693a245bdff1552c31d894a13dc68..c902a63bd606528350418ca3664b634d0314e4bd 100644
--- a/Framework/MDAlgorithms/test/CompactMDTest.h
+++ b/Framework/MDAlgorithms/test/CompactMDTest.h
@@ -34,9 +34,9 @@ public:
      * Input structure:
      *------------------
      *  -------------
-     *  |   |///|   |
-     *  -------------
-     * -3-2-1 0 1 2 3
+     *  |   |   |///|   |   |
+     *  ---------------------
+     * -5-4-3 2-1 0 1 2 3 4 5
      *---------------------------
      * Expected output structure:
      *----------------------------
@@ -51,13 +51,13 @@ public:
     const size_t numDims = 1;
     const double signal = 0.0;
     const double errorSquared = 1.3;
-    size_t numBins[static_cast<int>(numDims)] = {3};
-    Mantid::coord_t min[static_cast<int>(numDims)] = {-3};
-    Mantid::coord_t max[static_cast<int>(numDims)] = {3};
+    size_t numBins[static_cast<int>(numDims)] = {5};
+    Mantid::coord_t min[static_cast<int>(numDims)] = {-5};
+    Mantid::coord_t max[static_cast<int>(numDims)] = {5};
     const std::string name("test");
     auto inWS = MDEventsTestHelper::makeFakeMDHistoWorkspaceGeneral(
         numDims, signal, errorSquared, numBins, min, max, name);
-    inWS->setSignalAt(1, 1.0); // set middle bin signal to one
+    inWS->setSignalAt(2, 1.0); // set middle bin signal to one
     CompactMD alg;
     alg.setChild(true);
     alg.setRethrows(true);
@@ -258,17 +258,22 @@ public:
     const size_t numDims = 4;
     const double signal = 0.0;
     const double errorSquared = 1.2;
-    size_t numBins[static_cast<int>(numDims)] = {3, 3, 3, 3};
-    Mantid::coord_t min[static_cast<int>(numDims)] = {-3, -3, -3, -3};
-    Mantid::coord_t max[static_cast<int>(numDims)] = {3, 3, 3, 3};
+    size_t numBins[static_cast<int>(numDims)] = {10, 20, 10, 20};
+    Mantid::coord_t min[static_cast<int>(numDims)] = {-5, -10, -5, -10};
+    Mantid::coord_t max[static_cast<int>(numDims)] = {5, 10, 5, 10};
     const std::string name("test");
     m_ws = MDEventsTestHelper::makeFakeMDHistoWorkspaceGeneral(
         numDims, signal, errorSquared, numBins, min, max, name);
+    // setting signals like this for variety
+    auto iter = m_ws->createIterator();
+    do {
+      auto index = iter->getLinearIndex();
+      if (index % 2 == 0) {
+        m_ws->setSignalAt(index, 1.0);
+      }
+    } while (iter->next());
   }
   void test_execute_4d() {
-    m_ws->setSignalAt(0, 1.0);
-    m_ws->setSignalAt(5, 1.2);
-    m_ws->setSignalAt(1, 2.3);
     CompactMD alg;
     alg.setChild(true);
     alg.setRethrows(true);
diff --git a/Framework/Properties/Mantid.properties.template b/Framework/Properties/Mantid.properties.template
index 27e669d1d7ff7c2297397b120797a006c97aa4b6..9b160ba84bb9860cdd4b2237dc08e7576198f65b 100644
--- a/Framework/Properties/Mantid.properties.template
+++ b/Framework/Properties/Mantid.properties.template
@@ -16,7 +16,7 @@ default.facility = ISIS
 default.instrument =
 
 # Set of PyQt interfaces to add to the Interfaces menu, separated by a space.  Interfaces are seperated from their respective categories by a "/".
-mantidqt.python_interfaces = Direct/DGS_Reduction.py Direct/DGSPlanner.py SANS/ORNL_SANS.py Reflectometry/REFL_Reduction.py Reflectometry/REFL_SF_Calculator.py Reflectometry/REFM_Reduction.py Utility/TofConverter.py Reflectometry/ISIS_Reflectometry.py Diffraction/Powder_Diffraction_Reduction.py Utility/FilterEvents.py Diffraction/HFIR_Powder_Diffraction_Reduction.py
+mantidqt.python_interfaces = Direct/DGS_Reduction.py Direct/DGSPlanner.py SANS/ORNL_SANS.py Reflectometry/REFL_Reduction.py Reflectometry/REFL_SF_Calculator.py Reflectometry/REFM_Reduction.py Utility/TofConverter.py Reflectometry/ISIS_Reflectometry.py Diffraction/Powder_Diffraction_Reduction.py Utility/FilterEvents.py Diffraction/HFIR_Powder_Diffraction_Reduction.py Diffraction/HFIR_4Circle_Reduction.py
 
 mantidqt.python_interfaces_directory = @MANTID_ROOT@/scripts
 
diff --git a/Framework/PythonInterface/plugins/algorithms/ComputeCalibrationCoefVan.py b/Framework/PythonInterface/plugins/algorithms/ComputeCalibrationCoefVan.py
new file mode 100644
index 0000000000000000000000000000000000000000..a6964b3768e7acd5a4056f52cbfb721c8c95ef06
--- /dev/null
+++ b/Framework/PythonInterface/plugins/algorithms/ComputeCalibrationCoefVan.py
@@ -0,0 +1,168 @@
+from mantid.api import PythonAlgorithm, AlgorithmFactory, MatrixWorkspaceProperty, Progress, InstrumentValidator
+from mantid.kernel import Direction
+import numpy as np
+from scipy import integrate
+import scipy as sp
+import mlzutils
+
+
+class ComputeCalibrationCoefVan(PythonAlgorithm):
+    """ Calculate coefficients to normalize by Vanadium and correct Debye Waller factor
+    """
+    def __init__(self):
+        """
+        Init
+        """
+        PythonAlgorithm.__init__(self)
+        self.vanaws = None
+        self.defaultT = 293.0       # K, default temperature if not given
+        self.Mvan = 50.942          # [g/mol], Vanadium molar mass
+        self.DebyeT = 389.0         # K, Debye temperature for Vanadium
+
+    def category(self):
+        """ Return category
+        """
+        return "PythonAlgorithms;CorrectionFunctions\\EfficiencyCorrections"
+
+    def name(self):
+        """ Return summary
+        """
+        return "ComputeCalibrationCoefVan"
+
+    def summary(self):
+        return "Calculate coefficients for detector efficiency correction using the Vanadium data."
+
+    def PyInit(self):
+        """ Declare properties
+        """
+        self.declareProperty(MatrixWorkspaceProperty("VanadiumWorkspace", "", direction=Direction.Input,
+                                                     validator=InstrumentValidator()),
+                             "Input Vanadium workspace")
+        self.declareProperty(MatrixWorkspaceProperty("OutputWorkspace", "", direction=Direction.Output),
+                             "Name the workspace that will contain the calibration coefficients")
+        return
+
+    def validateInputs(self):
+        issues = dict()
+        inws = self.getProperty("VanadiumWorkspace").value
+        run = inws.getRun()
+
+        if not run.hasProperty('wavelength'):
+            issues['VanadiumWorkspace'] = "Input workspace must have wavelength sample log."
+        else:
+            try:
+                float(run.getProperty('wavelength').value)
+            except ValueError:
+                issues['VanadiumWorkspace'] = "Invalid value for wavelength sample log. Wavelength must be a number."
+
+        return issues
+
+    def get_temperature(self):
+        """
+        tries to get temperature from the sample logs
+        in the case of fail, default value is returned
+        """
+        run = self.vanaws.getRun()
+        if not run.hasProperty('temperature'):
+            self.log().warning("Temperature sample log is not present in " + self.vanaws.getName() +
+                               " T=293K is assumed for Debye-Waller factor.")
+            return self.defaultT
+        try:
+            temperature = float(run.getProperty('temperature').value)
+        except ValueError, err:
+            self.log().warning("Error of getting temperature: " + err +
+                               " T=293K is assumed for Debye-Waller factor.")
+            return self.defaultT
+
+        return temperature
+
+    def PyExec(self):
+        """ Main execution body
+        """
+        self.vanaws = self.getProperty("VanadiumWorkspace").value       # returns workspace instance
+        outws_name = self.getPropertyValue("OutputWorkspace")           # returns workspace name (string)
+        nhist = self.vanaws.getNumberHistograms()
+        prog_reporter = Progress(self, start=0.0, end=1.0, nreports=nhist+1)
+
+        # calculate array of Debye-Waller factors
+        dwf = self.calculate_dwf()
+
+        # for each detector: fit gaussian to get peak_centre and fwhm
+        # sum data in the range [peak_centre - 3*fwhm, peak_centre + 3*fwhm]
+        dataX = self.vanaws.readX(0)
+        coefY = np.zeros(nhist)
+        coefE = np.zeros(nhist)
+        instrument = self.vanaws.getInstrument()
+        detID_offset = self.get_detID_offset()
+        for idx in range(nhist):
+            prog_reporter.report("Setting %dth spectrum" % idx)
+            dataY = self.vanaws.readY(idx)
+            det = instrument.getDetector(idx + detID_offset)
+            if np.max(dataY) == 0 or det.isMasked():
+                coefY[idx] = 0.
+                coefE[idx] = 0.
+            else:
+                dataE = self.vanaws.readE(idx)
+                peak_centre, sigma = mlzutils.do_fit_gaussian(self.vanaws, idx, self.log())
+                fwhm = sigma*2.*np.sqrt(2.*np.log(2.))
+                idxmin = (np.fabs(dataX-peak_centre+3.*fwhm)).argmin()
+                idxmax = (np.fabs(dataX-peak_centre-3.*fwhm)).argmin()
+                coefY[idx] = dwf[idx]*sum(dataY[idxmin:idxmax+1])
+                coefE[idx] = dwf[idx]*sum(dataE[idxmin:idxmax+1])
+
+        # create X array, X data are the same for all detectors, so
+        coefX = np.zeros(nhist)
+        coefX.fill(dataX[0])
+
+        create = self.createChildAlgorithm("CreateWorkspace")
+        create.setPropertyValue('OutputWorkspace', outws_name)
+        create.setProperty('ParentWorkspace', self.vanaws)
+        create.setProperty('DataX', coefX)
+        create.setProperty('DataY', coefY)
+        create.setProperty('DataE', coefE)
+        create.setProperty('NSpec', nhist)
+        create.setProperty('UnitX', 'TOF')
+        create.execute()
+        outws = create.getProperty('OutputWorkspace').value
+
+        self.setProperty("OutputWorkspace", outws)
+
+    def get_detID_offset(self):
+        """
+        returns ID of the first detector
+        """
+        return self.vanaws.getSpectrum(0).getDetectorIDs()[0]
+
+    def calculate_dwf(self):
+        """
+        Calculates Debye-Waller factor according to
+        Sears and Shelley Acta Cryst. A 47, 441 (1991)
+        """
+        run = self.vanaws.getRun()
+        nhist = self.vanaws.getNumberHistograms()
+        thetasort = np.zeros(nhist)  # theta in radians, not 2Theta
+
+        instrument = self.vanaws.getInstrument()
+        detID_offset = self.get_detID_offset()
+
+        for i in range(nhist):
+            det = instrument.getDetector(i + detID_offset)
+            thetasort[i] = 0.5*np.sign(np.cos(det.getPhi()))*self.vanaws.detectorTwoTheta(det)
+            # thetasort[i] = 0.5*self.vanaws.detectorSignedTwoTheta(det) # gives opposite sign for detectors 0-24
+
+        temperature = self.get_temperature()                    # T in K
+        wlength = float(run.getLogData('wavelength').value)     # Wavelength, Angstrom
+        mass_vana = 0.001*self.Mvan/sp.constants.N_A            # Vanadium mass, kg
+        temp_ratio = temperature/self.DebyeT
+
+        if temp_ratio < 1.e-3:
+            integral = 0.5
+        else:
+            integral = integrate.quad(lambda x: x/sp.tanh(0.5*x/temp_ratio), 0, 1)[0]
+
+        msd = 3.*sp.constants.hbar**2/(2.*mass_vana*sp.constants.k * self.DebyeT)*integral*1.e20
+        return np.exp(-msd*(4.*sp.pi*sp.sin(thetasort)/wlength)**2)
+
+
+# Register algorithm with Mantid.
+AlgorithmFactory.subscribe(ComputeCalibrationCoefVan)
diff --git a/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/DetectorFloodWeighting.py b/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/DetectorFloodWeighting.py
index ffe6574e3e1326047cfee48cf811b073889f061c..32bb98f27c6a938069e1ccb3c01af95a91ac9472 100644
--- a/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/DetectorFloodWeighting.py
+++ b/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/DetectorFloodWeighting.py
@@ -86,14 +86,14 @@ class DetectorFloodWeighting(DataProcessorAlgorithm):
         divide.setProperty("RHSWorkspace", rhs)
         divide.execute()
         return divide.getProperty("OutputWorkspace").value
-        
+
     def _add(self, lhs, rhs):
         divide = self.createChildAlgorithm("Plus")
         divide.setProperty("LHSWorkspace", lhs)
         divide.setProperty("RHSWorkspace", rhs)
         divide.execute()
         return divide.getProperty("OutputWorkspace").value
-        
+
     def _integrate_bands(self, bands, in_ws):
         # Formulate bands, integrate and sum
         accumulated_output = None
diff --git a/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/EVSDiffractionReduction.py b/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/EVSDiffractionReduction.py
index 7fc7669b87706f09e5faec5f0b8e607dcb950867..69a0a5485cf1d5ce2e9d537260f2e60f09e913d5 100644
--- a/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/EVSDiffractionReduction.py
+++ b/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/EVSDiffractionReduction.py
@@ -1,3 +1,4 @@
+#pylint: disable=no-init
 from mantid.simpleapi import *
 from mantid.api import *
 from mantid.kernel import *
diff --git a/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/ResNorm2.py b/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/ResNorm2.py
index 960820fb8a070abd43f2ce9f20876c8f4d51428d..461f44dfac4040837f72c838ae4e1d8c4fd1a4a2 100644
--- a/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/ResNorm2.py
+++ b/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/ResNorm2.py
@@ -55,8 +55,8 @@ class ResNorm(PythonAlgorithm):
                                                     direction=Direction.Output),
                              doc='Fitted parameter output')
 
-        self.declareProperty(ITableWorkspaceProperty('OutputWorkspaceTable', '', 
-                                                     optional=PropertyMode.Optional, 
+        self.declareProperty(ITableWorkspaceProperty('OutputWorkspaceTable', '',
+                                                     optional=PropertyMode.Optional,
                                                      direction=Direction.Output),
                              doc='Table workspace of fit parameters')
 
diff --git a/Framework/PythonInterface/plugins/algorithms/mlzutils.py b/Framework/PythonInterface/plugins/algorithms/mlzutils.py
index 3b69302522b7ef2cd6d2eba41c946e3e548d5673..d0e47dbdc7891c084a714360e66ae6daf3b60f81 100644
--- a/Framework/PythonInterface/plugins/algorithms/mlzutils.py
+++ b/Framework/PythonInterface/plugins/algorithms/mlzutils.py
@@ -1,4 +1,6 @@
 import mantid.simpleapi as api
+from mantid.api import AlgorithmManager
+import numpy as np
 
 
 def cleanup(wslist):
@@ -154,3 +156,69 @@ def compare_mandatory(wslist, plist, logger, tolerance=0.01):
                 "Workspaces: " + ", ".join(wslist) + "\n Values: " + str(properties)
             logger.error(message)
             raise RuntimeError(message)
+
+
+def do_fit_gaussian(workspace, index, logger):
+    """
+    Calculates guess values on peak centre, sigma and peak height.
+    Uses them as an input to run a fit algorithm
+        @ param workspace --- input workspace
+        @ param index --- the spectrum with which WorkspaceIndex to fit
+        @ returns peak_centre --- fitted peak centre
+        @ returns sigma --- fitted sigma
+    """
+    nhist = workspace.getNumberHistograms()
+    if index > nhist:
+        message = "Index " + str(index) + " is out of range for the workspace " + workspace.getName()
+        logger.error(message)
+        raise RuntimeError(message)
+
+    x_values = np.array(workspace.readX(index))
+    y_values = np.array(workspace.readY(index))
+
+    # get peak centre position
+    imax = np.argmax(y_values)
+    height = y_values[imax]
+
+    # check for zero or negative signal
+    if height <= 0:
+        logger.warning("Workspace %s, detector %d has maximum <= 0" % (workspace.getName(), index))
+        return [0, 0]
+
+    try_centre = x_values[imax]
+
+    # guess sigma
+    indices = np.argwhere(y_values > 0.5*height)
+    nentries = len(indices)
+    if nentries < 3:
+        message = "Spectrum " + str(index) + " in workspace " + workspace.getName() +\
+            " has too narrow peak. Cannot guess sigma. Check your data."
+        logger.error(message)
+        raise RuntimeError(message)
+    # fwhm = sigma * (2.*np.sqrt(2.*np.log(2.)))
+    fwhm = np.fabs(x_values[indices[nentries - 1, 0]] - x_values[indices[0, 0]])
+    sigma = fwhm/(2.*np.sqrt(2.*np.log(2.)))
+
+    # create and execute Fit algorithm
+    myfunc = 'name=Gaussian, Height='+str(height)+', PeakCentre='+str(try_centre)+', Sigma='+str(sigma)
+    startX = try_centre - 3.0*fwhm
+    endX = try_centre + 3.0*fwhm
+    prefix = "Fit" + workspace.getName() + str(index)
+    fit_alg = AlgorithmManager.createUnmanaged('Fit')
+    fit_alg.initialize()
+    fit_alg.setChild(True)
+    api.set_properties(fit_alg, Function=myfunc, InputWorkspace=workspace, CreateOutput=True, Output=prefix)
+    fit_alg.setProperty('StartX', startX)
+    fit_alg.setProperty('EndX', endX)
+    fit_alg.setProperty('WorkspaceIndex', index)
+    fit_successful = fit_alg.execute()
+    param_table = fit_alg.getProperty('OutputParameters').value
+
+    if not fit_successful:
+        message = "For detector " + str(index) + " in workspace " + workspace.getName() +\
+            "fit was not successful. Input guess parameters are " + str(myfunc)
+        logger.error(message)
+        raise RuntimeError(message)
+
+    # return list: [peak_centre, sigma]
+    return param_table.column(1)[1:3]
diff --git a/Framework/PythonInterface/test/python/plugins/algorithms/CMakeLists.txt b/Framework/PythonInterface/test/python/plugins/algorithms/CMakeLists.txt
index 06aefc104046e72c2151ed57d7933b8230e6daec..952bb617bfa603aaaedee0c7393bf6f8a7ad9af5 100644
--- a/Framework/PythonInterface/test/python/plugins/algorithms/CMakeLists.txt
+++ b/Framework/PythonInterface/test/python/plugins/algorithms/CMakeLists.txt
@@ -8,6 +8,7 @@ set ( TEST_PY_FILES
   CalculateSampleTransmissionTest.py
   CheckForSampleLogsTest.py
   ConjoinSpectraTest.py
+  ComputeCalibrationCoefVanTest.py
   CorrectLogTimesTest.py
   CreateLeBailFitInputTest.py
   CreateMDTest.py
diff --git a/Framework/PythonInterface/test/python/plugins/algorithms/ComputeCalibrationCoefVanTest.py b/Framework/PythonInterface/test/python/plugins/algorithms/ComputeCalibrationCoefVanTest.py
new file mode 100644
index 0000000000000000000000000000000000000000..aff74c2e324ac2e288cce0a16a55727b9000f691
--- /dev/null
+++ b/Framework/PythonInterface/test/python/plugins/algorithms/ComputeCalibrationCoefVanTest.py
@@ -0,0 +1,82 @@
+import unittest
+from mantid.simpleapi import DeleteWorkspace, CreateSampleWorkspace, AddSampleLog, EditInstrumentGeometry,\
+    CloneWorkspace, CheckWorkspacesMatch
+from testhelpers import run_algorithm
+from mantid.api import AnalysisDataService
+from scipy.constants import N_A, hbar, k
+import numpy as np
+
+
+class ComputeCalibrationCoefVanTest(unittest.TestCase):
+    def setUp(self):
+        input_ws = CreateSampleWorkspace(Function="User Defined",
+                                         UserDefinedFunction="name=LinearBackground, A0=0.3;name=Gaussian, \
+                                         PeakCentre=5, Height=10, Sigma=0.3", NumBanks=2, BankPixelWidth=1,
+                                         XMin=0, XMax=10, BinWidth=0.1, BankDistanceFromSample=4.0)
+        self._input_ws = input_ws
+        AddSampleLog(self._input_ws, LogName='wavelength', LogText='4.0', LogType='Number', LogUnit='Angstrom')
+
+    def test_output(self):
+        outputWorkspaceName = "output_ws"
+        alg_test = run_algorithm("ComputeCalibrationCoefVan", VanadiumWorkspace=self._input_ws,
+                                 OutputWorkspace=outputWorkspaceName)
+        self.assertTrue(alg_test.isExecuted())
+        wsoutput = AnalysisDataService.retrieve(outputWorkspaceName)
+
+        # Output = Vanadium ws
+        self.assertEqual(wsoutput.getRun().getLogData('run_title').value,
+                         self._input_ws.getRun().getLogData('run_title').value)
+
+        # Size of output workspace
+        self.assertEqual(wsoutput.getNumberHistograms(), self._input_ws.getNumberHistograms())
+
+        DeleteWorkspace(wsoutput)
+        return
+
+    def test_sum(self):
+        outputWorkspaceName = "output_ws"
+        alg_test = run_algorithm("ComputeCalibrationCoefVan", VanadiumWorkspace=self._input_ws,
+                                 OutputWorkspace=outputWorkspaceName)
+        self.assertTrue(alg_test.isExecuted())
+        wsoutput = AnalysisDataService.retrieve(outputWorkspaceName)
+
+        # check whether sum is calculated correctly, for theta=0, dwf=1
+        y_sum = sum(self._input_ws.readY(0)[27:75])
+        self.assertAlmostEqual(y_sum, wsoutput.readY(0)[0])
+
+        DeleteWorkspace(wsoutput)
+
+    def test_dwf(self):
+        outputWorkspaceName = "output_ws"
+
+        # change theta to make dwf != 1
+        EditInstrumentGeometry(self._input_ws, L2="4,8", Polar="0,15", Azimuthal="0,0", DetectorIDs="1,2")
+        alg_test = run_algorithm("ComputeCalibrationCoefVan", VanadiumWorkspace=self._input_ws,
+                                 OutputWorkspace=outputWorkspaceName)
+        self.assertTrue(alg_test.isExecuted())
+        wsoutput = AnalysisDataService.retrieve(outputWorkspaceName)
+
+        # check dwf calculation
+        y_sum = sum(self._input_ws.readY(1)[27:75])
+        mvan = 0.001*50.942/N_A
+        Bcoef = 4.736767162094296*1e+20*hbar*hbar/(2.0*mvan*k*389.0)
+        dwf = np.exp(-1.0*Bcoef*(4.0*np.pi*np.sin(0.5*np.radians(15.0))/4.0)**2)
+        self.assertAlmostEqual(y_sum*dwf, wsoutput.readY(1)[0])
+
+        DeleteWorkspace(wsoutput)
+
+    def test_input_not_modified(self):
+        backup = CloneWorkspace(self._input_ws)
+        outputWorkspaceName = "output_ws"
+        alg_test = run_algorithm("ComputeCalibrationCoefVan", VanadiumWorkspace=self._input_ws,
+                                 OutputWorkspace=outputWorkspaceName)
+        self.assertTrue(alg_test.isExecuted())
+        self.assertEqual("Success!", CheckWorkspacesMatch(backup, self._input_ws))
+        DeleteWorkspace(backup)
+
+    def tearDown(self):
+        if AnalysisDataService.doesExist(self._input_ws.getName()):
+            DeleteWorkspace(self._input_ws)
+
+if __name__ == "__main__":
+    unittest.main()
diff --git a/Framework/WorkflowAlgorithms/inc/MantidWorkflowAlgorithms/MuonCalculateAsymmetry.h b/Framework/WorkflowAlgorithms/inc/MantidWorkflowAlgorithms/MuonCalculateAsymmetry.h
index 70f448d5433155eb5d1fd7ca0cb2d466a832e7bb..0d8c35783d1c54ea3aad93fc4231da183b59000b 100644
--- a/Framework/WorkflowAlgorithms/inc/MantidWorkflowAlgorithms/MuonCalculateAsymmetry.h
+++ b/Framework/WorkflowAlgorithms/inc/MantidWorkflowAlgorithms/MuonCalculateAsymmetry.h
@@ -49,12 +49,22 @@ private:
   void init();
   void exec();
 
-  /// Converts given workspace according to the OutputType
-  API::MatrixWorkspace_sptr convertWorkspace(API::MatrixWorkspace_sptr ws);
-
-  /// Merges two period workspaces according to PeriodOperation specified
-  API::MatrixWorkspace_sptr mergePeriods(API::MatrixWorkspace_sptr ws1,
-                                         API::MatrixWorkspace_sptr ws2);
+  // Calculates raw counts
+  API::MatrixWorkspace_sptr
+  calculateGroupCounts(const API::MatrixWorkspace_sptr &firstPeriodWS,
+                       const API::MatrixWorkspace_sptr &secondPeriodWS,
+                       int groupIndex, std::string op);
+  // Calculates asymmetry for specified spectrum
+  API::MatrixWorkspace_sptr
+  calculateGroupAsymmetry(const API::MatrixWorkspace_sptr &firstPeriodWS,
+                          const API::MatrixWorkspace_sptr &secondPeriodWS,
+                          int groupIndex, std::string op);
+  // Calculates asymmetry for a pair of spectra
+  API::MatrixWorkspace_sptr
+  calculatePairAsymmetry(const API::MatrixWorkspace_sptr &firstPeriodWS,
+                         const API::MatrixWorkspace_sptr &secondPeriodWS,
+                         int firstPairIndex, int secondPairIndex, double alpha,
+                         std::string op);
 };
 
 } // namespace WorkflowAlgorithms
diff --git a/Framework/WorkflowAlgorithms/src/MuonCalculateAsymmetry.cpp b/Framework/WorkflowAlgorithms/src/MuonCalculateAsymmetry.cpp
index ee9504bc04cea99fe906da51ab70484da81c0b83..0b5ee591080593aa78fc74fd76f7b8b71f7ed1d1 100644
--- a/Framework/WorkflowAlgorithms/src/MuonCalculateAsymmetry.cpp
+++ b/Framework/WorkflowAlgorithms/src/MuonCalculateAsymmetry.cpp
@@ -107,125 +107,286 @@ void MuonCalculateAsymmetry::exec() {
   MatrixWorkspace_sptr firstPeriodWS = getProperty("FirstPeriodWorkspace");
   MatrixWorkspace_sptr secondPeriodWS = getProperty("SecondPeriodWorkspace");
 
-  MatrixWorkspace_sptr convertedWS;
+  // The type of calculation
+  const std::string type = getPropertyValue("OutputType");
 
-  if (secondPeriodWS) {
-    // Two periods
-    MatrixWorkspace_sptr mergedWS = mergePeriods(firstPeriodWS, secondPeriodWS);
-    convertedWS = convertWorkspace(mergedWS);
+  // The group index
+  int groupIndex = getProperty("GroupIndex");
+
+  // The type of period operation (+ or -)
+  std::string op = getProperty("PeriodOperation");
+
+  if (type == "GroupCounts") {
+
+    auto outWS =
+        calculateGroupCounts(firstPeriodWS, secondPeriodWS, groupIndex, op);
+
+    setProperty("OutputWorkspace", outWS);
+
+  } else if (type == "GroupAsymmetry") {
+
+    auto outWS =
+        calculateGroupAsymmetry(firstPeriodWS, secondPeriodWS, groupIndex, op);
+
+    setProperty("OutputWorkspace", outWS);
+
+  } else if (type == "PairAsymmetry") {
+
+    int pairFirstIndex = getProperty("PairFirstIndex");
+    int pairSecondIndex = getProperty("PairSecondIndex");
+    double alpha = getProperty("Alpha");
+
+    auto outWS =
+        calculatePairAsymmetry(firstPeriodWS, secondPeriodWS, pairFirstIndex,
+                               pairSecondIndex, alpha, op);
+
+    setProperty("OutputWorkspace", outWS);
 
   } else {
-    // Single period only
-    convertedWS = convertWorkspace(firstPeriodWS);
-  }
 
-  setProperty("OutputWorkspace", convertedWS);
+    throw std::invalid_argument("Specified OutputType is not supported");
+  }
 }
 
 /**
- * Converts given workspace according to the OutputType.
- * @param ws :: Workspace to convert
- * @return Converted workspace
- */
-MatrixWorkspace_sptr
-MuonCalculateAsymmetry::convertWorkspace(MatrixWorkspace_sptr ws) {
-  const std::string type = getPropertyValue("OutputType");
+* Calculates raw counts according to period operation
+* @param firstPeriodWS :: [input] First period workspace
+* @param secondPeriodWS :: [input] Second period workspace
+* @param groupIndex :: [input] Index of the workspace to extract counts from
+* @param op :: [input] Period operation (+ or -)
+*/
+MatrixWorkspace_sptr MuonCalculateAsymmetry::calculateGroupCounts(
+    const MatrixWorkspace_sptr &firstPeriodWS,
+    const MatrixWorkspace_sptr &secondPeriodWS, int groupIndex,
+    std::string op) {
 
-  if (type == "GroupCounts" || type == "GroupAsymmetry") {
-    int groupIndex = getProperty("GroupIndex");
+  if (secondPeriodWS) {
+    // Two periods supplied
 
-    if (groupIndex == EMPTY_INT())
-      throw std::runtime_error("GroupIndex is not specified");
+    MatrixWorkspace_sptr tempWS;
 
-    // Yank out the counts of requested group
-    IAlgorithm_sptr alg = createChildAlgorithm("ExtractSingleSpectrum");
-    alg->initialize();
-    alg->setProperty("InputWorkspace", ws);
-    alg->setProperty("WorkspaceIndex", groupIndex);
-    alg->execute();
+    if (op == "+") {
 
-    MatrixWorkspace_sptr outWS = alg->getProperty("OutputWorkspace");
+      IAlgorithm_sptr alg = createChildAlgorithm("Plus");
+      alg->initialize();
+      alg->setProperty("LHSWorkspace", firstPeriodWS);
+      alg->setProperty("RHSWorkspace", secondPeriodWS);
+      alg->execute();
+      tempWS = alg->getProperty("OutputWorkspace");
 
-    if (type == "GroupAsymmetry") {
-      // GroupAsymmetry - counts with ExpDecay removed and normalized
+    } else if (op == "-") {
 
-      IAlgorithm_sptr alg = createChildAlgorithm("RemoveExpDecay");
+      IAlgorithm_sptr alg = createChildAlgorithm("Minus");
       alg->initialize();
-      alg->setProperty("InputWorkspace", outWS);
+      alg->setProperty("LHSWorkspace", firstPeriodWS);
+      alg->setProperty("RHSWorkspace", secondPeriodWS);
       alg->execute();
-
-      outWS = alg->getProperty("OutputWorkspace");
+      tempWS = alg->getProperty("OutputWorkspace");
     }
 
-    return outWS;
-  } else if (type == "PairAsymmetry") {
-    // PairAsymmetry - result of AsymmetryCalc algorithm
-
-    int pairFirstIndex = getProperty("PairFirstIndex");
-    int pairSecondIndex = getProperty("PairSecondIndex");
-
-    if (pairFirstIndex == EMPTY_INT() || pairSecondIndex == EMPTY_INT())
-      throw std::invalid_argument("Both pair indices should be specified");
-
-    double alpha = getProperty("Alpha");
+    IAlgorithm_sptr alg = createChildAlgorithm("ExtractSingleSpectrum");
+    alg->initialize();
+    alg->setProperty("InputWorkspace", tempWS);
+    alg->setProperty("WorkspaceIndex", groupIndex);
+    alg->execute();
+    MatrixWorkspace_sptr outWS = alg->getProperty("OutputWorkspace");
 
-    // We get pair groups as their workspace indices, but AsymmetryCalc wants
-    // spectra numbers,
-    // so need to convert
-    specid_t spectraNo1 = ws->getSpectrum(pairFirstIndex)->getSpectrumNo();
-    specid_t spectraNo2 = ws->getSpectrum(pairSecondIndex)->getSpectrumNo();
+    return outWS;
 
-    if (spectraNo1 == -1 || spectraNo2 == -1 || spectraNo1 == spectraNo2)
-      throw std::invalid_argument(
-          "Spectra numbers of the input workspace are not set properly");
+  } else {
+    // Only one period supplied
 
-    IAlgorithm_sptr alg = createChildAlgorithm("AsymmetryCalc");
-    alg->setProperty("InputWorkspace", ws);
-    // As strings, cause otherwise would need to create arrays with single
-    // elements
-    alg->setPropertyValue("ForwardSpectra",
-                          boost::lexical_cast<std::string>(spectraNo1));
-    alg->setPropertyValue("BackwardSpectra",
-                          boost::lexical_cast<std::string>(spectraNo2));
-    alg->setProperty("Alpha", alpha);
+    IAlgorithm_sptr alg = createChildAlgorithm("ExtractSingleSpectrum");
+    alg->initialize();
+    alg->setProperty("InputWorkspace", firstPeriodWS);
+    alg->setProperty("WorkspaceIndex", groupIndex);
     alg->execute();
-
     MatrixWorkspace_sptr outWS = alg->getProperty("OutputWorkspace");
 
     return outWS;
   }
-
-  throw std::invalid_argument("Specified OutputType is not supported");
 }
 
 /**
- * Merges two period workspaces according to PeriodOperation specified.
- * @param ws1 :: First period workspace
- * @param ws2 :: Second period workspace
- * @return Merged workspace
- */
-MatrixWorkspace_sptr
-MuonCalculateAsymmetry::mergePeriods(MatrixWorkspace_sptr ws1,
-                                     MatrixWorkspace_sptr ws2) {
-  std::string op = getProperty("PeriodOperation");
+* Calculates single-spectrum asymmetry according to period operation
+* @param firstPeriodWS :: [input] First period workspace
+* @param secondPeriodWS :: [input] Second period workspace
+* @param groupIndex :: [input] Workspace index for which to calculate asymmetry
+* @param op :: [input] Period operation (+ or -)
+*/
+MatrixWorkspace_sptr MuonCalculateAsymmetry::calculateGroupAsymmetry(
+    const MatrixWorkspace_sptr &firstPeriodWS,
+    const MatrixWorkspace_sptr &secondPeriodWS, int groupIndex,
+    std::string op) {
+
+  // The output workspace
+  MatrixWorkspace_sptr tempWS;
+
+  if (secondPeriodWS) {
+    // Two period workspaces where supplied
+
+    if (op == "+") {
 
-  std::string algorithmName;
+      // Sum
+      IAlgorithm_sptr alg = createChildAlgorithm("Plus");
+      alg->initialize();
+      alg->setProperty("LHSWorkspace", firstPeriodWS);
+      alg->setProperty("RHSWorkspace", secondPeriodWS);
+      alg->execute();
+      MatrixWorkspace_sptr sumWS = alg->getProperty("OutputWorkspace");
+
+      // GroupIndex as vector
+      // Necessary if we want RemoveExpDecay to fit only the requested
+      // spectrum
+      std::vector<int> spec(1, groupIndex);
+
+      // Remove decay
+      IAlgorithm_sptr asym = createChildAlgorithm("RemoveExpDecay");
+      asym->setProperty("InputWorkspace", sumWS);
+      asym->setProperty("Spectra", spec);
+      asym->execute();
+      tempWS = asym->getProperty("OutputWorkspace");
+
+    } else if (op == "-") {
+
+      // GroupIndex as vector
+      std::vector<int> spec(1, groupIndex);
+
+      // Remove decay (first period ws)
+      IAlgorithm_sptr asym = createChildAlgorithm("RemoveExpDecay");
+      asym->initialize();
+      asym->setProperty("InputWorkspace", firstPeriodWS);
+      asym->setProperty("Spectra", spec);
+      asym->execute();
+      MatrixWorkspace_sptr asymFirstPeriod =
+          asym->getProperty("OutputWorkspace");
+
+      // Remove decay (second period ws)
+      asym = createChildAlgorithm("RemoveExpDecay");
+      asym->initialize();
+      asym->setProperty("InputWorkspace", secondPeriodWS);
+      asym->setProperty("Spectra", spec);
+      asym->execute();
+      MatrixWorkspace_sptr asymSecondPeriod =
+          asym->getProperty("OutputWorkspace");
+
+      // Now subtract
+      IAlgorithm_sptr alg = createChildAlgorithm("Minus");
+      alg->initialize();
+      alg->setProperty("LHSWorkspace", asymFirstPeriod);
+      alg->setProperty("RHSWorkspace", asymSecondPeriod);
+      alg->execute();
+      tempWS = alg->getProperty("OutputWorkspace");
+    }
+  } else {
+    // Only one period was supplied
 
-  if (op == "+") {
-    algorithmName = "Plus";
-  } else if (op == "-") {
-    algorithmName = "Minus";
+    IAlgorithm_sptr alg = createChildAlgorithm("RemoveExpDecay");
+    alg->initialize();
+    alg->setProperty("InputWorkspace", firstPeriodWS);
+    alg->execute();
+    tempWS = alg->getProperty("OutputWorkspace");
   }
 
-  IAlgorithm_sptr alg = createChildAlgorithm(algorithmName);
+  // Extract the requested spectrum
+  IAlgorithm_sptr alg = createChildAlgorithm("ExtractSingleSpectrum");
   alg->initialize();
-  alg->setProperty("LHSWorkspace", ws1);
-  alg->setProperty("RHSWorkspace", ws2);
+  alg->setProperty("InputWorkspace", tempWS);
+  alg->setProperty("WorkspaceIndex", groupIndex);
   alg->execute();
-
   MatrixWorkspace_sptr outWS = alg->getProperty("OutputWorkspace");
-
   return outWS;
 }
+
+/**
+* Calculates pair asymmetry according to period operation
+* @param firstPeriodWS :: [input] First period workspace
+* @param secondPeriodWS :: [input] Second period workspace
+* @param firstPairIndex :: [input] Workspace index for the forward group
+* @param secondPairIndex :: [input] Workspace index for the backward group
+* @param alpha :: [input] The balance parameter
+* @param op :: [input] Period operation (+ or -)
+*/
+MatrixWorkspace_sptr MuonCalculateAsymmetry::calculatePairAsymmetry(
+    const MatrixWorkspace_sptr &firstPeriodWS,
+    const MatrixWorkspace_sptr &secondPeriodWS, int firstPairIndex,
+    int secondPairIndex, double alpha, std::string op) {
+
+  // Pair indices as vectors
+  std::vector<int> fwd(1, firstPairIndex + 1);
+  std::vector<int> bwd(1, secondPairIndex + 1);
+
+  if (secondPeriodWS) {
+
+    MatrixWorkspace_sptr outWS;
+
+    if (op == "+") {
+
+      // Sum
+      IAlgorithm_sptr alg = createChildAlgorithm("Plus");
+      alg->initialize();
+      alg->setProperty("LHSWorkspace", firstPeriodWS);
+      alg->setProperty("RHSWorkspace", secondPeriodWS);
+      alg->execute();
+      MatrixWorkspace_sptr sumWS = alg->getProperty("OutputWorkspace");
+
+      // Asymmetry calculation
+      alg = createChildAlgorithm("AsymmetryCalc");
+      alg->setProperty("InputWorkspace", sumWS);
+      alg->setProperty("ForwardSpectra", fwd);
+      alg->setProperty("BackwardSpectra", bwd);
+      alg->setProperty("Alpha", alpha);
+      alg->execute();
+      outWS = alg->getProperty("OutputWorkspace");
+
+    } else if (op == "-") {
+
+      std::vector<int> fwd(1, firstPairIndex + 1);
+      std::vector<int> bwd(1, secondPairIndex + 1);
+
+      // First period asymmetry
+      IAlgorithm_sptr alg = createChildAlgorithm("AsymmetryCalc");
+      alg->setProperty("InputWorkspace", firstPeriodWS);
+      alg->setProperty("ForwardSpectra", fwd);
+      alg->setProperty("BackwardSpectra", bwd);
+      alg->setProperty("Alpha", alpha);
+      alg->execute();
+      MatrixWorkspace_sptr asymFirstPeriod =
+          alg->getProperty("OutputWorkspace");
+
+      // Second period asymmetry
+      alg = createChildAlgorithm("AsymmetryCalc");
+      alg->setProperty("InputWorkspace", secondPeriodWS);
+      alg->setProperty("ForwardSpectra", fwd);
+      alg->setProperty("BackwardSpectra", bwd);
+      alg->setProperty("Alpha", alpha);
+      alg->execute();
+      MatrixWorkspace_sptr asymSecondPeriod =
+          alg->getProperty("OutputWorkspace");
+
+      // Now subtract
+      alg = createChildAlgorithm("Minus");
+      alg->initialize();
+      alg->setProperty("LHSWorkspace", asymFirstPeriod);
+      alg->setProperty("RHSWorkspace", asymSecondPeriod);
+      alg->execute();
+      outWS = alg->getProperty("OutputWorkspace");
+    }
+
+    return outWS;
+
+  } else {
+
+    IAlgorithm_sptr alg = createChildAlgorithm("AsymmetryCalc");
+    alg->setProperty("InputWorkspace", firstPeriodWS);
+    alg->setProperty("ForwardSpectra", fwd);
+    alg->setProperty("BackwardSpectra", bwd);
+    alg->setProperty("Alpha", alpha);
+    alg->execute();
+    MatrixWorkspace_sptr outWS = alg->getProperty("OutputWorkspace");
+
+    return outWS;
+  }
+}
 } // namespace WorkflowAlgorithms
 } // namespace Mantid
diff --git a/Framework/WorkflowAlgorithms/src/RefReduction.cpp b/Framework/WorkflowAlgorithms/src/RefReduction.cpp
index 9cc5678a2d2df87113a607c4a9ac52bc0976f26b..5a85b6b69186405fdeae7e31bee928b7e11f1dd3 100644
--- a/Framework/WorkflowAlgorithms/src/RefReduction.cpp
+++ b/Framework/WorkflowAlgorithms/src/RefReduction.cpp
@@ -612,16 +612,35 @@ double RefReduction::calculateAngleREFM(MatrixWorkspace_sptr workspace) {
   double dangle = getProperty("DetectorAngle");
   if (isEmpty(dangle)) {
     Mantid::Kernel::Property *prop = workspace->run().getProperty("DANGLE");
+    if (!prop) {
+      throw std::runtime_error("DetectorAngle property not given as input, and "
+                               "could not find the log entry DANGLE either");
+    }
     Mantid::Kernel::TimeSeriesProperty<double> *dp =
         dynamic_cast<Mantid::Kernel::TimeSeriesProperty<double> *>(prop);
+    if (!dp) {
+      throw std::runtime_error(
+          "The log entry DANGLE could not"
+          "be interpreted as a property of type time series of double");
+    }
     dangle = dp->getStatistics().mean;
   }
 
   double dangle0 = getProperty("DetectorAngle0");
   if (isEmpty(dangle0)) {
     Mantid::Kernel::Property *prop = workspace->run().getProperty("DANGLE0");
+    if (!prop) {
+      throw std::runtime_error("DetectorAngle0 property not given aas input, "
+                               "and could not find the log entry DANGLE0 "
+                               "either");
+    }
     Mantid::Kernel::TimeSeriesProperty<double> *dp =
         dynamic_cast<Mantid::Kernel::TimeSeriesProperty<double> *>(prop);
+    if (!dp) {
+      throw std::runtime_error(
+          "The log entry DANGLE0 could not "
+          "be interpreted as a property of type time series of double values");
+    }
     dangle0 = dp->getStatistics().mean;
   }
 
diff --git a/Framework/WorkflowAlgorithms/test/MuonCalculateAsymmetryTest.h b/Framework/WorkflowAlgorithms/test/MuonCalculateAsymmetryTest.h
index 0d2038ad16f5aca37a804114647c0c3dfd1a2e9e..8b19f4693fb2f5ab6e98d44afdd88dafa5c84f35 100644
--- a/Framework/WorkflowAlgorithms/test/MuonCalculateAsymmetryTest.h
+++ b/Framework/WorkflowAlgorithms/test/MuonCalculateAsymmetryTest.h
@@ -171,7 +171,7 @@ public:
     AnalysisDataService::Instance().remove(outWSName);
   }
 
-  void test_groupAsymmetry() {
+  void test_groupAsymmetry_singlePeriod() {
     // Name of the output workspace.
     const std::string outWSName = outputWorkspaceName("GroupAsymmetry");
 
@@ -213,7 +213,96 @@ public:
     AnalysisDataService::Instance().remove(outWSName);
   }
 
-  void test_pairAsymmetry() {
+  void test_groupAsymmetry_twoPeriods_minus() {
+    // Name of the output workspace.
+    const std::string outWSName = outputWorkspaceName("GroupAsymmetry");
+
+    MatrixWorkspace_sptr inWS = createWorkspace(3);
+    MatrixWorkspace_sptr inWSSecond = createWorkspace();
+
+    MuonCalculateAsymmetry alg;
+    alg.initialize();
+    alg.setProperty("FirstPeriodWorkspace", inWS);
+    alg.setProperty("SecondPeriodWorkspace", inWSSecond);
+    alg.setProperty("PeriodOperation", "-");
+    alg.setProperty("OutputType", "GroupAsymmetry");
+    alg.setProperty("GroupIndex", 2);
+    alg.setPropertyValue("OutputWorkspace", outWSName);
+    TS_ASSERT_THROWS_NOTHING(alg.execute(););
+    TS_ASSERT(alg.isExecuted());
+
+    // Retrieve the workspace from data service.
+    auto ws =
+        AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(outWSName);
+    TS_ASSERT(ws);
+
+    if (ws) {
+      TS_ASSERT_EQUALS(ws->getNumberHistograms(), 1);
+      TS_ASSERT_EQUALS(ws->blocksize(), 3);
+
+      TS_ASSERT_EQUALS(ws->readX(0)[0], 1);
+      TS_ASSERT_EQUALS(ws->readX(0)[1], 2);
+      TS_ASSERT_EQUALS(ws->readX(0)[2], 3);
+
+      TS_ASSERT_DELTA(ws->readY(0)[0], 0.0030, 0.0001);
+      TS_ASSERT_DELTA(ws->readY(0)[1], -0.0455, 0.0001);
+      TS_ASSERT_DELTA(ws->readY(0)[2], -0.1511, 0.0001);
+
+      TS_ASSERT_DELTA(ws->readE(0)[0], 0.1066, 0.0001);
+      TS_ASSERT_DELTA(ws->readE(0)[1], 0.1885, 0.0001);
+      TS_ASSERT_DELTA(ws->readE(0)[2], 0.3295, 0.0001);
+    }
+
+    // Remove workspace from the data service.
+    AnalysisDataService::Instance().remove(outWSName);
+  }
+
+  void test_groupAsymmetry_twoPeriods_plus() {
+
+    // Name of the output workspace.
+    const std::string outWSName = outputWorkspaceName("GroupAsymmetry");
+
+    MatrixWorkspace_sptr inWS = createWorkspace(3);
+    MatrixWorkspace_sptr inWSSecond = createWorkspace();
+
+    MuonCalculateAsymmetry alg;
+    alg.initialize();
+    alg.setProperty("FirstPeriodWorkspace", inWS);
+    alg.setProperty("SecondPeriodWorkspace", inWSSecond);
+    alg.setProperty("PeriodOperation", "+");
+    alg.setProperty("OutputType", "GroupAsymmetry");
+    alg.setProperty("GroupIndex", 1);
+    alg.setPropertyValue("OutputWorkspace", outWSName);
+    TS_ASSERT_THROWS_NOTHING(alg.execute(););
+    TS_ASSERT(alg.isExecuted());
+
+    // Retrieve the workspace from data service.
+    auto ws =
+        AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(outWSName);
+    TS_ASSERT(ws);
+
+    if (ws) {
+      TS_ASSERT_EQUALS(ws->getNumberHistograms(), 1);
+      TS_ASSERT_EQUALS(ws->blocksize(), 3);
+
+      TS_ASSERT_EQUALS(ws->readX(0)[0], 1);
+      TS_ASSERT_EQUALS(ws->readX(0)[1], 2);
+      TS_ASSERT_EQUALS(ws->readX(0)[2], 3);
+
+      TS_ASSERT_DELTA(ws->readY(0)[0], -0.2529, 0.0001);
+      TS_ASSERT_DELTA(ws->readY(0)[1], 0.3918, 0.0001);
+      TS_ASSERT_DELTA(ws->readY(0)[2], 1.5316, 0.0001);
+
+      TS_ASSERT_DELTA(ws->readE(0)[0], 0.0547, 0.0001);
+      TS_ASSERT_DELTA(ws->readE(0)[1], 0.1010, 0.0001);
+      TS_ASSERT_DELTA(ws->readE(0)[2], 0.1825, 0.0001);
+    }
+
+    // Remove workspace from the data service.
+    AnalysisDataService::Instance().remove(outWSName);
+  }
+
+  void test_pairAsymmetry_singlePeriod() {
     // Name of the output workspace.
     const std::string outWSName = outputWorkspaceName("GroupAsymmetry");
 
@@ -257,6 +346,98 @@ public:
     AnalysisDataService::Instance().remove(outWSName);
   }
 
+  void test_pairAsymmetry_twoPeriods_minus() {
+    // Name of the output workspace.
+    const std::string outWSName = outputWorkspaceName("GroupAsymmetry");
+
+    MatrixWorkspace_sptr inWS = createWorkspace(3);
+    MatrixWorkspace_sptr inWSSecond = createWorkspace();
+
+    MuonCalculateAsymmetry alg;
+    alg.initialize();
+    alg.setProperty("FirstPeriodWorkspace", inWS);
+    alg.setProperty("SecondPeriodWorkspace", inWSSecond);
+    alg.setProperty("PeriodOperation", "-");
+    alg.setProperty("OutputType", "PairAsymmetry");
+    alg.setProperty("PeriodOperation", "-");
+    alg.setProperty("PairFirstIndex", 2);
+    alg.setProperty("PairSecondIndex", 0);
+    alg.setPropertyValue("OutputWorkspace", outWSName);
+    TS_ASSERT_THROWS_NOTHING(alg.execute());
+    TS_ASSERT(alg.isExecuted());
+
+    // Retrieve the workspace from data service.
+    auto ws =
+        AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(outWSName);
+    TS_ASSERT(ws);
+
+    if (ws) {
+      TS_ASSERT_EQUALS(ws->getNumberHistograms(), 1);
+      TS_ASSERT_EQUALS(ws->blocksize(), 3);
+
+      TS_ASSERT_DELTA(ws->readY(0)[0], -0.3214, 0.0001);
+      TS_ASSERT_DELTA(ws->readY(0)[1], -0.2250, 0.0001);
+      TS_ASSERT_DELTA(ws->readY(0)[2], -0.1666, 0.0001);
+
+      TS_ASSERT_EQUALS(ws->readX(0)[0], 1.5);
+      TS_ASSERT_EQUALS(ws->readX(0)[1], 2.5);
+      TS_ASSERT_EQUALS(ws->readX(0)[2], 3);
+
+      TS_ASSERT_DELTA(ws->readE(0)[0], 0.5290, 0.001);
+      TS_ASSERT_DELTA(ws->readE(0)[1], 0.4552, 0.001);
+      TS_ASSERT_DELTA(ws->readE(0)[2], 0.4073, 0.001);
+    }
+
+    // Remove workspace from the data service.
+    AnalysisDataService::Instance().remove(outWSName);
+  }
+
+  void test_pairAsymmetry_twoPeriods_plus() {
+
+    // Name of the output workspace.
+    const std::string outWSName = outputWorkspaceName("GroupAsymmetry");
+
+    MatrixWorkspace_sptr inWS = createWorkspace(3);
+    MatrixWorkspace_sptr inWSSecond = createWorkspace();
+
+    MuonCalculateAsymmetry alg;
+    alg.initialize();
+    alg.setProperty("FirstPeriodWorkspace", inWS);
+    alg.setProperty("SecondPeriodWorkspace", inWSSecond);
+    alg.setProperty("PeriodOperation", "+");
+    alg.setProperty("OutputType", "PairAsymmetry");
+    alg.setProperty("PairFirstIndex", 0);
+    alg.setProperty("PairSecondIndex", 2);
+    alg.setPropertyValue("OutputWorkspace", outWSName);
+    TS_ASSERT_THROWS_NOTHING(alg.execute(););
+    TS_ASSERT(alg.isExecuted());
+
+    // Retrieve the workspace from data service.
+    auto ws =
+        AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(outWSName);
+    TS_ASSERT(ws);
+
+    if (ws) {
+      TS_ASSERT_EQUALS(ws->getNumberHistograms(), 1);
+      TS_ASSERT_EQUALS(ws->blocksize(), 3);
+
+      TS_ASSERT_EQUALS(ws->readX(0)[0], 1.5);
+      TS_ASSERT_EQUALS(ws->readX(0)[1], 2.5);
+      TS_ASSERT_EQUALS(ws->readX(0)[2], 3);
+
+      TS_ASSERT_DELTA(ws->readY(0)[0], -0.5454, 0.0001);
+      TS_ASSERT_DELTA(ws->readY(0)[1], -0.4615, 0.0001);
+      TS_ASSERT_DELTA(ws->readY(0)[2], -0.4000, 0.0001);
+
+      TS_ASSERT_DELTA(ws->readE(0)[0], 0.2428, 0.0001);
+      TS_ASSERT_DELTA(ws->readE(0)[1], 0.2159, 0.0001);
+      TS_ASSERT_DELTA(ws->readE(0)[2], 0.1966, 0.0001);
+    }
+
+    // Remove workspace from the data service.
+    AnalysisDataService::Instance().remove(outWSName);
+  }
+
 private:
   std::string outputWorkspaceName(std::string testName) {
     return "MuonCalculateAsymmetryTest_" + testName + "_OutputWS";
diff --git a/MantidPlot/src/Graph.cpp b/MantidPlot/src/Graph.cpp
index b90d59c0c2ba39d003eb0589957f4663b3ab805e..2fbfe1977b7b92b4614dbd36e78c743f457c99d5 100644
--- a/MantidPlot/src/Graph.cpp
+++ b/MantidPlot/src/Graph.cpp
@@ -1290,7 +1290,7 @@ void Graph::linColor()
   notifyChanges();
 }
 
-void Graph::setAxisScale(int axis, double start, double end, int type, double step,
+void Graph::setAxisScale(int axis, double start, double end, int scaleType, double step,
     int majorTicks, int minorTicks)
 {
   ScaleEngine *sc_engine = dynamic_cast<ScaleEngine *>(d_plot->axisScaleEngine(axis));
@@ -1300,19 +1300,30 @@ void Graph::setAxisScale(int axis, double start, double end, int type, double st
   ScaleTransformation::Type old_type = sc_engine->type();
 
   // If not specified, keep the same as now
-  if( type < 0 ) type = axisType(axis);
+  if( scaleType < 0 ) scaleType = axisType(axis);
 
-  if (type != old_type)
+  int type = ScaleTransformation::Linear;
+  // just to have the one-by-one ScaleType => GraphOptions; higher values of ScaleType
+  // will be GraphOptions::Linear
+  if (ScaleDraw::ScaleType::Numeric == scaleType) {
+    type = ScaleTransformation::Linear;
+  } else if (ScaleDraw::ScaleType::Text == scaleType) {
+    type = ScaleTransformation::Log10;
+  } else if (ScaleDraw::ScaleType::Day == scaleType) {
+    type = ScaleTransformation::Power;
+  }
+
+  if (static_cast<int>(type) != static_cast<int>(old_type))
   {
     // recalculate boundingRect of MantidCurves
-    emit axisScaleChanged(axis,type == ScaleTransformation::Log10);
+    emit axisScaleChanged(axis, type == ScaleTransformation::Log10);
   }
 
-  if (type == GraphOptions::Log10)
+  if (type == ScaleTransformation::Log10)
   {
     sc_engine->setType(ScaleTransformation::Log10);
   }
-  else if (type == GraphOptions::Power)
+  else if (type == ScaleTransformation::Power)
   {
     sc_engine->setType(ScaleTransformation::Power);
   }
@@ -1321,7 +1332,7 @@ void Graph::setAxisScale(int axis, double start, double end, int type, double st
     sc_engine->setType(ScaleTransformation::Linear);
   }
 
-  if (type == GraphOptions::Log10)
+  if (type == ScaleTransformation::Log10)
   {
     if (start <= 0)
     {
@@ -1368,7 +1379,7 @@ void Graph::setAxisScale(int axis, double start, double end, int type, double st
     // log scales can't represent zero or negative values, 1e-10 is a low number that I hope will be lower than most of the data but is still sensible for many color plots
     //start = start < 1e-90 ? 1e-10 : start;
   }
-  else if (type == GraphOptions::Power)
+  else if (type == ScaleTransformation::Power)
   {
     double const nth_power = sc_engine->nthPower();
     if (start <= 0 && nth_power < 0)
@@ -1440,8 +1451,7 @@ void Graph::setAxisScale(int axis, double start, double end, int type, double st
           QwtScaleWidget *rightAxis = d_plot->axisWidget(QwtPlot::yRight);
           if(rightAxis)
           {
-            //if (type == ScaleTransformation::Log10 && (start <= 0 || start == DBL_MAX))
-            if (type == GraphOptions::Log10 && (start <= 0 || start == DBL_MAX))
+            if (type == ScaleTransformation::Log10 && (start <= 0 || start == DBL_MAX))
             {
               start = sp->getMinPositiveValue();
             }
diff --git a/MantidPlot/src/Graph.h b/MantidPlot/src/Graph.h
index 34ae08f03ca7eacf89224cf0b37a0bffcc81b19d..0b3cdbecd8d2eec45c4f3cb4d9bfe6af4b2101f2 100644
--- a/MantidPlot/src/Graph.h
+++ b/MantidPlot/src/Graph.h
@@ -385,7 +385,7 @@ public slots:
   void setScale(QwtPlot::Axis axis, QString logOrLin);
   double axisStep(int axis){return d_user_step[axis];};
   //! Set the axis scale
-  void setAxisScale(int axis, double start, double end, int type = -1, double step = 0.0,
+  void setAxisScale(int axis, double start, double end, int scaleType = -1, double step = 0.0,
                     int majorTicks = 5, int minorTicks = 5);
   
 	/// in plot windows change both axis to log-log
diff --git a/MantidPlot/src/ImportASCIIDialog.cpp b/MantidPlot/src/ImportASCIIDialog.cpp
index 075910ef35fb89d929af75626a20ae8a6845b781..f8b10566e93fa4cb43a9ed5ad25385d6a984380c 100644
--- a/MantidPlot/src/ImportASCIIDialog.cpp
+++ b/MantidPlot/src/ImportASCIIDialog.cpp
@@ -464,7 +464,7 @@ void ImportASCIIDialog::previewTable()
 
   int importMode = d_import_mode->currentIndex();
   if (importMode == NewTables) {
-    importMode = (ImportASCIIDialog::ImportMode)Table::Overwrite;
+    importMode = ImportASCIIDialog::NewWorkspace; //(ImportASCIIDialog::ImportMode)Table::Overwrite;
   } else {
     importMode -= 2;
   }
@@ -494,7 +494,7 @@ void ImportASCIIDialog::previewMatrix() {
 
   int importMode = d_import_mode->currentIndex();
   if (importMode == NewMatrices) {
-    importMode = (ImportASCIIDialog::ImportMode)Matrix::Overwrite;
+    importMode = ImportASCIIDialog::NewWorkspace; //(ImportASCIIDialog::ImportMode)Matrix::Overwrite;
   } else {
     // Overwrite-2 => NewColumns (in both Matrix::importMode and
     // ImportASCIIDialog::importMode)
diff --git a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/QtReflMainView.h b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/QtReflMainView.h
index ab2f48dfa2db8daac520f43ab82517c3a5325e67..e57514b3b0750f06dbcc794cdfd578ea1efc4e4c 100644
--- a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/QtReflMainView.h
+++ b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/QtReflMainView.h
@@ -95,6 +95,7 @@ public:
   virtual std::string getSearchString() const;
 
   virtual boost::shared_ptr<IReflPresenter> getPresenter() const;
+
 private:
   // initialise the interface
   virtual void initLayout();
@@ -143,7 +144,7 @@ private slots:
   void showSearchContextMenu(const QPoint &pos);
 };
 
-} // namespace CustomInterfaces
 } // namespace Mantid
+} // namespace CustomInterfaces
 
 #endif /* MANTID_CUSTOMINTERFACES_QTREFLMAINVIEW_H_ */
diff --git a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/ReflMainView.h b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/ReflMainView.h
index bfcca663b78dc95a9e99974146d2ec1d066007fb..a60b2df5525e7d4ef0a35effba9220db034e6313 100644
--- a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/ReflMainView.h
+++ b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/ReflMainView.h
@@ -59,6 +59,10 @@ namespace MantidQt
       virtual void showAlgorithmDialog(const std::string& algorithm) = 0;
       virtual std::string requestNotebookPath() = 0;
 
+      //Settings
+      virtual void saveSettings(const std::map<std::string,QVariant>& options) = 0;
+      virtual void loadSettings(std::map<std::string,QVariant>& options) = 0;
+
       //Plotting
       virtual void plotWorkspaces(const std::set<std::string>& workspaces) = 0;
 
diff --git a/MantidQt/CustomInterfaces/src/Indirect/ConvFit.cpp b/MantidQt/CustomInterfaces/src/Indirect/ConvFit.cpp
index 07fef6447c8a24678b514740f03f64a9664d855f..e38a224bff1f2b19cf1dbf3c3bad6b7a724deb5e 100644
--- a/MantidQt/CustomInterfaces/src/Indirect/ConvFit.cpp
+++ b/MantidQt/CustomInterfaces/src/Indirect/ConvFit.cpp
@@ -28,7 +28,8 @@ namespace IDA {
 
 ConvFit::ConvFit(QWidget *parent)
     : IndirectDataAnalysisTab(parent), m_stringManager(NULL), m_cfTree(NULL),
-      m_fixedProps(), m_cfInputWS(), m_cfInputWSName(), m_confitResFileType() {
+      m_fixedProps(), m_cfInputWS(), m_cfInputWSName(), m_confitResFileType(),
+      m_runMin(-1), m_runMax(-1) {
   m_uiForm.setupUi(parent);
 }
 
@@ -996,7 +997,7 @@ void ConvFit::updatePlot() {
       return;
     if ((specNo - m_runMin) >= 0) {
       MatrixWorkspace_sptr ws = boost::dynamic_pointer_cast<MatrixWorkspace>(
-		  outputGroup->getItem(specNo- m_runMin));
+          outputGroup->getItem(specNo - m_runMin));
       if (ws) {
         m_uiForm.ppPlot->addSpectrum("Fit", ws, 1, Qt::red);
         m_uiForm.ppPlot->addSpectrum("Diff", ws, 2, Qt::blue);
@@ -1102,8 +1103,7 @@ void ConvFit::singleFit() {
       runPythonCode(
           QString(
               "from IndirectCommon import getWSprefix\nprint getWSprefix('") +
-          m_cfInputWSName + QString("')\n"))
-          .trimmed();
+          m_cfInputWSName + QString("')\n")).trimmed();
   m_singleFitOutputName +=
       QString("conv_") + fitType + bgType + m_uiForm.spPlotSpectrum->text();
   int maxIterations =
diff --git a/MantidQt/CustomInterfaces/src/QtReflMainView.cpp b/MantidQt/CustomInterfaces/src/QtReflMainView.cpp
index f3632eaf125e82c4d98e20af56f2a998ad70bcea..2723cd05a2779d7712ba4611ec522047e81dda1a 100644
--- a/MantidQt/CustomInterfaces/src/QtReflMainView.cpp
+++ b/MantidQt/CustomInterfaces/src/QtReflMainView.cpp
@@ -8,6 +8,12 @@
 #include <qinputdialog.h>
 #include <qmessagebox.h>
 
+
+namespace
+{
+  const QString ReflSettingsGroup = "Mantid/CustomInterfaces/ISISReflectometry";
+}
+
 namespace MantidQt
 {
   namespace CustomInterfaces
@@ -450,6 +456,33 @@ namespace MantidQt
       return qfilename.toStdString();
     }
 
+    /**
+     Save settings
+     @param options : map of user options to save
+     */
+    void QtReflMainView::saveSettings(const std::map<std::string,QVariant>& options)
+    {
+      QSettings settings;
+      settings.beginGroup(ReflSettingsGroup);
+      for(auto it = options.begin(); it != options.end(); ++it)
+        settings.setValue(QString::fromStdString(it->first), it->second);
+      settings.endGroup();
+    }
+
+    /**
+     Load settings
+     @param options : map of user options to load into
+     */
+    void QtReflMainView::loadSettings(std::map<std::string,QVariant>& options)
+    {
+      QSettings settings;
+      settings.beginGroup(ReflSettingsGroup);
+      QStringList keys = settings.childKeys();
+      for(auto it = keys.begin(); it != keys.end(); ++it)
+        options[it->toStdString()] = settings.value(*it);
+      settings.endGroup();
+    }
+
     /**
     Plot a workspace
     */
diff --git a/MantidQt/CustomInterfaces/src/ReflMainViewPresenter.cpp b/MantidQt/CustomInterfaces/src/ReflMainViewPresenter.cpp
index 2aedd280cf80054880642b336291837ffc642aa8..9323fb9b10cc1e91839a520a0f17ac3b65a302f9 100644
--- a/MantidQt/CustomInterfaces/src/ReflMainViewPresenter.cpp
+++ b/MantidQt/CustomInterfaces/src/ReflMainViewPresenter.cpp
@@ -24,9 +24,6 @@
 #include <fstream>
 #include <sstream>
 
-#include <QSettings>
-#include <QFileDialog>
-
 
 using namespace Mantid::API;
 using namespace Mantid::Geometry;
@@ -36,7 +33,6 @@ using namespace MantidQt::MantidWidgets;
 
 namespace
 {
-  const QString ReflSettingsGroup = "Mantid/CustomInterfaces/ISISReflectometry";
 
   void validateModel(ITableWorkspace_sptr model)
   {
@@ -1511,11 +1507,7 @@ namespace MantidQt
         m_options[it->first] = it->second;
 
       //Save any changes to disk
-      QSettings settings;
-      settings.beginGroup(ReflSettingsGroup);
-      for(auto it = m_options.begin(); it != m_options.end(); ++it)
-        settings.setValue(QString::fromStdString(it->first), it->second);
-      settings.endGroup();
+      m_view->saveSettings(m_options);
     }
 
     /** Load options from disk if possible, or set to defaults */
@@ -1537,12 +1529,7 @@ namespace MantidQt
       m_options["RoundDQQPrecision"] = 3;
 
       //Load saved values from disk
-      QSettings settings;
-      settings.beginGroup(ReflSettingsGroup);
-      QStringList keys = settings.childKeys();
-      for(auto it = keys.begin(); it != keys.end(); ++it)
-        m_options[it->toStdString()] = settings.value(*it);
-      settings.endGroup();
+      m_view->loadSettings(m_options);
     }
   }
 }
diff --git a/MantidQt/CustomInterfaces/test/ReflMainViewMockObjects.h b/MantidQt/CustomInterfaces/test/ReflMainViewMockObjects.h
index 026b49d21b3e9966e32a84f26c1b3df3b72ea023..e42a5a70d0bc573e435fb47faf22d0f7b0a6a2b6 100644
--- a/MantidQt/CustomInterfaces/test/ReflMainViewMockObjects.h
+++ b/MantidQt/CustomInterfaces/test/ReflMainViewMockObjects.h
@@ -57,6 +57,8 @@ public:
   virtual void setProgress(int) {};
   virtual void setTableList(const std::set<std::string>&) {};
   virtual void setInstrumentList(const std::vector<std::string>&, const std::string&) {};
+  virtual void saveSettings(const std::map<std::string,QVariant>&) {};
+  virtual void loadSettings(std::map<std::string,QVariant>&) {};
   virtual std::string getProcessInstrument() const {return "FAKE";}
   virtual boost::shared_ptr<IReflPresenter> getPresenter() const {return boost::shared_ptr<IReflPresenter>();}
 };
diff --git a/MantidQt/Python/mantidqt.sip b/MantidQt/Python/mantidqt.sip
index 47824677bf3e1bcd8e3a02a951fbbfa38afd5ad5..8278d788941a600a84f1dd6cc448d1fde138bc8f 100644
--- a/MantidQt/Python/mantidqt.sip
+++ b/MantidQt/Python/mantidqt.sip
@@ -1171,9 +1171,9 @@ void SliceViewer::setRebinNumBins(int xBins, int yBins)
 
 %End
 
-  void setRebinMode(bool mode, bool locked)   throw (std::runtime_error);
+  void setRebinMode(bool mode)   throw (std::runtime_error);
 %Docstring
-void SliceViewer::setRebinMode(bool mode, bool locked)
+void SliceViewer::setRebinMode(bool mode)
 ------------------------------------------------------
     Sets the SliceViewer in dynamic rebin mode.
     In this mode, the current view area (see setXYLimits()) is used as the
@@ -1183,8 +1183,6 @@ void SliceViewer::setRebinMode(bool mode, bool locked)
 
     Args:
         mode :: true for rebinning mode
-        locked :: if true, then the rebinned area is only refreshed manually
-           or when changing rebinning parameters.
 
 %End
 
diff --git a/MantidQt/SliceViewer/inc/MantidQtSliceViewer/SliceViewer.h b/MantidQt/SliceViewer/inc/MantidQtSliceViewer/SliceViewer.h
index f2eded1e2fa66061992d0583adf13527708f6afc..75014b4c584c09308350b1e6a85956cc64fa9d8a 100644
--- a/MantidQt/SliceViewer/inc/MantidQtSliceViewer/SliceViewer.h
+++ b/MantidQt/SliceViewer/inc/MantidQtSliceViewer/SliceViewer.h
@@ -117,7 +117,7 @@ public:
   /// Dynamic Rebinning-related Python bindings
   void setRebinThickness(int dim, double thickness);
   void setRebinNumBins(int xBins, int yBins);
-  void setRebinMode(bool mode, bool locked);
+  void setRebinMode(bool mode);
   void refreshRebin();
 
   /// Methods relating to peaks overlays.
@@ -188,7 +188,6 @@ public slots:
   void LineMode_toggled(bool);
   void SnapToGrid_toggled(bool);
   void RebinMode_toggled(bool);
-  void RebinLock_toggled(bool);
   void autoRebin_toggled(bool);
 
   // Dynamic rebinning
@@ -333,7 +332,7 @@ private:
 
   /// Synced menu/buttons
   MantidQt::API::SyncedCheckboxes *m_syncLineMode, *m_syncSnapToGrid,
-    *m_syncRebinMode, *m_syncRebinLock, *m_syncAutoRebin;
+    *m_syncRebinMode, *m_syncAutoRebin;
 
   /// Cached double for infinity
   double m_inf;
diff --git a/MantidQt/SliceViewer/inc/MantidQtSliceViewer/SliceViewer.ui b/MantidQt/SliceViewer/inc/MantidQtSliceViewer/SliceViewer.ui
index 9414476bc32f0f92da829ed186475e2fdcb485cb..d3b64c0df10eab853bd8fcc3abe0e5fe74e5c353 100644
--- a/MantidQt/SliceViewer/inc/MantidQtSliceViewer/SliceViewer.ui
+++ b/MantidQt/SliceViewer/inc/MantidQtSliceViewer/SliceViewer.ui
@@ -489,47 +489,6 @@
             </property>
            </widget>
           </item>
-          <item>
-           <widget class="QToolButton" name="btnRebinLock">
-            <property name="enabled">
-             <bool>false</bool>
-            </property>
-            <property name="minimumSize">
-             <size>
-              <width>45</width>
-              <height>45</height>
-             </size>
-            </property>
-            <property name="maximumSize">
-             <size>
-              <width>45</width>
-              <height>45</height>
-             </size>
-            </property>
-            <property name="toolTip">
-             <string>Lock the rebinned workspace in place (use the refresh button to refresh)</string>
-            </property>
-            <property name="text">
-             <string>...</string>
-            </property>
-            <property name="icon">
-             <iconset>
-              <normaloff>:/SliceViewer/icons/stock-lock.png</normaloff>:/SliceViewer/icons/stock-lock.png</iconset>
-            </property>
-            <property name="iconSize">
-             <size>
-              <width>32</width>
-              <height>32</height>
-             </size>
-            </property>
-            <property name="checkable">
-             <bool>true</bool>
-            </property>
-            <property name="checked">
-             <bool>true</bool>
-            </property>
-           </widget>
-          </item>
           <item>
            <spacer name="horizontalSpacer_5">
             <property name="orientation">
diff --git a/MantidQt/SliceViewer/src/SliceViewer.cpp b/MantidQt/SliceViewer/src/SliceViewer.cpp
index f251baaf4445e9f32142a3d54ea3d16ef6fe62a6..34bba3a13bc370f18250ec802dc46ad8a141908e 100644
--- a/MantidQt/SliceViewer/src/SliceViewer.cpp
+++ b/MantidQt/SliceViewer/src/SliceViewer.cpp
@@ -122,8 +122,6 @@ SliceViewer::SliceViewer(QWidget *parent)
 
   // hide unused buttons
   ui.btnZoom->hide();      // hidden for a long time
-  ui.btnRebinLock->hide(); // now replaced by auto rebin mode
-  // ui.btnClearLine->hide();  // turning off line mode now removes line
 
   // ----------- Toolbar button signals ----------------
   QObject::connect(ui.btnResetZoom, SIGNAL(clicked()), this, SLOT(resetZoom()));
@@ -379,13 +377,6 @@ void SliceViewer::initMenus() {
           SLOT(RebinMode_toggled(bool)));
   m_menuView->addAction(action);
 
-  action = new QAction(QPixmap(), "&Lock Rebinned WS", this);
-  m_syncRebinLock = new SyncedCheckboxes(action, ui.btnRebinLock, true);
-  connect(m_syncRebinLock, SIGNAL(toggled(bool)), this,
-          SLOT(RebinLock_toggled(bool)));
-  action->setVisible(false); // hide this action
-  m_menuView->addAction(action);
-
   action = new QAction(QPixmap(), "Rebin Current View", this);
   action->setShortcut(Qt::Key_R + Qt::ControlModifier);
   action->setEnabled(false);
@@ -691,7 +682,6 @@ void SliceViewer::setWorkspace(Mantid::API::IMDWorkspace_sptr ws) {
 
   // Can't use dynamic rebin mode with a MatrixWorkspace
   m_syncRebinMode->setEnabled(!matrix);
-  m_syncRebinLock->setEnabled(!matrix);
 
   // Go to no normalization by default for MatrixWorkspaces
   if (matrix)
@@ -1008,13 +998,10 @@ void SliceViewer::setRebinNumBins(int xBins, int yBins) {
  * See setRebinThickness() to adjust the thickness in other dimensions.
  *
  * @param mode :: true for rebinning mode
- * @param locked :: if true, then the rebinned area is only refreshed manually
- *        or when changing rebinning parameters.
  */
-void SliceViewer::setRebinMode(bool mode, bool locked) {
+void SliceViewer::setRebinMode(bool mode) {
   // The events associated with these controls will trigger a re-draw
   m_syncRebinMode->toggle(mode);
-  m_syncRebinLock->toggle(locked);
 }
 
 //------------------------------------------------------------------------------
@@ -1098,7 +1085,6 @@ void SliceViewer::RebinMode_toggled(bool checked) {
   for (size_t d = 0; d < m_dimWidgets.size(); d++)
     m_dimWidgets[d]->showRebinControls(checked);
   ui.btnRebinRefresh->setEnabled(checked);
-  ui.btnRebinLock->setEnabled(checked);
   m_syncAutoRebin->setEnabled(checked);
   m_actionRefreshRebin->setEnabled(checked);
   m_rebinMode = checked;
@@ -1118,17 +1104,6 @@ void SliceViewer::RebinMode_toggled(bool checked) {
   }
 }
 
-//------------------------------------------------------------------------------
-/** Slot called when locking/unlocking the dynamically rebinned
- * overlaid workspace
- * @param checked :: DO lock the workspace in place
- */
-void SliceViewer::RebinLock_toggled(bool checked) {
-  m_rebinLocked = checked;
-  // Rebin immediately
-  if (!m_rebinLocked && m_rebinMode)
-    this->rebinParamsChanged();
-}
 
 //------------------------------------------------------------------------------
 /// Slot for zooming into
diff --git a/MantidQt/SliceViewer/test/SliceViewerPythonInterfaceTest.py b/MantidQt/SliceViewer/test/SliceViewerPythonInterfaceTest.py
index f7ac61b15e55516acb33bf420257de185ef081dc..cff5c28c1d8bc20a66cc35ae89fff4f6f0cb077d 100644
--- a/MantidQt/SliceViewer/test/SliceViewerPythonInterfaceTest.py
+++ b/MantidQt/SliceViewer/test/SliceViewerPythonInterfaceTest.py
@@ -449,7 +449,7 @@ class SliceViewerPythonInterfaceTest(unittest.TestCase):
         sv.setRebinThickness(2, 1.0)
         sv.setRebinNumBins(50, 200)
         sv.refreshRebin()
-        sv.setRebinMode(True, True)
+        sv.setRebinMode(True)
         time.sleep(1)
         self.assertTrue(mtd.doesExist('uniform_rebinned'), 'Dynamically rebinned workspace was created.')
         ws = mtd['uniform_rebinned']
diff --git a/Testing/SystemTests/tests/analysis/ValidateInstrumentDefinitionFiles.py b/Testing/SystemTests/tests/analysis/ValidateInstrumentDefinitionFiles.py
index 70f51e4427d150b0679b9fa6579287cf043b1e07..299d6d5dc17f3a001ae3e1cb7aa485ce5db73da2 100644
--- a/Testing/SystemTests/tests/analysis/ValidateInstrumentDefinitionFiles.py
+++ b/Testing/SystemTests/tests/analysis/ValidateInstrumentDefinitionFiles.py
@@ -1,3 +1,4 @@
+#pylint: disable=invalid-name
 #pylint: disable=no-init
 from mantid import config
 import os
diff --git a/Testing/SystemTests/tests/analysis/reference/MuonLoad_MUSR00015192.nxs.md5 b/Testing/SystemTests/tests/analysis/reference/MuonLoad_MUSR00015192.nxs.md5
index 26060d7d5d3cf334ac8181df8c1433b7d1113530..f5e0395c9f732ac49915ea272c372dda1a7c5366 100644
--- a/Testing/SystemTests/tests/analysis/reference/MuonLoad_MUSR00015192.nxs.md5
+++ b/Testing/SystemTests/tests/analysis/reference/MuonLoad_MUSR00015192.nxs.md5
@@ -1 +1 @@
-f9f8aee9e15f495f43a9846da7adad3e
+75b425bdf72f1d82bb78e0c71a7fe2ca
diff --git a/docs/source/algorithms/ComputeCalibrationCoefVan-v1.rst b/docs/source/algorithms/ComputeCalibrationCoefVan-v1.rst
new file mode 100644
index 0000000000000000000000000000000000000000..47661c2ffe102b08e1a498d0c60dc5ee66232113
--- /dev/null
+++ b/docs/source/algorithms/ComputeCalibrationCoefVan-v1.rst
@@ -0,0 +1,83 @@
+.. algorithm::
+
+.. summary::
+
+.. alias::
+
+.. properties::
+
+Description
+-----------
+
+Algorithm creates a workspace with  detector sensitivity correction coefficients using the given Vanadium workspace. The correction coefficients are calculated as follows.
+
+1. Calculate the Debye-Waller factor according to Sears and Shelley *Acta Cryst. A* **47**, 441 (1991):
+
+   :math:`D_i = \exp\left(-B_i\cdot\frac{4\pi\sin\theta_i}{\lambda^2}\right)`
+
+   :math:`B_i = \frac{3\hbar^2\cdot 10^{20}}{2m_VkT_m}\cdot J(y)`
+
+   where :math:`J(y) = 0.5` if :math:`y < 10^{-3}`, otherwise
+
+   :math:`J(y) = \int_0^1 x\cdot\mathrm{coth}\left(\frac{x}{2y}\right)\,\mathrm{d}x`
+
+   where :math:`y=T/T_m` is the ratio of the temperature during the experiment :math:`T` to the Debye temperature :math:`T_m = 389K`, :math:`m_V` is the Vanadium atomic mass (in kg) and :math:`\theta_i` is the polar angle of the i-th detector.
+
+.. warning::
+
+    If sample log *temperature* is not present in the given Vanadium workspace or temperature is set to an invalid value, T=293K will be taken for the Debye-Waller factor calculation. Algorithm will produce warning in this case.
+
+2. Perform Gaussian fit of the data to find out the position of the peak centre and FWHM. These values are used to calculate sum :math:`S_i` as
+
+   :math:`S_i = \sum_{x = x_C - 3\,\mathrm{fwhm}}^{x_C + 3\,\mathrm{fwhm}} Y_i(x)`
+
+   where :math:`x_C` is the peak centre position and :math:`Y_i(x)` is the coresponding to :math:`x` :math:`Y` value for i-th detector.
+
+3. Finally, the correction coefficients :math:`K_i` are calculated as
+
+   :math:`K_i = D_i\times S_i`
+
+Workspace containing these correction coefficients is created as an output and can be used as a RHS workspace in :ref:`algm-Divide` to apply correction to the LHS workspace.
+
+.. note::
+    
+    If gaussian fit fails, algorithm terminates with an error message. The error message contains name of the workspace and detector number.
+
+Restrictions on the input workspace
+###################################
+
+The valid input workspace:
+
+- must have an instrument set
+- must have a *wavelength* sample log
+
+
+Usage
+-----
+
+**Example**
+
+.. testcode:: ExComputeCalibrationCoefVan
+
+    # load Vanadium data
+    wsVana = LoadMLZ(Filename='TOFTOFTestdata.nxs')
+    # calculate correction coefficients
+    wsCoefs = ComputeCalibrationCoefVan(wsVana)
+    print 'Spectrum 4 of the output workspace is filled with: ', round(wsCoefs.readY(999)[0])
+
+    # wsCoefs can be used as rhs with Divide algorithm to apply correction to the data 
+    wsCorr = wsVana/wsCoefs
+    print 'Spectrum 4 of the input workspace is filled with: ', round(wsVana.readY(999)[0], 1)
+    print 'Spectrum 4 of the corrected workspace is filled with: ', round(wsCorr.readY(999)[0], 5)
+
+Output:    
+
+.. testoutput:: ExComputeCalibrationCoefVan
+
+    Spectrum 4 of the output workspace is filled with:  6596.0
+    Spectrum 4 of the input workspace is filled with:  1.0
+    Spectrum 4 of the corrected workspace is filled with:  0.00015
+
+.. categories::
+
+.. sourcelink::
diff --git a/docs/source/algorithms/ConvertCWSDExpToMomentum-v1.rst b/docs/source/algorithms/ConvertCWSDExpToMomentum-v1.rst
index 904b8dd2a5ccd21368da10509b6c936c4aa5fe42..1d88cdd45e69e58036d500ee26a3af2f5b079de6 100644
--- a/docs/source/algorithms/ConvertCWSDExpToMomentum-v1.rst
+++ b/docs/source/algorithms/ConvertCWSDExpToMomentum-v1.rst
@@ -19,18 +19,22 @@ In this algorithm's name, ConvertCWSDToMomentum, *CW* stands for constant wave
 This algorithm takes ??? as inputs.
 
 Futhermore, the unit of the output matrix workspace can be converted to 
-momentum transfer (:math:`Q`). 
+momentum transfer (Q).
 
 
 Outline of algorithm
 ####################
 
-1. Create output workspace.
+1. Create output workspace
+
  * Build a virtual instrument, requiring  
+
    - position of source
    - position of sample
    - detector ID, position, detector size of pixels
+
 2. Read in data via table workspace
+
  * From each row, (1) file name and (2) starting detector ID are read in.  
  * Detector position in (virtual) instrument of MDEventWorkspace is compared with the position in MatrixWorkspace 
  * Momentum is calcualted by goniometry values
@@ -75,8 +79,6 @@ Each MDEvent in output MDEventWorkspace contain
 * Detector ID
 * Run Number
 
-
-
 Combine Experiment Into One MDEventWorkspace
 --------------------------------------------
 
@@ -90,7 +92,7 @@ In order to integrate them into an organized data structure, i.e., *MDEventWorks
 a virtual instrument is built in the algorithm. 
 
 Virtual instrument
-==================
+##################
 
 A virtual instrument is built in the algorithm. 
 In this virtual instrument, the number of detectors and their position are determined 
@@ -98,13 +100,13 @@ by the number of individual detector's positions in the *experiment*.
 
 
 MDEventWorkspace
-================
+################
 
 There is only one *virtual* instrument and *N* ExperimentInfo.  
 *N* is the total number of experiment points in the *experiment*. 
 
 Inconsistency between using virtual instrument and copying instrument
-=====================================================================
+#####################################################################
 
 It is found that the results, i.e., the peak's position in sample-momentum
 space, by FindPeaksMD, are different betweent the MDEventWorkspaces 
@@ -145,7 +147,7 @@ with 2D angular detector.
 Usage
 -----
 
-**Example - convert an HB3A's experiment to MDWorkspace in sample momentum workspae and creating virtual instrument.:**
+**Example - convert an HB3A's experiment to MDWorkspace in sample momentum workspae and creating virtual instrument**
 
 .. testcode:: ExConvertHB3AToMDVirtualInstrument
 
diff --git a/docs/source/algorithms/LoadEventAndCompress-v1.rst b/docs/source/algorithms/LoadEventAndCompress-v1.rst
index 904f90502164953738e1a6948991f082077e233c..62a3f3d65ff40e21572ce2ba45219dfb24bfb24a 100644
--- a/docs/source/algorithms/LoadEventAndCompress-v1.rst
+++ b/docs/source/algorithms/LoadEventAndCompress-v1.rst
@@ -41,6 +41,44 @@ download due to their size.  They can however be downloaded using these links:
    PG3_9830_event = LoadEventAndCompress(Filename='PG3_9830_event.nxs',
                                          MaxChunkSize=1.)
 
+**Example - Usage with MPI**
+
+Create a python driver script called test_mpi.py
+
+.. code-block:: python
+
+    from mantid.simpleapi import *
+    import mantid
+    if AlgorithmFactory.exists('GatherWorkspaces'):
+        HAVE_MPI = True
+        from mpi4py import MPI
+        mpiRank = MPI.COMM_WORLD.Get_rank()
+        mpiSize = MPI.COMM_WORLD.Get_size()
+    else:
+        HAVE_MPI = False
+        mpiRank = 0 # simplify if clauses
+        mpiSize = 1 # simplify if clauses
+
+    wksp = LoadEventAndCompress(Filename="PG3_2538_event.nxs")
+    print "Rank = ", mpiRank, "Number of Events = ", wksp.getNumberEvents()
+    if mpiRank == 0:
+        reduce = AlignAndFocusPowder(InputWorkspace=wksp, CalFileName='PG3_calibrate_d2538_2014_05_13.cal', Params='0.5,0.01,2')
+        SaveNexus(reduce,Filename=str(mpiSize)+"tasks.nxs")
+
+And run it using the following commands
+
+.. code-block::
+
+    $ module load mpi/openmpi-x86_64
+    $ export LD_PRELOAD=/usr/lib64/openmpi/lib/libmpi.so
+    $ mpirun -np 8 mantidpython test_mpi.py
+
+to run without mpi is simply
+
+.. code-block::
+
+    $ mantidpython test_mpi.py
+
 .. categories::
 
 .. sourcelink::
diff --git a/docs/source/algorithms/MuonCalculateAsymmetry-v1.rst b/docs/source/algorithms/MuonCalculateAsymmetry-v1.rst
index 1b977a1084e9a7272aefb2610287611cb6e22440..1bbd806a20d33affe4a25d1cc4f652faa373e3d0 100644
--- a/docs/source/algorithms/MuonCalculateAsymmetry-v1.rst
+++ b/docs/source/algorithms/MuonCalculateAsymmetry-v1.rst
@@ -57,7 +57,7 @@ Output:
 .. testcode:: ExGroupAsymmetryMultiperiod
 
    y1 = [100,50,10]
-   y2 = [ 50,25, 5]
+   y2 = [150,20,1]
    x = [1,2,3]
 
    input1 = CreateWorkspace(x, y1)
@@ -75,7 +75,7 @@ Output:
 
 .. testoutput:: ExGroupAsymmetryMultiperiod
 
-   Output: [ 0.1524242  -0.0916425  -0.71360777]
+   Output: [-0.28634067  0.60594273  0.26255546]
 
 .. categories::
 
diff --git a/docs/source/concepts/DiffractionCalibrationWorkspace.rst b/docs/source/concepts/DiffractionCalibrationWorkspace.rst
index 58ee3f066f1239d1014fabe0b5b590fe423205f9..105e6e31562877adb9521585cdb43bf2205a28ff 100644
--- a/docs/source/concepts/DiffractionCalibrationWorkspace.rst
+++ b/docs/source/concepts/DiffractionCalibrationWorkspace.rst
@@ -57,3 +57,5 @@ various parameters on an instrument view.
   * ``offset`` (double array) not used. Value of the legacy calibration file.
 
 The `group` information will still be extracted into separate `GroupingWorkspace` and `MaskWorkspace`.
+
+.. categories:: Concepts
diff --git a/docs/source/concepts/MDNorm.rst b/docs/source/concepts/MDNorm.rst
index 1a1fdf7a1e8cda9fd304ef831f7c0537bcf981d6..8f2d64ba4430c6a34de7cd74f4a404caf449b819 100644
--- a/docs/source/concepts/MDNorm.rst
+++ b/docs/source/concepts/MDNorm.rst
@@ -158,4 +158,6 @@ Current implementation
 As of release 3.3, the normalization can be calculated for single crystal 
 diffraction (:ref:`MDNormSCD <algm-MDNormSCD>`) 
 and single crystal direct geometry inelastic scattering 
-(:ref:`MDNormDirectSC <algm-MDNormDirectSC>`).    
+(:ref:`MDNormDirectSC <algm-MDNormDirectSC>`).
+
+.. categories:: Concepts
diff --git a/docs/source/concepts/Properties.rst b/docs/source/concepts/Properties.rst
index 3ea0cb965e0ad77b4b0a782ffb444d607a7fd356..71d8ab02a89f8b938f78a4585fec228801795fec 100644
--- a/docs/source/concepts/Properties.rst
+++ b/docs/source/concepts/Properties.rst
@@ -176,8 +176,7 @@ In addition to the above, if used, Workspace properties also have a
 built in validator that requires that input workspaces exist and are of
 the correct type and that output workspaces have a name set.
 
-For more details on using validators, see the
-`PropertyAlgorithm <https://github.com/mantidproject/mantid/blob/master/Code/Mantid/Framework/UserAlgorithms/PropertyAlgorithm.cpp>`__
+For more details on using validators, see the :ref:`PropertyAlgorithm <algm-PropertyAlgorithm>`
 example or the full documentation for the individual validators (linked
 above).
 
@@ -186,4 +185,4 @@ to implement the IValidator interface.
 
 
 
-.. categories:: Concepts
\ No newline at end of file
+.. categories:: Concepts
diff --git a/docs/source/interfaces/HFIR_4Circle_Reduction.rst b/docs/source/interfaces/HFIR_4Circle_Reduction.rst
new file mode 100644
index 0000000000000000000000000000000000000000..01c42636b87472ebfb13e637f5a3ceb0597b8c99
--- /dev/null
+++ b/docs/source/interfaces/HFIR_4Circle_Reduction.rst
@@ -0,0 +1,116 @@
+HFIR Single Crystal Reduction Interface
+=======================================
+
+.. contents:: Table of Contents
+  :local:
+  
+Overview
+--------
+
+HFIR single crystalreduction interface is a GUI to download, view and reduce data from 
+HFIR's four-circle single crystal diffractometer in SPICE format. 
+
+
+Introduction of Tabs
+--------------------
+
+  1. **Setup and Data Access**: Configure the instrument name, data server URL and directories.
+  
+    - Configure the instrument name;
+    - Set up and test HB3A data server's URL;
+    - Configure the directory to save raw data;
+    - Configure the directory to save working result;
+    - Download data from server;
+    
+  2. **View Raw Data**: View 2D image of counts on detector of one measurement.
+  
+    - Plot the counts of the 256 by 256 2D detector;
+    
+  3. **Calculate UB**: Calculate UB matrix.
+  
+    - Find peak in one measurement;
+    - Option to load Miller index directly from SPICE file;
+    - Calculate UB matrix;
+    - Re-index the peaks;
+    
+  4. **Merge Scan**: Merge all the measurements in a scan.
+  
+    - Merge all measuring points in a scan to an MDEventWorkspace in HKL-frame or Q-sample-frame;
+    - Allow various ways to set up UB matrix
+    
+  5. **Refine UB**: Refine UB matrix
+  
+    - Disabled becaues it is in development still;
+      
+  6. **Peak Integration**: Integrate peaks
+  
+    - Disabled because it is still in development.
+
+Use Cases
+---------
+
+Here are some use cases that can be used as examples.
+
+
+Workflow to calculate UB matrix
++++++++++++++++++++++++++++++++
+
+Here is a typical use case to calculate UB matrix
+
+ 1. User specifies *Experiment* and pushes button *Set*
+ 
+ 2. User enters tab *View Raw Data*
+
+ 3. User inputs scan number and list all the measuring points
+ 
+ 4. User views all the measurements
+
+ 5. User finds out the measurement with the strongest reflection and push button use
+
+ 6. GUI shifts to tab *Calculate UB* automatically
+
+ 7. User pushes button *Find Peak* with checking *Load HKL from file*
+
+ 8. GUI finds the peak center and load HKL
+
+ 9. User pushes button *Add peak* to add the peak to table
+
+ 10. User repeats step 2 to 9 to add other peaks
+
+ 11. User select the peaks that are linearly independent and pushes *Calcualte UB*
+
+ 12. GUI calculates UB matrix and show the result
+
+ 13. User may push *Index peak* to use the calculated UB matrix to index peaks in the table to check UB matrix.
+ 
+
+Workflow to merge measurements in scan
+++++++++++++++++++++++++++++++++++++++
+
+Here is a typical use case to merge all the measuring points (Pt.) in a scan.
+
+ 1. User specifies *Experiment* and pushes button *Set*
+ 
+ 2. User enters tab *Merge Scan*
+
+ 3. User specifies the UB matrix either by *From tab Calculate UB* or by entering the values to text editor
+
+ 4. User pushes button *Set*.
+
+ 5. User specifies the frame in which the merged data will be in. If the target frame is Q-Sample-Sapce, then there is 
+     no need to specify UB matrix;
+
+ 6. User specifies the scan numbers and push button *Add*;
+     
+ 7. User specifies the base name for the output MDEventWorkspaces;
+
+ 8. User pushes button *Process*;
+
+ 9. User goes to MantidPlot to view the merged scan by SliceView or Vates.
+
+
+
+Limitation
+----------
+
+- HFIR single crystal reduction GUI supports for instrument HB3A only from release 3.5.0 and nightly.
diff --git a/docs/sphinxext/mantiddoc/directives/algorithm.py b/docs/sphinxext/mantiddoc/directives/algorithm.py
index e01645c182f245813f77a10fedcaa153b782c8d7..9333d680eea9274d2bf3de4d7f6ed1b82a5d56f6 100644
--- a/docs/sphinxext/mantiddoc/directives/algorithm.py
+++ b/docs/sphinxext/mantiddoc/directives/algorithm.py
@@ -202,7 +202,7 @@ class AlgorithmDirective(AlgorithmBaseDirective):
 
 #------------------------------------------------------------------------------------------------------------
 
-def html_collect_pages(app):
+def html_collect_pages(dummy_app):
     """
     Write out unversioned algorithm pages that redirect to the highest version of the algorithm
     """
diff --git a/docs/sphinxext/mantiddoc/directives/properties.py b/docs/sphinxext/mantiddoc/directives/properties.py
index 0531ada285c35b0231d90c388590851163e635ad..2e14a854077bea111e82ccfd43608175a5733b77 100644
--- a/docs/sphinxext/mantiddoc/directives/properties.py
+++ b/docs/sphinxext/mantiddoc/directives/properties.py
@@ -1,3 +1,4 @@
+#pylint: disable=invalid-name
 from mantiddoc.directives.base import AlgorithmBaseDirective
 import string
 
diff --git a/docs/sphinxext/mantiddoc/directives/sourcelink.py b/docs/sphinxext/mantiddoc/directives/sourcelink.py
index f60bee49b5fc22ad5029399456c5cba1190f679b..1e436b1f71b441e1c1e965677e7e8391578d7249 100644
--- a/docs/sphinxext/mantiddoc/directives/sourcelink.py
+++ b/docs/sphinxext/mantiddoc/directives/sourcelink.py
@@ -150,7 +150,7 @@ class SourceLinkDirective(AlgorithmBaseDirective):
         builddir = os.path.join(builddir, "..", "..")
         builddir = os.path.abspath(builddir)
 
-        for dirName, subdirList, fileList in os.walk(self.source_root):
+        for dirName, dummy_subdirList, fileList in os.walk(self.source_root):
             if dirName.startswith(builddir):
                 continue # don't check or add to the cache
             for fname in fileList:
@@ -186,29 +186,31 @@ class SourceLinkDirective(AlgorithmBaseDirective):
             suggested_path = "os_agnostic_path_to_file_from_Code/Mantid"
             if len(valid_ext_list) == 0:
                 raise SourceLinkError("No file possibilities for " + file_name + " have been found\n" +
-                    "Please specify a better one using the :filename: opiton or use the " + str(self.file_types.keys()) + " options\n" +
-                    "e.g. \n" +
-                    ".. sourcelink:\n" +
-                    "      :" + self.file_types.keys()[0] + ": " + suggested_path + "\n "+
-                    "or \n" +
-                    ".. sourcelink:\n" +
-                    "      :filename: " + file_name)
+                                      "Please specify a better one using the :filename: opiton or use the " +
+                                      str(self.file_types.keys()) + " options\n" +
+                                      "e.g. \n" +
+                                      ".. sourcelink:\n" +
+                                      "      :" + self.file_types.keys()[0] + ": " + suggested_path + "\n "+
+                                      "or \n" +
+                                      ".. sourcelink:\n" +
+                                      "      :filename: " + file_name)
             #if the have a cpp we should also have a h
             if ("cpp" in valid_ext_list) or ("h" in valid_ext_list):
                 if ("cpp" not in valid_ext_list) or ("h" not in valid_ext_list):
                     raise SourceLinkError("Only one of .h and .cpp found for " + file_name + "\n" +
-                    "valid files found for " + str(valid_ext_list) + "\n" +
-                    "Please specify the missing one using an " + str(self.file_types.keys()) + " option\n" +
-                    "e.g. \n" +
-                    ".. sourcelink:\n" +
-                    "      :" + self.file_types.keys()[0] + ": " + suggested_path)
+                                          "valid files found for " + str(valid_ext_list) + "\n" +
+                                          "Please specify the missing one using an " +
+                                          str(self.file_types.keys()) + " option\n" +
+                                          "e.g. \n" +
+                                          ".. sourcelink:\n" +
+                                          "      :" + self.file_types.keys()[0] + ": " + suggested_path)
         return
 
     def output_path_to_page(self, filepath, extension):
         """
         Outputs the source link for a file to the rst page
         """
-        dirName,fName = os.path.split(filepath)
+        dummy_dirName,fName = os.path.split(filepath)
         self.add_rst(self.file_types[extension] + ": `" + fName + " <" + self.convert_path_to_github_url(filepath) + ">`_\n\n")
         return
 
diff --git a/docs/sphinxext/mantiddoc/doctest.py b/docs/sphinxext/mantiddoc/doctest.py
index e4364825320559fc06647688164ba4025b609d72..d6d176e0159c852380fc41e67e5d3993c89f0b7d 100644
--- a/docs/sphinxext/mantiddoc/doctest.py
+++ b/docs/sphinxext/mantiddoc/doctest.py
@@ -198,7 +198,7 @@ class TestCaseReport(object):
 
     @property
     def passed(self):
-        return (self.failure_descr == "")
+        return self.failure_descr == ""
 
     @property
     def failed(self):
@@ -309,7 +309,7 @@ class DocTestOutputParser(object):
                              % text[1])
         results = results[2:] # trim off top two lines of header information
         maintests, cleanup = self.__split_on_cleanup(results)
-        overall_success = not (maintests[0] == FAILURE_MARKER)
+        overall_success = not maintests[0] == FAILURE_MARKER
 
         if overall_success:
             testcases = self.__parse_success(fullname, maintests)
diff --git a/scripts/CMakeLists.txt b/scripts/CMakeLists.txt
index 7c00c508283118881ab92f0d7c8e6b079bc1f0f3..7cd45300f74869139a60cf613343c6613fe322d6 100644
--- a/scripts/CMakeLists.txt
+++ b/scripts/CMakeLists.txt
@@ -6,6 +6,7 @@ add_subdirectory(Interface/ui)
 add_subdirectory(lib1to2/gui)
 add_subdirectory(PyChop)
 add_subdirectory(TofConverter)
+add_subdirectory(HFIR_4Circle_Reduction)
 
 # Chain all required interface custom targets into CompilePyUI
 add_custom_target(CompilePyUI DEPENDS
@@ -15,6 +16,7 @@ add_custom_target(CompilePyUI DEPENDS
   CompileUITofConverter
   CompileUIUI
   CompileUILib1To2
+  CompileUIHFIR_4Circle_Reduction
 )
 
 set ( TEST_PY_FILES
diff --git a/scripts/HFIR_4Circle_Reduction.py b/scripts/HFIR_4Circle_Reduction.py
new file mode 100644
index 0000000000000000000000000000000000000000..89742c6bfa9f75bb50d994cf3148f7d9e1c84476
--- /dev/null
+++ b/scripts/HFIR_4Circle_Reduction.py
@@ -0,0 +1,17 @@
+#pylint: disable=invalid-name
+from HFIR_4Circle_Reduction import reduce4circleGUI
+from PyQt4 import QtGui
+import sys
+
+def qapp():
+    if QtGui.QApplication.instance():
+        _app = QtGui.QApplication.instance()
+    else:
+        _app = QtGui.QApplication(sys.argv)
+    return _app
+
+app = qapp()
+
+reducer = reduce4circleGUI.MainWindow() #the main ui class in this file is called MainWindow
+reducer.show()
+app.exec_()
diff --git a/scripts/HFIR_4Circle_Reduction/CMakeLists.txt b/scripts/HFIR_4Circle_Reduction/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..67fe46df205d951ff83380c933f71c88d5325604
--- /dev/null
+++ b/scripts/HFIR_4Circle_Reduction/CMakeLists.txt
@@ -0,0 +1,8 @@
+include(UiToPy)
+
+# List of UIs to Auto convert
+set( UI_FILES
+  MainWindow.ui 
+)
+
+UiToPy( UI_FILES CompileUIHFIR_4Circle_Reduction)
diff --git a/scripts/HFIR_4Circle_Reduction/MainWindow.ui b/scripts/HFIR_4Circle_Reduction/MainWindow.ui
new file mode 100644
index 0000000000000000000000000000000000000000..4f7fa462e7008c7cf9e167e822ad5b0b47996aca
--- /dev/null
+++ b/scripts/HFIR_4Circle_Reduction/MainWindow.ui
@@ -0,0 +1,2312 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MainWindow</class>
+ <widget class="QMainWindow" name="MainWindow">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>1292</width>
+    <height>783</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>4-Circle Reduction</string>
+  </property>
+  <widget class="QWidget" name="centralwidget">
+   <layout class="QHBoxLayout" name="horizontalLayout_11">
+    <item>
+     <layout class="QVBoxLayout" name="verticalLayout_3">
+      <item>
+       <layout class="QHBoxLayout" name="horizontalLayout_General">
+        <item>
+         <widget class="QLabel" name="label_exp">
+          <property name="font">
+           <font>
+            <weight>75</weight>
+            <bold>true</bold>
+           </font>
+          </property>
+          <property name="text">
+           <string>Experiment</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QLineEdit" name="lineEdit_exp">
+          <property name="minimumSize">
+           <size>
+            <width>40</width>
+            <height>0</height>
+           </size>
+          </property>
+          <property name="maximumSize">
+           <size>
+            <width>60</width>
+            <height>16777215</height>
+           </size>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QPushButton" name="pushButton_setExp">
+          <property name="text">
+           <string>Set</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <spacer name="horizontalSpacer_11">
+          <property name="orientation">
+           <enum>Qt::Horizontal</enum>
+          </property>
+          <property name="sizeHint" stdset="0">
+           <size>
+            <width>40</width>
+            <height>20</height>
+           </size>
+          </property>
+         </spacer>
+        </item>
+        <item>
+         <widget class="QLabel" name="label_15">
+          <property name="font">
+           <font>
+            <weight>75</weight>
+            <bold>true</bold>
+           </font>
+          </property>
+          <property name="text">
+           <string>Unit Cell</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QLabel" name="label_16">
+          <property name="text">
+           <string>a</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QLineEdit" name="lineEdit_a">
+          <property name="maximumSize">
+           <size>
+            <width>120</width>
+            <height>16777215</height>
+           </size>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QLabel" name="label_23">
+          <property name="text">
+           <string>b</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QLineEdit" name="lineEdit_b">
+          <property name="maximumSize">
+           <size>
+            <width>120</width>
+            <height>16777215</height>
+           </size>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QLabel" name="label_24">
+          <property name="text">
+           <string>c</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QLineEdit" name="lineEdit_c">
+          <property name="maximumSize">
+           <size>
+            <width>120</width>
+            <height>16777215</height>
+           </size>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QLabel" name="label_25">
+          <property name="text">
+           <string>alpha</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QLineEdit" name="lineEdit_alpha">
+          <property name="maximumSize">
+           <size>
+            <width>120</width>
+            <height>16777215</height>
+           </size>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QLabel" name="label_26">
+          <property name="text">
+           <string>beta</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QLineEdit" name="lineEdit_beta">
+          <property name="maximumSize">
+           <size>
+            <width>120</width>
+            <height>16777215</height>
+           </size>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QLabel" name="label_27">
+          <property name="text">
+           <string>gamma</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QLineEdit" name="lineEdit_gamma">
+          <property name="maximumSize">
+           <size>
+            <width>120</width>
+            <height>16777215</height>
+           </size>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </item>
+      <item>
+       <layout class="QHBoxLayout" name="horizontalLayout_Tab">
+        <item>
+         <widget class="QTabWidget" name="tabWidget">
+          <property name="enabled">
+           <bool>true</bool>
+          </property>
+          <property name="currentIndex">
+           <number>0</number>
+          </property>
+          <widget class="QWidget" name="tab">
+           <attribute name="title">
+            <string>Setup &amp;&amp; Data Access</string>
+           </attribute>
+           <layout class="QGridLayout" name="gridLayout_5">
+            <item row="1" column="0">
+             <widget class="QTextEdit" name="textEdit">
+              <property name="enabled">
+               <bool>true</bool>
+              </property>
+              <property name="sizePolicy">
+               <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+                <horstretch>0</horstretch>
+                <verstretch>0</verstretch>
+               </sizepolicy>
+              </property>
+              <property name="readOnly">
+               <bool>true</bool>
+              </property>
+              <property name="html">
+               <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt; font-weight:600;&quot;&gt;1. Configure the data reduction&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt; font-style:italic;&quot;&gt;(a) Do not modify ServerURL unless necessary;&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt; font-style:italic;&quot;&gt;(b) Click 'Apply' to check internet connection and directories;&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt; font-style:italic;&quot;&gt;(c) If 'Time out' is popped out, try to click 'Apply' again. Server may not be able to respond promptly.&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt; font-style:italic;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt; font-weight:600;&quot;&gt;2. Start to reduce data&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt; font-style:italic;&quot;&gt;(a) Set&lt;/span&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt; Experiment&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+              </property>
+             </widget>
+            </item>
+            <item row="6" column="0">
+             <spacer name="verticalSpacer_2">
+              <property name="orientation">
+               <enum>Qt::Vertical</enum>
+              </property>
+              <property name="sizeHint" stdset="0">
+               <size>
+                <width>20</width>
+                <height>40</height>
+               </size>
+              </property>
+             </spacer>
+            </item>
+            <item row="0" column="0">
+             <widget class="QGroupBox" name="groupBox">
+              <property name="title">
+               <string>Configuration</string>
+              </property>
+              <layout class="QGridLayout" name="gridLayout_11">
+               <item row="1" column="2">
+                <widget class="QPushButton" name="pushButton_testURLs">
+                 <property name="sizePolicy">
+                  <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+                   <horstretch>0</horstretch>
+                   <verstretch>0</verstretch>
+                  </sizepolicy>
+                 </property>
+                 <property name="minimumSize">
+                  <size>
+                   <width>100</width>
+                   <height>0</height>
+                  </size>
+                 </property>
+                 <property name="maximumSize">
+                  <size>
+                   <width>200</width>
+                   <height>16777215</height>
+                  </size>
+                 </property>
+                 <property name="text">
+                  <string>Test</string>
+                 </property>
+                </widget>
+               </item>
+               <item row="2" column="2">
+                <widget class="QPushButton" name="pushButton_browseLocalDataDir">
+                 <property name="text">
+                  <string>Browse</string>
+                 </property>
+                </widget>
+               </item>
+               <item row="2" column="3">
+                <spacer name="horizontalSpacer">
+                 <property name="orientation">
+                  <enum>Qt::Horizontal</enum>
+                 </property>
+                 <property name="sizeType">
+                  <enum>QSizePolicy::Preferred</enum>
+                 </property>
+                 <property name="sizeHint" stdset="0">
+                  <size>
+                   <width>40</width>
+                   <height>20</height>
+                  </size>
+                 </property>
+                </spacer>
+               </item>
+               <item row="2" column="1">
+                <widget class="QLineEdit" name="lineEdit_localSpiceDir">
+                 <property name="sizePolicy">
+                  <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+                   <horstretch>0</horstretch>
+                   <verstretch>0</verstretch>
+                  </sizepolicy>
+                 </property>
+                 <property name="toolTip">
+                  <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Directory for local data storage&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+                 </property>
+                </widget>
+               </item>
+               <item row="0" column="0">
+                <widget class="QLabel" name="label_instrument">
+                 <property name="sizePolicy">
+                  <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+                   <horstretch>0</horstretch>
+                   <verstretch>0</verstretch>
+                  </sizepolicy>
+                 </property>
+                 <property name="text">
+                  <string>Instrument</string>
+                 </property>
+                </widget>
+               </item>
+               <item row="2" column="0">
+                <widget class="QLabel" name="label_dir">
+                 <property name="sizePolicy">
+                  <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+                   <horstretch>0</horstretch>
+                   <verstretch>0</verstretch>
+                  </sizepolicy>
+                 </property>
+                 <property name="minimumSize">
+                  <size>
+                   <width>80</width>
+                   <height>0</height>
+                  </size>
+                 </property>
+                 <property name="toolTip">
+                  <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Directory for local data storage&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+                 </property>
+                 <property name="text">
+                  <string>Data Directory</string>
+                 </property>
+                 <property name="alignment">
+                  <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+                 </property>
+                </widget>
+               </item>
+               <item row="0" column="1">
+                <widget class="QComboBox" name="comboBox_instrument">
+                 <item>
+                  <property name="text">
+                   <string>HB3A</string>
+                  </property>
+                 </item>
+                </widget>
+               </item>
+               <item row="0" column="2">
+                <widget class="QPushButton" name="pushButton_useDefaultDir">
+                 <property name="font">
+                  <font>
+                   <pointsize>10</pointsize>
+                  </font>
+                 </property>
+                 <property name="toolTip">
+                  <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Use default set up&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+                 </property>
+                 <property name="text">
+                  <string>Load Default</string>
+                 </property>
+                </widget>
+               </item>
+               <item row="3" column="1">
+                <widget class="QLineEdit" name="lineEdit_workDir">
+                 <property name="sizePolicy">
+                  <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+                   <horstretch>0</horstretch>
+                   <verstretch>0</verstretch>
+                  </sizepolicy>
+                 </property>
+                 <property name="toolTip">
+                  <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Directory to save outcome of the data reduction&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+                 </property>
+                </widget>
+               </item>
+               <item row="1" column="1">
+                <widget class="QLineEdit" name="lineEdit_url">
+                 <property name="sizePolicy">
+                  <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+                   <horstretch>0</horstretch>
+                   <verstretch>0</verstretch>
+                  </sizepolicy>
+                 </property>
+                </widget>
+               </item>
+               <item row="1" column="0">
+                <widget class="QLabel" name="label_url">
+                 <property name="sizePolicy">
+                  <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+                   <horstretch>0</horstretch>
+                   <verstretch>0</verstretch>
+                  </sizepolicy>
+                 </property>
+                 <property name="minimumSize">
+                  <size>
+                   <width>80</width>
+                   <height>0</height>
+                  </size>
+                 </property>
+                 <property name="toolTip">
+                  <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;URL of the http server to download HB3A data&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+                 </property>
+                 <property name="text">
+                  <string>Server URL</string>
+                 </property>
+                </widget>
+               </item>
+               <item row="3" column="2">
+                <widget class="QPushButton" name="pushButton_browseWorkDir">
+                 <property name="text">
+                  <string>Browse</string>
+                 </property>
+                </widget>
+               </item>
+               <item row="3" column="0">
+                <widget class="QLabel" name="label_2">
+                 <property name="sizePolicy">
+                  <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+                   <horstretch>0</horstretch>
+                   <verstretch>0</verstretch>
+                  </sizepolicy>
+                 </property>
+                 <property name="minimumSize">
+                  <size>
+                   <width>140</width>
+                   <height>1</height>
+                  </size>
+                 </property>
+                 <property name="maximumSize">
+                  <size>
+                   <width>140</width>
+                   <height>16777215</height>
+                  </size>
+                 </property>
+                 <property name="toolTip">
+                  <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Directory to save outcome of the data reduction&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+                 </property>
+                 <property name="text">
+                  <string>Working Direcotry</string>
+                 </property>
+                </widget>
+               </item>
+               <item row="4" column="2">
+                <widget class="QPushButton" name="pushButton_applySetup">
+                 <property name="font">
+                  <font>
+                   <weight>75</weight>
+                   <bold>true</bold>
+                  </font>
+                 </property>
+                 <property name="text">
+                  <string>Apply</string>
+                 </property>
+                </widget>
+               </item>
+              </layout>
+             </widget>
+            </item>
+            <item row="4" column="0">
+             <widget class="QGroupBox" name="groupBox_2">
+              <property name="title">
+               <string>Data Download</string>
+              </property>
+              <layout class="QGridLayout" name="gridLayout_12">
+               <item row="0" column="2">
+                <widget class="QPushButton" name="pushButton_browseLocalCache">
+                 <property name="sizePolicy">
+                  <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+                   <horstretch>0</horstretch>
+                   <verstretch>0</verstretch>
+                  </sizepolicy>
+                 </property>
+                 <property name="minimumSize">
+                  <size>
+                   <width>100</width>
+                   <height>0</height>
+                  </size>
+                 </property>
+                 <property name="maximumSize">
+                  <size>
+                   <width>100</width>
+                   <height>16777215</height>
+                  </size>
+                 </property>
+                 <property name="text">
+                  <string>Browse</string>
+                 </property>
+                </widget>
+               </item>
+               <item row="2" column="0">
+                <widget class="QLabel" name="label">
+                 <property name="sizePolicy">
+                  <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+                   <horstretch>0</horstretch>
+                   <verstretch>0</verstretch>
+                  </sizepolicy>
+                 </property>
+                 <property name="minimumSize">
+                  <size>
+                   <width>80</width>
+                   <height>0</height>
+                  </size>
+                 </property>
+                 <property name="text">
+                  <string>Scans List</string>
+                 </property>
+                </widget>
+               </item>
+               <item row="1" column="1">
+                <widget class="QComboBox" name="comboBox_mode">
+                 <property name="sizePolicy">
+                  <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+                   <horstretch>0</horstretch>
+                   <verstretch>0</verstretch>
+                  </sizepolicy>
+                 </property>
+                 <property name="toolTip">
+                  <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Mode &amp;quot;download&amp;quot;: download data to local disk;&lt;/p&gt;&lt;p&gt;Mode &amp;quot;http server only&amp;quot;: download data to cache, process and delete cached data upon returning&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+                 </property>
+                 <item>
+                  <property name="text">
+                   <string>Download Complete Experiment</string>
+                  </property>
+                 </item>
+                 <item>
+                  <property name="text">
+                   <string>Download Selected Scans</string>
+                  </property>
+                 </item>
+                </widget>
+               </item>
+               <item row="0" column="1">
+                <widget class="QLineEdit" name="lineEdit_localSrcDir">
+                 <property name="toolTip">
+                  <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Cache on local disk.  The dowloaded data will be saved to here. &lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+                 </property>
+                </widget>
+               </item>
+               <item row="1" column="0">
+                <widget class="QLabel" name="label_datamode">
+                 <property name="sizePolicy">
+                  <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+                   <horstretch>0</horstretch>
+                   <verstretch>0</verstretch>
+                  </sizepolicy>
+                 </property>
+                 <property name="minimumSize">
+                  <size>
+                   <width>80</width>
+                   <height>0</height>
+                  </size>
+                 </property>
+                 <property name="text">
+                  <string>Download Mode</string>
+                 </property>
+                </widget>
+               </item>
+               <item row="0" column="0">
+                <widget class="QLabel" name="label_4">
+                 <property name="sizePolicy">
+                  <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+                   <horstretch>0</horstretch>
+                   <verstretch>0</verstretch>
+                  </sizepolicy>
+                 </property>
+                 <property name="minimumSize">
+                  <size>
+                   <width>140</width>
+                   <height>0</height>
+                  </size>
+                 </property>
+                 <property name="maximumSize">
+                  <size>
+                   <width>140</width>
+                   <height>16777215</height>
+                  </size>
+                 </property>
+                 <property name="text">
+                  <string>Destination</string>
+                 </property>
+                </widget>
+               </item>
+               <item row="0" column="6">
+                <spacer name="horizontalSpacer_2">
+                 <property name="orientation">
+                  <enum>Qt::Horizontal</enum>
+                 </property>
+                 <property name="sizeType">
+                  <enum>QSizePolicy::Minimum</enum>
+                 </property>
+                 <property name="sizeHint" stdset="0">
+                  <size>
+                   <width>40</width>
+                   <height>20</height>
+                  </size>
+                 </property>
+                </spacer>
+               </item>
+               <item row="1" column="2">
+                <widget class="QPushButton" name="pushButton_downloadExpData">
+                 <property name="font">
+                  <font>
+                   <weight>75</weight>
+                   <bold>true</bold>
+                  </font>
+                 </property>
+                 <property name="toolTip">
+                  <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:400;&quot;&gt;Download scans specified by 'Scans List'; &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:400;&quot;&gt;If 'Scans List' is empty, then the complete experiment data will be downloaded&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+                 </property>
+                 <property name="text">
+                  <string>Download</string>
+                 </property>
+                </widget>
+               </item>
+               <item row="2" column="1">
+                <widget class="QLineEdit" name="lineEdit_downloadScans"/>
+               </item>
+               <item row="2" column="2">
+                <widget class="QPushButton" name="pushButton_ListScans">
+                 <property name="text">
+                  <string>List Scans</string>
+                 </property>
+                </widget>
+               </item>
+              </layout>
+             </widget>
+            </item>
+            <item row="3" column="0">
+             <spacer name="verticalSpacer_4">
+              <property name="orientation">
+               <enum>Qt::Vertical</enum>
+              </property>
+              <property name="sizeType">
+               <enum>QSizePolicy::Preferred</enum>
+              </property>
+              <property name="sizeHint" stdset="0">
+               <size>
+                <width>20</width>
+                <height>40</height>
+               </size>
+              </property>
+             </spacer>
+            </item>
+           </layout>
+          </widget>
+          <widget class="QWidget" name="tab_4">
+           <attribute name="title">
+            <string>View Raw Data</string>
+           </attribute>
+           <layout class="QGridLayout" name="gridLayout_9">
+            <item row="0" column="0">
+             <layout class="QGridLayout" name="gridLayout_3">
+              <item row="0" column="3">
+               <layout class="QVBoxLayout" name="verticalLayout_5">
+                <item>
+                 <layout class="QGridLayout" name="gridLayout"/>
+                </item>
+                <item>
+                 <widget class="QGroupBox" name="groupBox_3">
+                  <property name="title">
+                   <string>Scan</string>
+                  </property>
+                  <layout class="QVBoxLayout" name="verticalLayout">
+                   <item>
+                    <widget class="QLineEdit" name="lineEdit_run">
+                     <property name="sizePolicy">
+                      <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+                       <horstretch>0</horstretch>
+                       <verstretch>0</verstretch>
+                      </sizepolicy>
+                     </property>
+                     <property name="minimumSize">
+                      <size>
+                       <width>10</width>
+                       <height>0</height>
+                      </size>
+                     </property>
+                     <property name="maximumSize">
+                      <size>
+                       <width>10000</width>
+                       <height>16777215</height>
+                      </size>
+                     </property>
+                     <property name="alignment">
+                      <set>Qt::AlignCenter</set>
+                     </property>
+                    </widget>
+                   </item>
+                   <item>
+                    <widget class="QPushButton" name="pushButton_setScanInfo">
+                     <property name="text">
+                      <string>Set</string>
+                     </property>
+                    </widget>
+                   </item>
+                   <item>
+                    <widget class="QPushButton" name="pushButton_showPtList">
+                     <property name="text">
+                      <string>List Pt.</string>
+                     </property>
+                    </widget>
+                   </item>
+                  </layout>
+                 </widget>
+                </item>
+                <item>
+                 <widget class="Line" name="line">
+                  <property name="orientation">
+                   <enum>Qt::Horizontal</enum>
+                  </property>
+                 </widget>
+                </item>
+                <item>
+                 <widget class="QGroupBox" name="groupBox_4">
+                  <property name="title">
+                   <string> Pt</string>
+                  </property>
+                  <layout class="QVBoxLayout" name="verticalLayout_2">
+                   <item>
+                    <widget class="QLineEdit" name="lineEdit_rawDataPtNo">
+                     <property name="sizePolicy">
+                      <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+                       <horstretch>0</horstretch>
+                       <verstretch>0</verstretch>
+                      </sizepolicy>
+                     </property>
+                     <property name="minimumSize">
+                      <size>
+                       <width>60</width>
+                       <height>0</height>
+                      </size>
+                     </property>
+                     <property name="maximumSize">
+                      <size>
+                       <width>1000</width>
+                       <height>16777215</height>
+                      </size>
+                     </property>
+                     <property name="alignment">
+                      <set>Qt::AlignCenter</set>
+                     </property>
+                    </widget>
+                   </item>
+                   <item>
+                    <widget class="QPushButton" name="pushButton_plotRawPt">
+                     <property name="sizePolicy">
+                      <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+                       <horstretch>0</horstretch>
+                       <verstretch>0</verstretch>
+                      </sizepolicy>
+                     </property>
+                     <property name="minimumSize">
+                      <size>
+                       <width>80</width>
+                       <height>0</height>
+                      </size>
+                     </property>
+                     <property name="text">
+                      <string>Plot</string>
+                     </property>
+                    </widget>
+                   </item>
+                   <item>
+                    <widget class="QPushButton" name="pushButton_usePt4UB">
+                     <property name="toolTip">
+                      <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Use this peak to calcualate UB matrix&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+                     </property>
+                     <property name="text">
+                      <string>Use</string>
+                     </property>
+                    </widget>
+                   </item>
+                   <item>
+                    <spacer name="verticalSpacer_5">
+                     <property name="orientation">
+                      <enum>Qt::Vertical</enum>
+                     </property>
+                     <property name="sizeType">
+                      <enum>QSizePolicy::Minimum</enum>
+                     </property>
+                     <property name="sizeHint" stdset="0">
+                      <size>
+                       <width>20</width>
+                       <height>40</height>
+                      </size>
+                     </property>
+                    </spacer>
+                   </item>
+                   <item>
+                    <layout class="QHBoxLayout" name="horizontalLayout_8">
+                     <item>
+                      <widget class="QPushButton" name="pushButton_prevPtNumber">
+                       <property name="sizePolicy">
+                        <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+                         <horstretch>0</horstretch>
+                         <verstretch>0</verstretch>
+                        </sizepolicy>
+                       </property>
+                       <property name="minimumSize">
+                        <size>
+                         <width>30</width>
+                         <height>0</height>
+                        </size>
+                       </property>
+                       <property name="maximumSize">
+                        <size>
+                         <width>40</width>
+                         <height>16777215</height>
+                        </size>
+                       </property>
+                       <property name="toolTip">
+                        <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Previous Pt. No&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+                       </property>
+                       <property name="text">
+                        <string>&lt;---|</string>
+                       </property>
+                      </widget>
+                     </item>
+                     <item>
+                      <spacer name="horizontalSpacer_7">
+                       <property name="orientation">
+                        <enum>Qt::Horizontal</enum>
+                       </property>
+                       <property name="sizeType">
+                        <enum>QSizePolicy::Preferred</enum>
+                       </property>
+                       <property name="sizeHint" stdset="0">
+                        <size>
+                         <width>5</width>
+                         <height>20</height>
+                        </size>
+                       </property>
+                      </spacer>
+                     </item>
+                     <item>
+                      <widget class="QPushButton" name="pushButton_nextPtNumber">
+                       <property name="sizePolicy">
+                        <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+                         <horstretch>0</horstretch>
+                         <verstretch>0</verstretch>
+                        </sizepolicy>
+                       </property>
+                       <property name="minimumSize">
+                        <size>
+                         <width>30</width>
+                         <height>0</height>
+                        </size>
+                       </property>
+                       <property name="maximumSize">
+                        <size>
+                         <width>40</width>
+                         <height>16777215</height>
+                        </size>
+                       </property>
+                       <property name="text">
+                        <string>|--&gt;</string>
+                       </property>
+                      </widget>
+                     </item>
+                    </layout>
+                   </item>
+                  </layout>
+                 </widget>
+                </item>
+                <item>
+                 <spacer name="verticalSpacer_6">
+                  <property name="orientation">
+                   <enum>Qt::Vertical</enum>
+                  </property>
+                  <property name="sizeHint" stdset="0">
+                   <size>
+                    <width>20</width>
+                    <height>40</height>
+                   </size>
+                  </property>
+                 </spacer>
+                </item>
+               </layout>
+              </item>
+              <item row="0" column="0">
+               <widget class="MplGraphicsView" name="graphicsView">
+                <property name="sizePolicy">
+                 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+                  <horstretch>0</horstretch>
+                  <verstretch>0</verstretch>
+                 </sizepolicy>
+                </property>
+               </widget>
+              </item>
+             </layout>
+            </item>
+           </layout>
+          </widget>
+          <widget class="QWidget" name="tab_2">
+           <attribute name="title">
+            <string>Calculate UB</string>
+           </attribute>
+           <layout class="QGridLayout" name="gridLayout_6">
+            <item row="0" column="0">
+             <layout class="QVBoxLayout" name="verticalLayout_4">
+              <item>
+               <widget class="QGroupBox" name="groupBox_7">
+                <property name="title">
+                 <string>Add Peak</string>
+                </property>
+                <layout class="QGridLayout" name="gridLayout_2">
+                 <item row="0" column="0">
+                  <widget class="QLabel" name="label_scanNo">
+                   <property name="text">
+                    <string>Scan Number</string>
+                   </property>
+                  </widget>
+                 </item>
+                 <item row="0" column="8">
+                  <widget class="QLineEdit" name="lineEdit_H">
+                   <property name="maximumSize">
+                    <size>
+                     <width>60</width>
+                     <height>40</height>
+                    </size>
+                   </property>
+                  </widget>
+                 </item>
+                 <item row="0" column="2">
+                  <widget class="QLabel" name="label_PtNo">
+                   <property name="text">
+                    <string>Pt Number</string>
+                   </property>
+                  </widget>
+                 </item>
+                 <item row="3" column="12">
+                  <widget class="QLineEdit" name="lineEdit_sampleQy">
+                   <property name="enabled">
+                    <bool>false</bool>
+                   </property>
+                   <property name="maximumSize">
+                    <size>
+                     <width>120</width>
+                     <height>16777215</height>
+                    </size>
+                   </property>
+                  </widget>
+                 </item>
+                 <item row="0" column="11">
+                  <widget class="QLabel" name="label_11">
+                   <property name="text">
+                    <string>K</string>
+                   </property>
+                  </widget>
+                 </item>
+                 <item row="0" column="13">
+                  <widget class="QLabel" name="label_6">
+                   <property name="text">
+                    <string>L</string>
+                   </property>
+                  </widget>
+                 </item>
+                 <item row="3" column="8">
+                  <widget class="QLineEdit" name="lineEdit_sampleQx">
+                   <property name="enabled">
+                    <bool>false</bool>
+                   </property>
+                   <property name="maximumSize">
+                    <size>
+                     <width>120</width>
+                     <height>16777215</height>
+                    </size>
+                   </property>
+                  </widget>
+                 </item>
+                 <item row="3" column="6">
+                  <widget class="QLabel" name="label_7">
+                   <property name="text">
+                    <string> Q-Sample </string>
+                   </property>
+                   <property name="alignment">
+                    <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+                   </property>
+                  </widget>
+                 </item>
+                 <item row="0" column="3">
+                  <widget class="QLineEdit" name="lineEdit_ptNumber">
+                   <property name="sizePolicy">
+                    <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+                     <horstretch>0</horstretch>
+                     <verstretch>0</verstretch>
+                    </sizepolicy>
+                   </property>
+                   <property name="maximumSize">
+                    <size>
+                     <width>60</width>
+                     <height>16777215</height>
+                    </size>
+                   </property>
+                  </widget>
+                 </item>
+                 <item row="3" column="11">
+                  <widget class="QLabel" name="label_9">
+                   <property name="text">
+                    <string>Y</string>
+                   </property>
+                  </widget>
+                 </item>
+                 <item row="3" column="14">
+                  <widget class="QLineEdit" name="lineEdit_sampleQz">
+                   <property name="enabled">
+                    <bool>false</bool>
+                   </property>
+                   <property name="maximumSize">
+                    <size>
+                     <width>120</width>
+                     <height>16777215</height>
+                    </size>
+                   </property>
+                  </widget>
+                 </item>
+                 <item row="3" column="7">
+                  <widget class="QLabel" name="label_8">
+                   <property name="text">
+                    <string>X</string>
+                   </property>
+                  </widget>
+                 </item>
+                 <item row="0" column="1">
+                  <widget class="QLineEdit" name="lineEdit_scanNumber">
+                   <property name="sizePolicy">
+                    <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+                     <horstretch>0</horstretch>
+                     <verstretch>0</verstretch>
+                    </sizepolicy>
+                   </property>
+                   <property name="maximumSize">
+                    <size>
+                     <width>60</width>
+                     <height>16777215</height>
+                    </size>
+                   </property>
+                  </widget>
+                 </item>
+                 <item row="0" column="12">
+                  <widget class="QLineEdit" name="lineEdit_K">
+                   <property name="maximumSize">
+                    <size>
+                     <width>60</width>
+                     <height>16777215</height>
+                    </size>
+                   </property>
+                  </widget>
+                 </item>
+                 <item row="0" column="14">
+                  <widget class="QLineEdit" name="lineEdit_L">
+                   <property name="maximumSize">
+                    <size>
+                     <width>60</width>
+                     <height>16777215</height>
+                    </size>
+                   </property>
+                  </widget>
+                 </item>
+                 <item row="0" column="7">
+                  <widget class="QLabel" name="label_12">
+                   <property name="text">
+                    <string>H</string>
+                   </property>
+                  </widget>
+                 </item>
+                 <item row="3" column="13">
+                  <widget class="QLabel" name="label_10">
+                   <property name="text">
+                    <string>Z</string>
+                   </property>
+                  </widget>
+                 </item>
+                 <item row="0" column="5">
+                  <spacer name="horizontalSpacer_4">
+                   <property name="orientation">
+                    <enum>Qt::Horizontal</enum>
+                   </property>
+                   <property name="sizeType">
+                    <enum>QSizePolicy::Preferred</enum>
+                   </property>
+                   <property name="sizeHint" stdset="0">
+                    <size>
+                     <width>40</width>
+                     <height>20</height>
+                    </size>
+                   </property>
+                  </spacer>
+                 </item>
+                 <item row="0" column="6">
+                  <widget class="QLabel" name="label_31">
+                   <property name="text">
+                    <string>Miller Index</string>
+                   </property>
+                  </widget>
+                 </item>
+                 <item row="0" column="4">
+                  <widget class="QPushButton" name="pushButton_findPeak">
+                   <property name="font">
+                    <font>
+                     <weight>75</weight>
+                     <bold>true</bold>
+                    </font>
+                   </property>
+                   <property name="text">
+                    <string>Find Peak</string>
+                   </property>
+                  </widget>
+                 </item>
+                 <item row="3" column="4">
+                  <widget class="QCheckBox" name="checkBox_loadHKLfromFile">
+                   <property name="font">
+                    <font>
+                     <pointsize>9</pointsize>
+                    </font>
+                   </property>
+                   <property name="text">
+                    <string>Load HKL from file</string>
+                   </property>
+                  </widget>
+                 </item>
+                </layout>
+               </widget>
+              </item>
+              <item>
+               <layout class="QHBoxLayout" name="horizontalLayout_7">
+                <item>
+                 <widget class="UBMatrixPeakTable" name="tableWidget_peaksCalUB"/>
+                </item>
+                <item>
+                 <layout class="QVBoxLayout" name="verticalLayout_8">
+                  <item>
+                   <widget class="QPushButton" name="pushButton_addPeakToCalUB">
+                    <property name="font">
+                     <font>
+                      <weight>75</weight>
+                      <bold>true</bold>
+                     </font>
+                    </property>
+                    <property name="text">
+                     <string>Add Peak</string>
+                    </property>
+                   </widget>
+                  </item>
+                  <item>
+                   <widget class="QCheckBox" name="checkBox_roundHKLInt">
+                    <property name="font">
+                     <font>
+                      <pointsize>9</pointsize>
+                     </font>
+                    </property>
+                    <property name="text">
+                     <string>RoundHKL to int</string>
+                    </property>
+                   </widget>
+                  </item>
+                  <item>
+                   <spacer name="verticalSpacer_11">
+                    <property name="orientation">
+                     <enum>Qt::Vertical</enum>
+                    </property>
+                    <property name="sizeHint" stdset="0">
+                     <size>
+                      <width>20</width>
+                      <height>40</height>
+                     </size>
+                    </property>
+                   </spacer>
+                  </item>
+                  <item>
+                   <widget class="QPushButton" name="pushButton_deleteUBPeak">
+                    <property name="minimumSize">
+                     <size>
+                      <width>100</width>
+                      <height>0</height>
+                     </size>
+                    </property>
+                    <property name="maximumSize">
+                     <size>
+                      <width>200</width>
+                      <height>16777215</height>
+                     </size>
+                    </property>
+                    <property name="text">
+                     <string>Delete</string>
+                    </property>
+                   </widget>
+                  </item>
+                  <item>
+                   <widget class="QPushButton" name="pushButton_clearUBPeakTable">
+                    <property name="text">
+                     <string>Clear</string>
+                    </property>
+                   </widget>
+                  </item>
+                  <item>
+                   <spacer name="verticalSpacer_7">
+                    <property name="orientation">
+                     <enum>Qt::Vertical</enum>
+                    </property>
+                    <property name="sizeHint" stdset="0">
+                     <size>
+                      <width>20</width>
+                      <height>40</height>
+                     </size>
+                    </property>
+                   </spacer>
+                  </item>
+                 </layout>
+                </item>
+               </layout>
+              </item>
+              <item>
+               <layout class="QHBoxLayout" name="horizontalLayout_13">
+                <item>
+                 <widget class="QLabel" name="label_32">
+                  <property name="sizePolicy">
+                   <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+                    <horstretch>0</horstretch>
+                    <verstretch>0</verstretch>
+                   </sizepolicy>
+                  </property>
+                  <property name="font">
+                   <font>
+                    <pointsize>14</pointsize>
+                    <weight>75</weight>
+                    <bold>true</bold>
+                   </font>
+                  </property>
+                  <property name="text">
+                   <string>UB Matrix</string>
+                  </property>
+                 </widget>
+                </item>
+                <item>
+                 <spacer name="horizontalSpacer_6">
+                  <property name="orientation">
+                   <enum>Qt::Horizontal</enum>
+                  </property>
+                  <property name="sizeType">
+                   <enum>QSizePolicy::Preferred</enum>
+                  </property>
+                  <property name="sizeHint" stdset="0">
+                   <size>
+                    <width>40</width>
+                    <height>20</height>
+                   </size>
+                  </property>
+                 </spacer>
+                </item>
+                <item>
+                 <widget class="UBMatrixTable" name="tableWidget_ubMatrix">
+                  <property name="sizePolicy">
+                   <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+                    <horstretch>0</horstretch>
+                    <verstretch>0</verstretch>
+                   </sizepolicy>
+                  </property>
+                  <property name="minimumSize">
+                   <size>
+                    <width>360</width>
+                    <height>0</height>
+                   </size>
+                  </property>
+                  <row>
+                   <property name="text">
+                    <string/>
+                   </property>
+                  </row>
+                  <row>
+                   <property name="text">
+                    <string/>
+                   </property>
+                  </row>
+                  <row>
+                   <property name="text">
+                    <string/>
+                   </property>
+                  </row>
+                  <column>
+                   <property name="text">
+                    <string/>
+                   </property>
+                  </column>
+                  <column>
+                   <property name="text">
+                    <string/>
+                   </property>
+                  </column>
+                  <column>
+                   <property name="text">
+                    <string/>
+                   </property>
+                  </column>
+                 </widget>
+                </item>
+                <item>
+                 <spacer name="horizontalSpacer_5">
+                  <property name="orientation">
+                   <enum>Qt::Horizontal</enum>
+                  </property>
+                  <property name="sizeHint" stdset="0">
+                   <size>
+                    <width>40</width>
+                    <height>20</height>
+                   </size>
+                  </property>
+                 </spacer>
+                </item>
+                <item>
+                 <layout class="QVBoxLayout" name="verticalLayout_12">
+                  <item>
+                   <widget class="QPushButton" name="pushButton_calUB">
+                    <property name="minimumSize">
+                     <size>
+                      <width>100</width>
+                      <height>0</height>
+                     </size>
+                    </property>
+                    <property name="maximumSize">
+                     <size>
+                      <width>100</width>
+                      <height>16777215</height>
+                     </size>
+                    </property>
+                    <property name="text">
+                     <string>Calculate UB</string>
+                    </property>
+                   </widget>
+                  </item>
+                  <item>
+                   <spacer name="verticalSpacer_8">
+                    <property name="orientation">
+                     <enum>Qt::Vertical</enum>
+                    </property>
+                    <property name="sizeType">
+                     <enum>QSizePolicy::Ignored</enum>
+                    </property>
+                    <property name="sizeHint" stdset="0">
+                     <size>
+                      <width>20</width>
+                      <height>40</height>
+                     </size>
+                    </property>
+                   </spacer>
+                  </item>
+                  <item>
+                   <widget class="QPushButton" name="pushButton_acceptUB">
+                    <property name="minimumSize">
+                     <size>
+                      <width>100</width>
+                      <height>0</height>
+                     </size>
+                    </property>
+                    <property name="maximumSize">
+                     <size>
+                      <width>100</width>
+                      <height>16777215</height>
+                     </size>
+                    </property>
+                    <property name="text">
+                     <string>Accept</string>
+                    </property>
+                   </widget>
+                  </item>
+                  <item>
+                   <spacer name="verticalSpacer_9">
+                    <property name="orientation">
+                     <enum>Qt::Vertical</enum>
+                    </property>
+                    <property name="sizeType">
+                     <enum>QSizePolicy::Preferred</enum>
+                    </property>
+                    <property name="sizeHint" stdset="0">
+                     <size>
+                      <width>20</width>
+                      <height>40</height>
+                     </size>
+                    </property>
+                   </spacer>
+                  </item>
+                 </layout>
+                </item>
+                <item>
+                 <spacer name="horizontalSpacer_8">
+                  <property name="orientation">
+                   <enum>Qt::Horizontal</enum>
+                  </property>
+                  <property name="sizeType">
+                   <enum>QSizePolicy::Ignored</enum>
+                  </property>
+                  <property name="sizeHint" stdset="0">
+                   <size>
+                    <width>40</width>
+                    <height>20</height>
+                   </size>
+                  </property>
+                 </spacer>
+                </item>
+                <item>
+                 <layout class="QVBoxLayout" name="verticalLayout_9">
+                  <item>
+                   <widget class="QPushButton" name="pushButton_indexUBPeaks">
+                    <property name="minimumSize">
+                     <size>
+                      <width>100</width>
+                      <height>0</height>
+                     </size>
+                    </property>
+                    <property name="maximumSize">
+                     <size>
+                      <width>100</width>
+                      <height>16777215</height>
+                     </size>
+                    </property>
+                    <property name="text">
+                     <string>Index Peak</string>
+                    </property>
+                   </widget>
+                  </item>
+                  <item>
+                   <spacer name="verticalSpacer_12">
+                    <property name="orientation">
+                     <enum>Qt::Vertical</enum>
+                    </property>
+                    <property name="sizeType">
+                     <enum>QSizePolicy::Ignored</enum>
+                    </property>
+                    <property name="sizeHint" stdset="0">
+                     <size>
+                      <width>20</width>
+                      <height>40</height>
+                     </size>
+                    </property>
+                   </spacer>
+                  </item>
+                  <item>
+                   <widget class="QPushButton" name="pushButton_resetPeakHKLs">
+                    <property name="text">
+                     <string>Reset HKL</string>
+                    </property>
+                   </widget>
+                  </item>
+                  <item>
+                   <spacer name="verticalSpacer">
+                    <property name="orientation">
+                     <enum>Qt::Vertical</enum>
+                    </property>
+                    <property name="sizeType">
+                     <enum>QSizePolicy::Preferred</enum>
+                    </property>
+                    <property name="sizeHint" stdset="0">
+                     <size>
+                      <width>20</width>
+                      <height>40</height>
+                     </size>
+                    </property>
+                   </spacer>
+                  </item>
+                 </layout>
+                </item>
+               </layout>
+              </item>
+             </layout>
+            </item>
+           </layout>
+          </widget>
+          <widget class="QWidget" name="tab_advsetup">
+           <attribute name="title">
+            <string>Merge Scan</string>
+           </attribute>
+           <layout class="QHBoxLayout" name="horizontalLayout_2">
+            <item>
+             <widget class="QGroupBox" name="groupBox_5">
+              <property name="title">
+               <string>UB Matrix</string>
+              </property>
+              <layout class="QVBoxLayout" name="verticalLayout_13">
+               <item>
+                <widget class="UBMatrixTable" name="tableWidget_ubSiceView">
+                 <property name="sizePolicy">
+                  <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+                   <horstretch>0</horstretch>
+                   <verstretch>0</verstretch>
+                  </sizepolicy>
+                 </property>
+                 <property name="maximumSize">
+                  <size>
+                   <width>16777215</width>
+                   <height>150</height>
+                  </size>
+                 </property>
+                 <row>
+                  <property name="text">
+                   <string/>
+                  </property>
+                 </row>
+                 <row>
+                  <property name="text">
+                   <string/>
+                  </property>
+                 </row>
+                 <row>
+                  <property name="text">
+                   <string/>
+                  </property>
+                 </row>
+                 <column>
+                  <property name="text">
+                   <string/>
+                  </property>
+                 </column>
+                 <column>
+                  <property name="text">
+                   <string/>
+                  </property>
+                 </column>
+                 <column>
+                  <property name="text">
+                   <string/>
+                  </property>
+                 </column>
+                 <item row="0" column="0">
+                  <property name="text">
+                   <string>1</string>
+                  </property>
+                 </item>
+                 <item row="1" column="1">
+                  <property name="text">
+                   <string>1</string>
+                  </property>
+                 </item>
+                 <item row="2" column="2">
+                  <property name="text">
+                   <string>1</string>
+                  </property>
+                 </item>
+                </widget>
+               </item>
+               <item>
+                <spacer name="verticalSpacer_13">
+                 <property name="orientation">
+                  <enum>Qt::Vertical</enum>
+                 </property>
+                 <property name="sizeType">
+                  <enum>QSizePolicy::Ignored</enum>
+                 </property>
+                 <property name="sizeHint" stdset="0">
+                  <size>
+                   <width>20</width>
+                   <height>40</height>
+                  </size>
+                 </property>
+                </spacer>
+               </item>
+               <item>
+                <layout class="QGridLayout" name="gridLayout_4">
+                 <item row="0" column="2">
+                  <widget class="QLabel" name="label_3">
+                   <property name="text">
+                    <string>From tab 'Caclulate UB'</string>
+                   </property>
+                  </widget>
+                 </item>
+                 <item row="0" column="0">
+                  <widget class="QRadioButton" name="radioButton_ubFromTab1">
+                   <property name="text">
+                    <string/>
+                   </property>
+                  </widget>
+                 </item>
+                 <item row="0" column="1">
+                  <spacer name="horizontalSpacer_9">
+                   <property name="orientation">
+                    <enum>Qt::Horizontal</enum>
+                   </property>
+                   <property name="sizeType">
+                    <enum>QSizePolicy::Preferred</enum>
+                   </property>
+                   <property name="sizeHint" stdset="0">
+                    <size>
+                     <width>40</width>
+                     <height>20</height>
+                    </size>
+                   </property>
+                  </spacer>
+                 </item>
+                 <item row="2" column="0">
+                  <widget class="QRadioButton" name="radioButton_ubFromTab3">
+                   <property name="enabled">
+                    <bool>false</bool>
+                   </property>
+                   <property name="text">
+                    <string/>
+                   </property>
+                  </widget>
+                 </item>
+                 <item row="2" column="2">
+                  <widget class="QLabel" name="label_28">
+                   <property name="text">
+                    <string>From tab 'Refine UB'</string>
+                   </property>
+                  </widget>
+                 </item>
+                 <item row="3" column="2">
+                  <widget class="QPlainTextEdit" name="plainTextEdit_ubInput">
+                   <property name="sizePolicy">
+                    <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
+                     <horstretch>0</horstretch>
+                     <verstretch>0</verstretch>
+                    </sizepolicy>
+                   </property>
+                  </widget>
+                 </item>
+                 <item row="3" column="0">
+                  <layout class="QVBoxLayout" name="verticalLayout_15">
+                   <item>
+                    <widget class="QRadioButton" name="radioButton_ubFromList">
+                     <property name="text">
+                      <string/>
+                     </property>
+                    </widget>
+                   </item>
+                   <item>
+                    <spacer name="verticalSpacer_15">
+                     <property name="orientation">
+                      <enum>Qt::Vertical</enum>
+                     </property>
+                     <property name="sizeHint" stdset="0">
+                      <size>
+                       <width>20</width>
+                       <height>40</height>
+                      </size>
+                     </property>
+                    </spacer>
+                   </item>
+                  </layout>
+                 </item>
+                </layout>
+               </item>
+               <item>
+                <spacer name="verticalSpacer_14">
+                 <property name="orientation">
+                  <enum>Qt::Vertical</enum>
+                 </property>
+                 <property name="sizeType">
+                  <enum>QSizePolicy::Ignored</enum>
+                 </property>
+                 <property name="sizeHint" stdset="0">
+                  <size>
+                   <width>20</width>
+                   <height>40</height>
+                  </size>
+                 </property>
+                </spacer>
+               </item>
+               <item>
+                <widget class="QPushButton" name="pushButton_setUBSliceView">
+                 <property name="text">
+                  <string>Set</string>
+                 </property>
+                </widget>
+               </item>
+               <item>
+                <spacer name="verticalSpacer_10">
+                 <property name="orientation">
+                  <enum>Qt::Vertical</enum>
+                 </property>
+                 <property name="sizeHint" stdset="0">
+                  <size>
+                   <width>20</width>
+                   <height>40</height>
+                  </size>
+                 </property>
+                </spacer>
+               </item>
+              </layout>
+             </widget>
+            </item>
+            <item>
+             <widget class="QGroupBox" name="groupBox_6">
+              <property name="title">
+               <string>Process Data</string>
+              </property>
+              <layout class="QVBoxLayout" name="verticalLayout_14">
+               <item>
+                <layout class="QGridLayout" name="gridLayout_10">
+                 <item row="1" column="0">
+                  <widget class="QLabel" name="label_29">
+                   <property name="toolTip">
+                    <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;For MDEventsWorkspace with merged runs&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;p&gt;For example:&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+                   </property>
+                   <property name="text">
+                    <string>Base Workspace Name</string>
+                   </property>
+                  </widget>
+                 </item>
+                 <item row="0" column="0">
+                  <widget class="QLabel" name="label_30">
+                   <property name="text">
+                    <string>Scans List</string>
+                   </property>
+                  </widget>
+                 </item>
+                 <item row="0" column="1">
+                  <widget class="QLineEdit" name="lineEdit_listScansSliceView"/>
+                 </item>
+                 <item row="0" column="2">
+                  <widget class="QPushButton" name="pushButton_addScanSliceView">
+                   <property name="text">
+                    <string>Add</string>
+                   </property>
+                  </widget>
+                 </item>
+                 <item row="1" column="1">
+                  <layout class="QHBoxLayout" name="horizontalLayout">
+                   <item>
+                    <widget class="QLineEdit" name="lineEdit_baseMergeMDName">
+                     <property name="sizePolicy">
+                      <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+                       <horstretch>0</horstretch>
+                       <verstretch>0</verstretch>
+                      </sizepolicy>
+                     </property>
+                    </widget>
+                   </item>
+                   <item>
+                    <widget class="QComboBox" name="comboBox_mergeScanFrame">
+                     <property name="minimumSize">
+                      <size>
+                       <width>140</width>
+                       <height>0</height>
+                      </size>
+                     </property>
+                     <property name="toolTip">
+                      <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Type of frame that the final merged scan will be in.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+                     </property>
+                     <item>
+                      <property name="text">
+                       <string>HKL-Space</string>
+                      </property>
+                     </item>
+                     <item>
+                      <property name="text">
+                       <string>Q-Sample-Space</string>
+                      </property>
+                     </item>
+                    </widget>
+                   </item>
+                   <item>
+                    <spacer name="horizontalSpacer_10">
+                     <property name="orientation">
+                      <enum>Qt::Horizontal</enum>
+                     </property>
+                     <property name="sizeType">
+                      <enum>QSizePolicy::Expanding</enum>
+                     </property>
+                     <property name="sizeHint" stdset="0">
+                      <size>
+                       <width>40</width>
+                       <height>20</height>
+                      </size>
+                     </property>
+                    </spacer>
+                   </item>
+                  </layout>
+                 </item>
+                 <item row="1" column="2">
+                  <widget class="QPushButton" name="pushButton_process4SliceView">
+                   <property name="font">
+                    <font>
+                     <weight>75</weight>
+                     <bold>true</bold>
+                    </font>
+                   </property>
+                   <property name="text">
+                    <string>Process</string>
+                   </property>
+                  </widget>
+                 </item>
+                </layout>
+               </item>
+               <item>
+                <widget class="ProcessTableWidget" name="tableWidget_sliceViewProgress">
+                 <property name="toolTip">
+                  <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;? columns: &lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;p&gt;1. Scan number&lt;/p&gt;&lt;p&gt;2. Number of Pts.&lt;/p&gt;&lt;p&gt;3. Status: &lt;/p&gt;&lt;p&gt;(a) done&lt;/p&gt;&lt;p&gt;(b) error with error message&lt;/p&gt;&lt;p&gt;(c) on-going&lt;/p&gt;&lt;p&gt;(d) empty as not yet&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+                 </property>
+                </widget>
+               </item>
+              </layout>
+             </widget>
+            </item>
+           </layout>
+          </widget>
+          <widget class="QWidget" name="tab_3">
+           <attribute name="title">
+            <string>Refine UB</string>
+           </attribute>
+           <layout class="QGridLayout" name="gridLayout_8">
+            <item row="0" column="0">
+             <layout class="QVBoxLayout" name="verticalLayout_6">
+              <item>
+               <layout class="QHBoxLayout" name="horizontalLayout_14">
+                <item>
+                 <widget class="QLabel" name="label_14">
+                  <property name="text">
+                   <string>Scan</string>
+                  </property>
+                 </widget>
+                </item>
+                <item>
+                 <widget class="QLineEdit" name="lineEdit_scanRefineUB">
+                  <property name="sizePolicy">
+                   <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
+                    <horstretch>0</horstretch>
+                    <verstretch>0</verstretch>
+                   </sizepolicy>
+                  </property>
+                 </widget>
+                </item>
+                <item>
+                 <widget class="QLabel" name="label_13">
+                  <property name="text">
+                   <string>Pt.</string>
+                  </property>
+                 </widget>
+                </item>
+                <item>
+                 <widget class="QLineEdit" name="lineEdit_ptRefineUB">
+                  <property name="sizePolicy">
+                   <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+                    <horstretch>0</horstretch>
+                    <verstretch>0</verstretch>
+                   </sizepolicy>
+                  </property>
+                 </widget>
+                </item>
+                <item>
+                 <widget class="QPushButton" name="pushButton_addToRefine">
+                  <property name="toolTip">
+                   <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Add a data point or data points (defined by scan number and pt number) to the list to refine UB matrix; &lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;p&gt;Scan number can be a list of integers;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;p&gt;Pt number can be empty such that all Pt. of that scan will be searched for peak and then used to refine UB matrix&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+                  </property>
+                  <property name="text">
+                   <string>Add</string>
+                  </property>
+                 </widget>
+                </item>
+                <item>
+                 <spacer name="horizontalSpacer_3">
+                  <property name="orientation">
+                   <enum>Qt::Horizontal</enum>
+                  </property>
+                  <property name="sizeHint" stdset="0">
+                   <size>
+                    <width>40</width>
+                    <height>20</height>
+                   </size>
+                  </property>
+                 </spacer>
+                </item>
+                <item>
+                 <widget class="QPushButton" name="pushButton_addAllRefineUB">
+                  <property name="text">
+                   <string>Add All</string>
+                  </property>
+                 </widget>
+                </item>
+               </layout>
+              </item>
+              <item>
+               <layout class="QHBoxLayout" name="horizontalLayout_15">
+                <item>
+                 <widget class="UBMatrixTable" name="tableWidget_refinedUB">
+                  <row>
+                   <property name="text">
+                    <string/>
+                   </property>
+                  </row>
+                  <row>
+                   <property name="text">
+                    <string/>
+                   </property>
+                  </row>
+                  <row>
+                   <property name="text">
+                    <string/>
+                   </property>
+                  </row>
+                  <column>
+                   <property name="text">
+                    <string/>
+                   </property>
+                  </column>
+                  <column>
+                   <property name="text">
+                    <string/>
+                   </property>
+                  </column>
+                  <column>
+                   <property name="text">
+                    <string/>
+                   </property>
+                  </column>
+                 </widget>
+                </item>
+                <item>
+                 <layout class="QVBoxLayout" name="verticalLayout_7"/>
+                </item>
+                <item>
+                 <layout class="QVBoxLayout" name="verticalLayout_10">
+                  <item>
+                   <widget class="QPushButton" name="pushButton_acceptRefinedUB">
+                    <property name="text">
+                     <string>Accept</string>
+                    </property>
+                   </widget>
+                  </item>
+                  <item>
+                   <widget class="QPushButton" name="pushButton_resetRefinedUB">
+                    <property name="text">
+                     <string>Reset</string>
+                    </property>
+                   </widget>
+                  </item>
+                 </layout>
+                </item>
+               </layout>
+              </item>
+              <item>
+               <layout class="QGridLayout" name="gridLayout_7">
+                <item row="0" column="0">
+                 <widget class="QLabel" name="label_17">
+                  <property name="text">
+                   <string>a</string>
+                  </property>
+                 </widget>
+                </item>
+                <item row="0" column="2">
+                 <widget class="QLabel" name="label_19">
+                  <property name="text">
+                   <string>c</string>
+                  </property>
+                 </widget>
+                </item>
+                <item row="0" column="4">
+                 <widget class="QLabel" name="label_21">
+                  <property name="text">
+                   <string>beta</string>
+                  </property>
+                 </widget>
+                </item>
+                <item row="0" column="1">
+                 <widget class="QLabel" name="label_18">
+                  <property name="text">
+                   <string>b</string>
+                  </property>
+                 </widget>
+                </item>
+                <item row="0" column="3">
+                 <widget class="QLabel" name="label_20">
+                  <property name="text">
+                   <string>alpha</string>
+                  </property>
+                 </widget>
+                </item>
+                <item row="0" column="5">
+                 <widget class="QLabel" name="label_22">
+                  <property name="text">
+                   <string>gamma</string>
+                  </property>
+                 </widget>
+                </item>
+                <item row="1" column="1">
+                 <widget class="QLineEdit" name="lineEdit_bUnitCell"/>
+                </item>
+                <item row="1" column="2">
+                 <widget class="QLineEdit" name="lineEdit_cUnitCell"/>
+                </item>
+                <item row="1" column="3">
+                 <widget class="QLineEdit" name="lineEdit_alphaUnitCell"/>
+                </item>
+                <item row="2" column="1">
+                 <widget class="QLineEdit" name="lineEdit_bError"/>
+                </item>
+                <item row="1" column="4">
+                 <widget class="QLineEdit" name="lineEdit_betaUnitCell"/>
+                </item>
+                <item row="1" column="0">
+                 <widget class="QLineEdit" name="lineEdit_aUnitCell"/>
+                </item>
+                <item row="2" column="2">
+                 <widget class="QLineEdit" name="lineEdit_cError"/>
+                </item>
+                <item row="2" column="0">
+                 <widget class="QLineEdit" name="lineEdit_aError"/>
+                </item>
+                <item row="2" column="3">
+                 <widget class="QLineEdit" name="lineEdit_alphaError"/>
+                </item>
+                <item row="2" column="4">
+                 <widget class="QLineEdit" name="lineEdit_betaError"/>
+                </item>
+                <item row="1" column="5">
+                 <widget class="QLineEdit" name="lineEdit_gammaUnitCell"/>
+                </item>
+                <item row="2" column="5">
+                 <widget class="QLineEdit" name="lineEdit_gammaError"/>
+                </item>
+               </layout>
+              </item>
+             </layout>
+            </item>
+            <item row="1" column="0">
+             <spacer name="verticalSpacer_3">
+              <property name="orientation">
+               <enum>Qt::Vertical</enum>
+              </property>
+              <property name="sizeHint" stdset="0">
+               <size>
+                <width>20</width>
+                <height>40</height>
+               </size>
+              </property>
+             </spacer>
+            </item>
+           </layout>
+          </widget>
+          <widget class="QWidget" name="tab_indexPeak">
+           <attribute name="title">
+            <string>Peak Integration</string>
+           </attribute>
+           <layout class="QVBoxLayout" name="verticalLayout_11">
+            <item>
+             <layout class="QGridLayout" name="gridLayout_13">
+              <item row="1" column="6">
+               <widget class="QCheckBox" name="checkBox_adaptQBkgd">
+                <property name="text">
+                 <string>Adaptive Q Background</string>
+                </property>
+               </widget>
+              </item>
+              <item row="0" column="1">
+               <widget class="QLineEdit" name="lineEdit_scanIntegratePeak">
+                <property name="sizePolicy">
+                 <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+                  <horstretch>0</horstretch>
+                  <verstretch>0</verstretch>
+                 </sizepolicy>
+                </property>
+               </widget>
+              </item>
+              <item row="2" column="0">
+               <widget class="QCheckBox" name="checkBox_cylinder">
+                <property name="text">
+                 <string>Cylinder</string>
+                </property>
+               </widget>
+              </item>
+              <item row="1" column="3">
+               <widget class="QLineEdit" name="lineEdit_bkgdInnerR"/>
+              </item>
+              <item row="1" column="5">
+               <widget class="QLineEdit" name="lineEdit_bkgdOuterR"/>
+              </item>
+              <item row="2" column="4">
+               <widget class="QLabel" name="label_36">
+                <property name="text">
+                 <string>Percent Background</string>
+                </property>
+               </widget>
+              </item>
+              <item row="1" column="7">
+               <widget class="QCheckBox" name="checkBox_integrateOnEdge">
+                <property name="text">
+                 <string>Integrate on Edge</string>
+                </property>
+               </widget>
+              </item>
+              <item row="0" column="0">
+               <widget class="QLabel" name="label_5">
+                <property name="text">
+                 <string>Scan Number</string>
+                </property>
+               </widget>
+              </item>
+              <item row="1" column="0">
+               <widget class="QLabel" name="label_34">
+                <property name="text">
+                 <string>Peak Radius</string>
+                </property>
+               </widget>
+              </item>
+              <item row="0" column="3">
+               <widget class="QLineEdit" name="lineEdit_ptNumListIntPeak"/>
+              </item>
+              <item row="2" column="7">
+               <widget class="QComboBox" name="comboBox_cylinderIntOption"/>
+              </item>
+              <item row="0" column="7">
+               <widget class="QPushButton" name="pushButton_integratePeak">
+                <property name="text">
+                 <string>Integrate Peaks</string>
+                </property>
+               </widget>
+              </item>
+              <item row="2" column="5">
+               <widget class="QLineEdit" name="lineEdit_cylinderBkgdPercent"/>
+              </item>
+              <item row="1" column="4">
+               <widget class="QLabel" name="label_35">
+                <property name="text">
+                 <string>Background Outer Radius</string>
+                </property>
+               </widget>
+              </item>
+              <item row="0" column="5">
+               <widget class="QComboBox" name="comboBox_3">
+                <property name="toolTip">
+                 <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Choose the name of the tab, in which the UB matrix is used to convert signals to HKL frame.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+                </property>
+                <item>
+                 <property name="text">
+                  <string>Calculate UB</string>
+                 </property>
+                </item>
+                <item>
+                 <property name="text">
+                  <string>Merge Scan</string>
+                 </property>
+                </item>
+                <item>
+                 <property name="text">
+                  <string>Refine UB</string>
+                 </property>
+                </item>
+               </widget>
+              </item>
+              <item row="2" column="6">
+               <widget class="QComboBox" name="comboBox_cylinderProfile">
+                <item>
+                 <property name="text">
+                  <string>Gaussian</string>
+                 </property>
+                </item>
+               </widget>
+              </item>
+              <item row="2" column="2">
+               <widget class="QLabel" name="label_39">
+                <property name="text">
+                 <string>Cylinder Length</string>
+                </property>
+               </widget>
+              </item>
+              <item row="1" column="2">
+               <widget class="QLabel" name="label_37">
+                <property name="text">
+                 <string>Background Inner Radius</string>
+                </property>
+               </widget>
+              </item>
+              <item row="2" column="3">
+               <widget class="QLineEdit" name="lineEdit_cylinderLength"/>
+              </item>
+              <item row="0" column="2">
+               <widget class="QLabel" name="label_33">
+                <property name="text">
+                 <string>Pt Numbers</string>
+                </property>
+               </widget>
+              </item>
+              <item row="1" column="1">
+               <widget class="QLineEdit" name="lineEdit_peakRadius"/>
+              </item>
+             </layout>
+            </item>
+            <item>
+             <widget class="IntegratePeaksTableWidget" name="tableWidget_peakIndex"/>
+            </item>
+           </layout>
+          </widget>
+         </widget>
+        </item>
+       </layout>
+      </item>
+     </layout>
+    </item>
+   </layout>
+  </widget>
+  <widget class="QMenuBar" name="menubar">
+   <property name="geometry">
+    <rect>
+     <x>0</x>
+     <y>0</y>
+     <width>1292</width>
+     <height>25</height>
+    </rect>
+   </property>
+   <widget class="QMenu" name="menuFile">
+    <property name="title">
+     <string>File</string>
+    </property>
+    <addaction name="separator"/>
+    <addaction name="actionExit"/>
+    <addaction name="separator"/>
+   </widget>
+   <widget class="QMenu" name="menuTools">
+    <property name="title">
+     <string>Tools</string>
+    </property>
+    <addaction name="actionSave_Session"/>
+    <addaction name="actionLoad_Session"/>
+    <addaction name="separator"/>
+   </widget>
+   <addaction name="menuFile"/>
+   <addaction name="menuTools"/>
+  </widget>
+  <widget class="QStatusBar" name="statusbar"/>
+  <action name="actionNew">
+   <property name="text">
+    <string>New</string>
+   </property>
+   <property name="shortcut">
+    <string>Ctrl+N</string>
+   </property>
+  </action>
+  <action name="actionOpen">
+   <property name="text">
+    <string>Open</string>
+   </property>
+   <property name="shortcut">
+    <string>Ctrl+O</string>
+   </property>
+  </action>
+  <action name="actionSave">
+   <property name="text">
+    <string>Save</string>
+   </property>
+  </action>
+  <action name="actionLog">
+   <property name="text">
+    <string>Log</string>
+   </property>
+   <property name="shortcut">
+    <string>Ctrl+L</string>
+   </property>
+  </action>
+  <action name="actionSave_Session">
+   <property name="text">
+    <string>Save Session</string>
+   </property>
+   <property name="shortcut">
+    <string>Ctrl+Shift+S</string>
+   </property>
+  </action>
+  <action name="actionExit">
+   <property name="text">
+    <string>Exit</string>
+   </property>
+   <property name="shortcut">
+    <string>Ctrl+Q</string>
+   </property>
+  </action>
+  <action name="actionLoad_Session">
+   <property name="text">
+    <string>Load Session</string>
+   </property>
+   <property name="shortcut">
+    <string>Ctrl+Shift+L</string>
+   </property>
+  </action>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>MplGraphicsView</class>
+   <extends>QGraphicsView</extends>
+   <header>mplgraphicsview.h</header>
+  </customwidget>
+  <customwidget>
+   <class>UBMatrixPeakTable</class>
+   <extends>QTableWidget</extends>
+   <header>hfctables.h</header>
+  </customwidget>
+  <customwidget>
+   <class>UBMatrixTable</class>
+   <extends>QTableWidget</extends>
+   <header>hfctables.h</header>
+  </customwidget>
+  <customwidget>
+   <class>ProcessTableWidget</class>
+   <extends>QTableWidget</extends>
+   <header>hfctables.h</header>
+  </customwidget>
+  <customwidget>
+   <class>IntegratePeaksTableWidget</class>
+   <extends>QTableWidget</extends>
+   <header>hfctables.h</header>
+  </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/scripts/HFIR_4Circle_Reduction/NTableWidget.py b/scripts/HFIR_4Circle_Reduction/NTableWidget.py
new file mode 100644
index 0000000000000000000000000000000000000000..198725f41ef1492b822dfddb572ecb7c75b0a3aa
--- /dev/null
+++ b/scripts/HFIR_4Circle_Reduction/NTableWidget.py
@@ -0,0 +1,268 @@
+#pylint: disable=C0103,R0904
+# N(DAV)TableWidget
+#
+
+from PyQt4 import QtGui, QtCore
+
+try:
+    _fromUtf8 = QtCore.QString.fromUtf8
+except AttributeError:
+    _fromUtf8 = lambda s: s
+
+
+class NTableWidget(QtGui.QTableWidget):
+    """
+    NdavTableWidget inherits from QTableWidget by extending the features
+    for easy application.
+    """
+    def __init__(self, parent):
+        """
+
+        :param parent:
+        :return:
+        """
+        QtGui.QTableWidget.__init__(self, parent)
+
+        self._myParent = parent
+
+        self._myHeaderList = None
+        self._myColumnTypeList = None
+
+        return
+
+    def append_row(self, row_value_list, type_list=None):
+        """
+
+        :param row_value_list:
+        :return:
+        """
+        # Check input
+        assert isinstance(row_value_list, list)
+        if type_list is not None:
+            assert isinstance(type_list, list)
+            assert len(row_value_list) == len(type_list)
+        else:
+            type_list = self._myColumnTypeList
+        if len(row_value_list) != self.columnCount():
+            ret_msg = 'Input number of values (%d) is different from ' \
+                      'column number (%d).' % (len(row_value_list), self.columnCount())
+            return False, ret_msg
+        else:
+            ret_msg = ''
+
+        # Insert new row
+        row_number = self.rowCount()
+        self.insertRow(row_number)
+
+        # Set values
+        for i_col in xrange(min(len(row_value_list), self.columnCount())):
+            item = QtGui.QTableWidgetItem()
+            item.setText(_fromUtf8(str(row_value_list[i_col])))
+            item.setFlags(item.flags() & ~QtCore.Qt.ItemIsEditable)
+            if type_list[i_col] == 'checkbox':
+                self.set_check_box(row_number, i_col, False)
+            else:
+                self.setItem(row_number, i_col, item)
+        # END-FOR(i_col)
+
+        return True, ret_msg
+
+    def delete_rows(self, row_number_list):
+        """ Delete rows
+        :param row_number_list:
+        :return:
+        """
+        # Check and re-order row numbers
+        assert isinstance(row_number_list, list)
+        row_number_list.sort(reverse=True)
+
+        for row_number in row_number_list:
+            self.removeRow(row_number)
+
+        return
+
+    def get_selected_rows(self):
+        """
+
+        :return: list of row numbers that are selected
+        """
+        rows_list = list()
+        index_status = self._myColumnTypeList.index('checkbox')
+        for i_row in xrange(self.rowCount()):
+            is_checked = self.get_row_value(i_row)[index_status]
+            if is_checked:
+                rows_list.append(i_row)
+
+        return rows_list
+
+    def get_cell_value(self, row_index, col_index):
+        """
+
+        :param row_index:
+        :param col_index:
+        :return:
+        """
+        c_type = self._myColumnTypeList[col_index]
+
+        return_value = None
+        if c_type == 'checkbox':
+            # Check box
+            cell_i_j = self.cellWidget(row_index, col_index)
+            assert isinstance(cell_i_j, QtGui.QCheckBox)
+            return_value = cell_i_j.isChecked()
+        else:
+            # Regular cell
+            item_i_j = self.item(row_index, col_index)
+            assert isinstance(item_i_j, QtGui.QTableWidgetItem)
+            value = str(item_i_j.text())
+            if c_type == 'int':
+                return_value = int(value)
+            elif c_type == 'float':
+                return_value = float(value)
+
+        return return_value
+
+    def get_row_value(self, row_index):
+        """
+        :param row_index:
+        :return: list of objects
+        """
+        if row_index < 0 or row_index >= self.rowCount():
+            raise IndexError('Index of row (%d) is out of range.' % row_index)
+
+        ret_list = list()
+        for i_col in xrange(len(self._myColumnTypeList)):
+            c_type = self._myColumnTypeList[i_col]
+
+            if c_type == 'checkbox':
+                # Check box
+                cell_i_j = self.cellWidget(row_index, i_col)
+                assert isinstance(cell_i_j, QtGui.QCheckBox)
+                is_checked = cell_i_j.isChecked()
+                ret_list.append(is_checked)
+            else:
+                # Regular cell
+                item_i_j = self.item(row_index, i_col)
+                assert isinstance(item_i_j, QtGui.QTableWidgetItem)
+                value = str(item_i_j.text()).strip()
+                if len(value) > 0:
+                    if c_type == 'int':
+                        value = int(value)
+                    elif c_type == 'float':
+                        value = float(value)
+                else:
+                    value = None
+
+                ret_list.append(value)
+            # END-IF-ELSE
+        # END-FOR
+
+        return ret_list
+
+    def init_setup(self, column_tup_list):
+        """ Initial setup
+        :param column_tup_list: list of 2-tuple as string (column name) and string (data type)
+        :return:
+        """
+        # Define column headings
+        num_cols = len(column_tup_list)
+
+        # Class variables
+        self._myHeaderList = list()
+        self._myColumnTypeList = list()
+
+        for c_tup in column_tup_list:
+            c_name = c_tup[0]
+            c_type = c_tup[1]
+            self._myHeaderList.append(c_name)
+            self._myColumnTypeList.append(c_type)
+
+        self.setColumnCount(num_cols)
+        self.setHorizontalHeaderLabels(self._myHeaderList)
+
+        return
+
+    def init_size(self, num_rows, num_cols):
+        """
+
+        :return:
+        """
+        self.setColumnCount(num_cols)
+        self.setRowCount(num_rows)
+
+        return
+
+    def set_check_box(self, row, col, state):
+        """ function to add a new select checkbox to a cell in a table row
+        won't add a new checkbox if one already exists
+        """
+        # Check input
+        assert isinstance(state, bool)
+
+        # Check if cellWidget exists
+        if self.cellWidget(row,col):
+            # existing: just set the value
+            self.cellWidget(row, col).setChecked(state)
+        else:
+            # case to add checkbox
+            checkbox = QtGui.QCheckBox()
+            checkbox.setText('')
+            checkbox.setChecked(state)
+
+            # Adding a widget which will be inserted into the table cell
+            # then centering the checkbox within this widget which in turn,
+            # centers it within the table column :-)
+            self.setCellWidget(row, col, checkbox)
+        # END-IF-ELSE
+
+        return
+
+    def set_value_cell(self, row, col, value=''):
+        """
+        Set value to a cell with integer, float or string
+        :param row:
+        :param col:
+        :param value:
+        :return:
+        """
+        # Check
+        if row < 0 or row >= self.rowCount() or col < 0 or col >= self.columnCount():
+            raise IndexError('Input row number or column number is out of range.')
+
+        # Init cell
+        cell_item = QtGui.QTableWidgetItem()
+        cell_item.setText(_fromUtf8(str(value)))
+        cell_item.setFlags(cell_item.flags() & ~QtCore.Qt.ItemIsEditable)
+
+        self.setItem(row, col, cell_item)
+
+        return
+
+    def update_cell_value(self, row, col, value):
+        """
+
+        :param row:
+        :param col:
+        :param value:
+        :return:
+        """
+        cell_item = self.item(row, col)
+        cell_widget = self.cellWidget(row, col)
+
+        if cell_item is not None and cell_widget is None:
+            # TableWidgetItem
+            assert isinstance(cell_item, QtGui.QTableWidgetItem)
+            if isinstance(value, float):
+                cell_item.setText(_fromUtf8('%.7f' % value))
+            else:
+                cell_item.setText(_fromUtf8(str(value)))
+        elif cell_item is None and cell_widget is not None:
+            # TableCellWidget
+            if isinstance(cell_item, QtGui.QCheckBox) is True:
+                cell_item.setChecked(value)
+            else:
+                raise TypeError('Cell of type %s is not supported.' % str(type(cell_item)))
+        else:
+            raise TypeError('Table cell (%d, %d) is in an unsupported situation!' % (row, col))
+
+        return
diff --git a/scripts/HFIR_4Circle_Reduction/__init__.py b/scripts/HFIR_4Circle_Reduction/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..04a95e8315757618d54dc05da33da722b0774d94
--- /dev/null
+++ b/scripts/HFIR_4Circle_Reduction/__init__.py
@@ -0,0 +1,2 @@
+#pylint: disable=invalid-name
+#pylint: disable=invalid-name
diff --git a/scripts/HFIR_4Circle_Reduction/fourcircle_utility.py b/scripts/HFIR_4Circle_Reduction/fourcircle_utility.py
new file mode 100644
index 0000000000000000000000000000000000000000..35dc1fe387e6bd1597eed0a9eb6c52f8c08811f8
--- /dev/null
+++ b/scripts/HFIR_4Circle_Reduction/fourcircle_utility.py
@@ -0,0 +1,188 @@
+#pylint: disable=W0633,too-many-branches
+__author__ = 'wzz'
+
+import os
+import urllib2
+import socket
+
+
+def check_url(url, read_lines=False):
+    """ Check whether a URL is valid
+    :param url:
+    :return: boolean, error message
+    """
+    lines = None
+    try:
+        # Access URL
+        url_stream = urllib2.urlopen(url, timeout=2)
+
+        # Read lines
+        if read_lines is True:
+            lines = url_stream.readlines()
+    except urllib2.URLError as url_error:
+        url_stream = url_error
+    except socket.timeout:
+        return False, 'Time out. Try again!'
+
+    # Return result
+    if url_stream.code in (200, 401):
+        url_good = True
+    else:
+        url_good = False
+
+    # Close connect
+    url_stream.close()
+
+    # Return
+    if read_lines is True:
+        return url_good, lines
+    if url_good is False:
+        error_message = 'Unable to access %s.  Check internet access. Code %d' % (url, url_stream.code)
+    else:
+        error_message = ''
+
+    return url_good, error_message
+
+
+def get_scans_list(server_url, exp_no, return_list=False):
+    """ Get list of scans under one experiment
+    :param server_url:
+    :param exp_no:
+    :return: message
+    """
+    if server_url.endswith('/') is False:
+        server_url = '%s/' % server_url
+    data_dir_url = '%sexp%d/Datafiles' % (server_url, exp_no)
+
+    does_exist, raw_lines = check_url(data_dir_url, read_lines=True)
+    if does_exist is False:
+        return "Experiment %d's URL %s cannot be found." % (exp_no, data_dir_url)
+
+    # Scan through the index page
+    scan_list = []
+    header = 'HB3A_exp%04d_scan' % exp_no
+    for line in raw_lines:
+        if line.count(header) > 0:
+            # try to find file HB3A_exp0123_scan6789.dat
+            term = line.split(header)[1].split('.dat')[0]
+            scan = int(term)
+            # check
+            if '%04d' % scan == term:
+                scan_list.append(scan)
+    # END_FOR
+    scan_list = sorted(scan_list)
+    if return_list is True:
+        return scan_list
+
+    message = 'Experiment %d: Scan from %d to %d' % (exp_no, scan_list[0], scan_list[-1])
+
+    return message
+
+
+def get_scans_list_local_disk(local_dir, exp_no):
+    """ Get scans from a specified directory on local disk
+    :param local_dir:
+    :param exp_no:
+    :return:
+    """
+    scan_list = []
+
+    file_names = os.listdir(local_dir)
+    header = 'HB3A_exp%04d_scan' % exp_no
+    for name in file_names:
+        if name.count(header) > 0:
+            scan = int(name.split(header)[1].split('.dat')[0])
+            scan_list.append(scan)
+
+    scan_list = sorted(scan_list)
+
+    if len(scan_list) == 0:
+        message = 'Experiment %d: No scan can be found.' % exp_no
+    else:
+        message = 'Experiment %d: Scan from %d to %d ' % (exp_no, scan_list[0], scan_list[-1])
+        num_skip_scans = scan_list[-1] - scan_list[0] + 1 - len(scan_list)
+        if num_skip_scans > 0:
+            message += 'with %d ' % num_skip_scans
+        else:
+            message += 'without '
+        message += 'missing scans.'
+
+    return message
+
+
+def parse_int_array(int_array_str):
+    """ Validate whether the string can be divided into integer strings.
+    Allowed: a, b, c-d, e, f
+    :param int_array_str:
+    :return:
+    """
+    int_array_str = str(int_array_str)
+    if int_array_str == "":
+        return True, []
+
+    # Split by ","
+    term_level_0 = int_array_str.split(",")
+    integer_list = []
+
+    # For each term
+    err_msg = ""
+    ret_status = True
+
+    for level0_term in term_level_0:
+        level0_term = level0_term.strip()
+
+        # split upon dash -
+        num_dashes = level0_term.count("-")
+        if num_dashes == 0:
+            # one integer
+            value_str = level0_term
+            try:
+                int_value = int(value_str)
+                if str(int_value) != value_str:
+                    ret_status = False
+                    err_msg =  "Contains non-integer string %s." % value_str
+            except ValueError:
+                ret_status = False
+                err_msg = "String %s is not an integer." % (value_str)
+            else:
+                integer_list.append(int_value)
+
+        elif num_dashes == 1:
+            # Integer range
+            two_terms = level0_term.split("-")
+            temp_list = []
+            for i in xrange(2):
+                value_str = two_terms[i]
+                try:
+                    int_value = int(value_str)
+                    if str(int_value) != value_str:
+                        ret_status = False
+                        err_msg = "Contains non-integer string %s." % (value_str)
+                except ValueError:
+                    ret_status = False
+                    err_msg = "String %s is not an integer." % (value_str)
+                else:
+                    temp_list.append(int_value)
+
+                # break loop
+                if ret_status is False:
+                    break
+            # END_FOR(i)
+            integer_list.extend(range(temp_list[0], temp_list[1]+1))
+
+        else:
+            # Undefined situation
+            ret_status = False
+            err_msg = "Term %s contains more than 1 dash." % level0_term
+        # END-IF-ELSE
+
+        # break loop if something is wrong
+        if ret_status is False:
+            break
+    # END-FOR(level0_term)
+
+    # Return with false
+    if ret_status is False:
+        return False, err_msg
+
+    return True, integer_list
diff --git a/scripts/HFIR_4Circle_Reduction/guiutility.py b/scripts/HFIR_4Circle_Reduction/guiutility.py
new file mode 100644
index 0000000000000000000000000000000000000000..79237a5729470b372017478b24a0564159d67fb1
--- /dev/null
+++ b/scripts/HFIR_4Circle_Reduction/guiutility.py
@@ -0,0 +1,164 @@
+#
+# GUI Utility Methods
+#
+from PyQt4 import QtGui
+
+
+def parse_float_array(array_str):
+    """ Parse a string to an array of float
+    :param array_str:
+    :return: boolean, list of floats/error message
+    """
+    print array_str
+    assert isinstance(array_str, str)
+    array_str = array_str.replace(',', ' ')
+    array_str = array_str.replace('\n', ' ')
+    array_str = array_str.replace('\t ', ' ')
+    array_str = array_str.strip()
+    print '[DB] After processing: ', array_str
+
+    float_str_list = array_str.split()
+    float_list = list()
+    for float_str in float_str_list:
+        try:
+            value = float(float_str)
+        except ValueError as value_error:
+            return False, 'Unable to parse %s due to %s.' % (float_str, str(value_error))
+        else:
+            float_list.append(value)
+    # END-FOR
+
+    return True, float_list
+
+
+def parse_integer_list(array_str):
+    """ Parse a string to an array of integer separated by ','
+    also, the format as 'a-b' is supported too
+    :param array_str:
+    :return: boolean, list of floats/error message
+    """
+    assert isinstance(array_str, str)
+    array_str = array_str.replace(' ', '')
+    array_str = array_str.replace('\n', '')
+    array_str = array_str.replace('\t ', '')
+
+    int_str_list = array_str.split(',')
+    integer_list = list()
+    for int_str in int_str_list:
+
+        try:
+            int_value = int(int_str)
+            integer_list.append(int_value)
+        except ValueError:
+            num_dash = int_str.count('-')
+            if num_dash == 1:
+                terms = int_str.split('-')
+                try:
+                    start_value = int(terms[0])
+                    end_value = int(terms[1])
+                except ValueError:
+                    raise RuntimeError('Unable to parse %s due to value error' % int_str)
+            elif num_dash == 2 and int_str.startswith('-'):
+                terms = int_str[1:].split('-')
+                try:
+                    start_value = int(terms[0])*-1
+                    end_value = int(terms[1])
+                except ValueError:
+                    raise RuntimeError('Unable to parse %s due to value error' % int_str)
+            elif num_dash == 3:
+                terms = int_str.split('-')
+                try:
+                    start_value = -1*int(terms[1])
+                    end_value = -1*int(terms[3])
+                except ValueError:
+                    raise RuntimeError('Unable to parse %s due to value error' % int_str)
+                except IndexError:
+                    raise RuntimeError('Unable to parse %s due to value error' % int_str)
+            else:
+                raise RuntimeError('Unable to parse %s due to value error' % int_str)
+
+            integer_list.extend(xrange(start_value, end_value+1))
+    # END-FOR
+
+    return integer_list
+
+
+def parse_float_editors(line_edits):
+    """
+    :param line_edits:
+    :return: (True, list of floats); (False, error message)
+    """
+    # Set flag
+    return_single_value = False
+
+    if isinstance(line_edits, QtGui.QLineEdit) is True:
+        line_edit_list = [line_edits]
+        return_single_value = True
+    elif isinstance(line_edits, list) is True:
+        line_edit_list = line_edits
+    else:
+        raise RuntimeError('Input is not LineEdit or list of LineEdit.')
+
+    error_message = ''
+    float_list = []
+
+    for line_edit in line_edit_list:
+        assert isinstance(line_edit, QtGui.QLineEdit)
+        try:
+            str_value = str(line_edit.text()).strip()
+            float_value = float(str_value)
+        except ValueError as value_err:
+            error_message += 'Unable to parse to integer. %s\n' % (str(value_err))
+        else:
+            float_list.append(float_value)
+        # END-TRY
+    # END-FOR
+
+    if len(error_message) > 0:
+        return False, error_message
+    elif return_single_value is True:
+        return True, float_list[0]
+
+    return True, float_list
+
+
+def parse_integers_editors(line_edits):
+    """
+    :param line_edits:
+    :return: (True, list of integers); (False, error message)
+    """
+    # Set flag
+    return_single_value = False
+
+    if isinstance(line_edits, QtGui.QLineEdit) is True:
+        line_edit_list = [line_edits]
+        return_single_value = True
+    elif isinstance(line_edits, list) is True:
+        line_edit_list = line_edits
+    else:
+        raise RuntimeError('Input is not LineEdit or list of LineEdit.')
+
+    error_message = ''
+    integer_list = []
+
+    for line_edit in line_edit_list:
+        assert isinstance(line_edit, QtGui.QLineEdit)
+        try:
+            str_value = str(line_edit.text()).strip()
+            int_value = int(str_value)
+        except ValueError as value_err:
+            error_message += 'Unable to parse to integer. %s\n' % (str(value_err))
+        else:
+            if str_value != '%d' % int_value:
+                error_message += 'Value %s is not a proper integer.\n' % str_value
+            else:
+                integer_list.append(int_value)
+        # END-TRY
+    # END-FOR
+
+    if len(error_message) > 0:
+        return False, error_message
+    elif return_single_value is True:
+        return True, integer_list[0]
+
+    return True, integer_list
diff --git a/scripts/HFIR_4Circle_Reduction/hfctables.py b/scripts/HFIR_4Circle_Reduction/hfctables.py
new file mode 100644
index 0000000000000000000000000000000000000000..dba8cb64a3aefb4adff82b540655251d9fe41311
--- /dev/null
+++ b/scripts/HFIR_4Circle_Reduction/hfctables.py
@@ -0,0 +1,385 @@
+#pylint: disable=W0403,C0103,R0901,R0904
+import numpy
+import NTableWidget as tableBase
+
+# UB peak information table
+Peak_Integration_Table_Setup = [('Scan', 'int'),
+                                ('Pt', 'int'),
+                                ('H', 'float'),
+                                ('K', 'float'),
+                                ('L', 'float'),
+                                ('Q_x', 'float'),
+                                ('Q_y', 'float'),
+                                ('Q_z', 'float'),
+                                ('Intensity', 'float')]
+
+
+class IntegratePeaksTableWidget(tableBase.NTableWidget):
+    """
+    Extended table widget for peak integration
+    """
+    def __init__(self, parent):
+        """
+        :param parent:
+        """
+        tableBase.NTableWidget.__init__(self, parent)
+
+        return
+
+    def setup(self):
+        """
+        Init setup
+        :return:
+        """
+        self.init_setup(Peak_Integration_Table_Setup)
+
+        return
+
+
+class UBMatrixTable(tableBase.NTableWidget):
+    """
+    Extended table for UB matrix
+    """
+    def __init__(self, parent):
+        """
+
+        :param parent:
+        :return:
+        """
+        tableBase.NTableWidget.__init__(self, parent)
+
+        # Matrix
+        self._matrix = numpy.ndarray((3, 3), float)
+        for i in xrange(3):
+            for j in xrange(3):
+                self._matrix[i][j] = 0.
+
+        return
+
+    def _set_to_table(self):
+        """
+        Set values in holder '_matrix' to TableWidget
+        :return:
+        """
+        for i_row in xrange(3):
+            for j_col in xrange(3):
+                self.update_cell_value(i_row, j_col, self._matrix[i_row][j_col])
+
+        return
+
+    def get_matrix(self):
+        """
+        Get the copy of the matrix
+        :return:
+        """
+        # print '[DB] MatrixTable: _Matrix = ', self._matrix
+        return self._matrix.copy()
+
+    def set_from_list(self, element_array):
+        """
+        Set table value including holder and QTable from a 1D numpy array
+        :param element_array:
+        :return:
+        """
+        # Check
+        assert isinstance(element_array, list)
+        assert len(element_array) == 9
+
+        # Set value
+        i_array = 0
+        for i in xrange(3):
+            for j in xrange(3):
+                self._matrix[i][j] = element_array[i_array]
+                i_array += 1
+
+        # Set to table
+        self._set_to_table()
+
+        return
+
+    def set_from_matrix(self, matrix):
+        """
+        Set value to both holder and QTable from a numpy 3 x 3 matrix
+        :param matrix:
+        :return:
+        """
+        # Check
+        assert isinstance(matrix, numpy.ndarray)
+        assert matrix.shape == (3, 3)
+
+        for i in xrange(3):
+            for j in xrange(3):
+                self._matrix[i][j] = matrix[i][j]
+
+        self._set_to_table()
+
+        return
+
+    def setup(self):
+        """
+        Init setup
+        :return:
+        """
+        # self.init_size(3, 3)
+
+        for i in xrange(3):
+            for j in xrange(3):
+                self.set_value_cell(i, j)
+
+        self._set_to_table()
+
+        return
+
+
+# UB peak information table
+UB_Peak_Table_Setup = [('Scan', 'int'),
+                       ('Pt', 'int'),
+                       ('H', 'float'),
+                       ('K', 'float'),
+                       ('L', 'float'),
+                       ('Q_x', 'float'),
+                       ('Q_y', 'float'),
+                       ('Q_z', 'float'),
+                       ('Selected', 'checkbox'),
+                       ('m1', 'float'),
+                       ('Error', 'float')]
+
+
+class UBMatrixPeakTable(tableBase.NTableWidget):
+    """
+    Extended table for peaks used to calculate UB matrix
+    """
+    def __init__(self, parent):
+        """
+
+        :param parent:
+        :return:
+        """
+        tableBase.NTableWidget.__init__(self, parent)
+
+        return
+
+    def get_exp_info(self, row_index):
+        """
+        Get experiment information from a row
+        :return: scan number, pt number
+        """
+        assert isinstance(row_index, int)
+
+        scan_number = self.get_cell_value(row_index, 0)
+        assert isinstance(scan_number, int)
+        pt_number = self.get_cell_value(row_index, 1)
+        assert isinstance(pt_number, int)
+
+        return scan_number, pt_number
+
+    def get_hkl(self, row_index):
+        """
+        Get reflection's miller index
+        :param row_index:
+        :return:
+        """
+        assert isinstance(row_index, int)
+
+        m_h = self.get_cell_value(row_index, 2)
+        m_k = self.get_cell_value(row_index, 3)
+        m_l = self.get_cell_value(row_index, 4)
+
+        assert isinstance(m_h, float)
+        assert isinstance(m_k, float)
+        assert isinstance(m_l, float)
+
+        return m_h, m_k, m_l
+
+    def get_scan_pt(self, row_number):
+        """
+        Get Scan and Pt from a row
+        :param row_number:
+        :return:
+        """
+        scan_number = self.get_cell_value(row_number, 0)
+        pt_number = self.get_cell_value(row_number, 1)
+
+        return scan_number, pt_number
+
+    def is_selected(self, row_index):
+        """
+
+        :return:
+        """
+        if row_index < 0 or row_index >= self.rowCount():
+            raise IndexError('Input row number %d is out of range [0, %d)' % (row_index, self.rowCount()))
+
+        col_index = UB_Peak_Table_Setup.index(('Selected', 'checkbox'))
+
+        return self.get_cell_value(row_index, col_index)
+
+    def setup(self):
+        """
+        Init setup
+        :return:
+        """
+        self.init_setup(UB_Peak_Table_Setup)
+
+        return
+
+    def set_hkl(self, i_row, hkl, error=None):
+        """
+        Set HKL to table
+        :param irow:
+        :param hkl:
+        """
+        # Check
+        assert isinstance(i_row, int)
+        assert isinstance(hkl, list)
+
+        i_col_h = UB_Peak_Table_Setup.index(('H', 'float'))
+        i_col_k = UB_Peak_Table_Setup.index(('K', 'float'))
+        i_col_l = UB_Peak_Table_Setup.index(('L', 'float'))
+
+        self.update_cell_value(i_row, i_col_h, hkl[0])
+        self.update_cell_value(i_row, i_col_k, hkl[1])
+        self.update_cell_value(i_row, i_col_l, hkl[2])
+
+        if error is not None:
+            i_col_error = UB_Peak_Table_Setup.index(('Error', 'float'))
+            self.update_cell_value(i_row, i_col_error, error)
+
+        return
+
+    def update_hkl(self, i_row, h, k, l):
+        """ Update HKL value
+        """
+        self.update_cell_value(i_row, 2, h)
+        self.update_cell_value(i_row, 3, k)
+        self.update_cell_value(i_row, 4, l)
+
+        return
+
+
+# Processing status table
+Process_Table_Setup = [('Scan', 'int'),
+                       ('Number Pt', 'int'),
+                       ('Status', 'str'),
+                       ('Merged Workspace', 'str'),
+                       ('Group Name', 'str'),
+                       ('Select', 'checkbox')]
+
+
+class ProcessTableWidget(tableBase.NTableWidget):
+    """
+    Extended table for peaks used to calculate UB matrix
+    """
+    def __init__(self, parent):
+        """
+
+        :param parent:
+        :return:
+        """
+        tableBase.NTableWidget.__init__(self, parent)
+
+        return
+
+    def append_scans(self, scans):
+        """ Append rows
+        :param scans:
+        :return:
+        """
+        # Check
+        assert isinstance(scans, list)
+
+        # Append rows
+        for scan in scans:
+            row_value_list = [scan, 0, 'In Queue', '', '', False]
+            status, err = self.append_row(row_value_list)
+            if status is False:
+                raise RuntimeError(err)
+
+        return
+
+    def setup(self):
+        """
+        Init setup
+        :return:
+        """
+        self.init_setup(Process_Table_Setup)
+
+        return
+
+    def set_scan_pt(self, scan_no, pt_list):
+        """
+        :param scan_no:
+        :param pt_list:
+        :return:
+        """
+        # Check
+        assert isinstance(scan_no, int)
+
+        num_rows = self.rowCount()
+        set_done = False
+        for i_row in xrange(num_rows):
+            tmp_scan_no = self.get_cell_value(i_row, 0)
+            if scan_no == tmp_scan_no:
+                self.update_cell_value(i_row, 1, len(pt_list))
+                set_done = True
+                break
+        # END-FOR
+
+        if set_done is False:
+            return 'Unable to find scan %d in table.' % scan_no
+
+        return ''
+
+    def set_status(self, scan_no, status):
+        """
+        Set the status for merging scan to QTable
+        :param status:
+        :return:
+        """
+        # Check
+        assert isinstance(scan_no, int)
+
+        num_rows = self.rowCount()
+        set_done = False
+        for i_row in xrange(num_rows):
+            tmp_scan_no = self.get_cell_value(i_row, 0)
+            if scan_no == tmp_scan_no:
+                self.update_cell_value(i_row, 2, status)
+                set_done = True
+                break
+        # END-FOR
+
+        if set_done is False:
+            return 'Unable to find scan %d in table.' % scan_no
+
+        return ''
+
+    def set_ws_names(self, scan_num, merged_md_name, ws_group_name):
+        """
+        Set the output workspace and workspace group's names to QTable
+        :param merged_md_name:
+        :param ws_group_name:
+        :return:
+        """
+        # Check
+        assert isinstance(scan_num, int)
+        assert isinstance(merged_md_name, str) or merged_md_name is None
+        assert isinstance(ws_group_name, str) or ws_group_name is None
+
+        num_rows = self.rowCount()
+        set_done = False
+        for i_row in xrange(num_rows):
+            tmp_scan_no = self.get_cell_value(i_row, 0)
+            if scan_num == tmp_scan_no:
+                if merged_md_name is not None:
+                    self.update_cell_value(i_row, 3, merged_md_name)
+                if ws_group_name is not None:
+                    self.update_cell_value(i_row, 4, ws_group_name)
+                set_done = True
+                break
+        # END-FOR
+
+        if set_done is False:
+            return 'Unable to find scan %d in table.' % scan_num
+
+        return
diff --git a/scripts/HFIR_4Circle_Reduction/mplgraphicsview.py b/scripts/HFIR_4Circle_Reduction/mplgraphicsview.py
new file mode 100644
index 0000000000000000000000000000000000000000..152ffc29c4775c6f98b8b67befe0554a36d66032
--- /dev/null
+++ b/scripts/HFIR_4Circle_Reduction/mplgraphicsview.py
@@ -0,0 +1,1255 @@
+#pylint: disable=invalid-name,too-many-public-methods,too-many-arguments,non-parent-init-called,R0902,too-many-branches,C0302
+import os
+import numpy as np
+
+from PyQt4 import QtGui
+
+from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
+from matplotlib.backends.backend_qt4agg import NavigationToolbar2QTAgg as NavigationToolbar2
+from matplotlib.figure import Figure
+import matplotlib.image
+
+MplLineStyles = ['-' , '--' , '-.' , ':' , 'None' , ' ' , '']
+MplLineMarkers = [
+    ". (point         )",
+    "* (star          )",
+    "x (x             )",
+    "o (circle        )",
+    "s (square        )",
+    "D (diamond       )",
+    ", (pixel         )",
+    "v (triangle_down )",
+    "^ (triangle_up   )",
+    "< (triangle_left )",
+    "> (triangle_right)",
+    "1 (tri_down      )",
+    "2 (tri_up        )",
+    "3 (tri_left      )",
+    "4 (tri_right     )",
+    "8 (octagon       )",
+    "p (pentagon      )",
+    "h (hexagon1      )",
+    "H (hexagon2      )",
+    "+ (plus          )",
+    "d (thin_diamond  )",
+    "| (vline         )",
+    "_ (hline         )",
+    "None (nothing    )"]
+
+# Note: in colors, "white" is removed
+MplBasicColors = [
+    "black",
+    "red",
+    "blue",
+    "green",
+    "cyan",
+    "magenta",
+    "yellow"]
+
+
+class IndicatorManager(object):
+    """ Manager for all indicator lines
+    """
+    def __init__(self):
+        """
+
+        :return:
+        """
+        # Auto color index
+        self._colorIndex = 0
+        # Auto line ID
+        self._autoLineID = 1
+
+        self._lineManager = dict()
+        self._canvasLineKeyDict = dict()
+        self._indicatorTypeDict = dict()  # value: 0 (horizontal), 1 (vertical), 2 (2-way)
+
+        return
+
+    def add_2way_indicator(self, x, x_min, x_max, y, y_min, y_max, color):
+        """
+
+        :param x:
+        :param x_min:
+        :param x_max:
+        :param y:
+        :param y_min:
+        :param y_max:
+        :param color:
+        :return:
+        """
+        # Set up indicator ID
+        this_id = str(self._autoLineID)
+        self._autoLineID += 1
+
+        # Set up vectors
+        vec_x_horizontal = np.array([x_min, x_max])
+        vec_y_horizontal = np.array([y, y])
+
+        vec_x_vertical = np.array([x, x])
+        vec_y_vertical = np.array([y_min, y_max])
+
+        #
+        self._lineManager[this_id] = [vec_x_horizontal, vec_y_horizontal, vec_x_vertical, vec_y_vertical, color]
+        self._indicatorTypeDict[this_id] = 2
+
+        return this_id
+
+    def add_horizontal_indicator(self, y, x_min, x_max, color):
+        """
+        Add a horizontal indicator
+        :param y:
+        :param x_min:
+        :param x_max:
+        :param color:
+        :return:
+        """
+        # Get ID
+        this_id = str(self._autoLineID)
+        self._autoLineID += 1
+
+        #
+        vec_x = np.array([x_min, x_max])
+        vec_y = np.array([y, y])
+
+        #
+        self._lineManager[this_id] = [vec_x, vec_y, color]
+        self._indicatorTypeDict[this_id] = 0
+
+        return this_id
+
+    def add_vertical_indicator(self, x, y_min, y_max, color):
+        """
+        Add a vertical indicator to data structure
+        :return: indicator ID
+        """
+        # Get ID
+        this_id = str(self._autoLineID)
+        self._autoLineID += 1
+
+        #
+        vec_x = np.array([x, x])
+        vec_y = np.array([y_min, y_max])
+
+        #
+        self._lineManager[this_id] = [vec_x, vec_y, color]
+        self._indicatorTypeDict[this_id] = 1
+
+        return this_id
+
+    def get_canvas_line_index(self, my_id):
+        """
+
+        :param my_id:
+        :return:
+        """
+        assert isinstance(my_id, str)
+
+        if my_id not in self._canvasLineKeyDict:
+            raise RuntimeError('Indicator ID %s cannot be found. Current keys are %s.' % (
+                my_id, str(sorted(self._canvasLineKeyDict.keys()))
+            ))
+        return self._canvasLineKeyDict[my_id]
+
+    def get_line_type(self, my_id):
+        """
+
+        :param my_id:
+        :return:
+        """
+        return self._indicatorTypeDict[my_id]
+
+    def get_2way_data(self, line_id):
+        """
+
+        :param line_id:
+        :return:
+        """
+        assert self._indicatorTypeDict.has_key(line_id)
+        assert self._indicatorTypeDict[line_id] == 2
+
+        vec_set = [self._lineManager[line_id][0:2], self._lineManager[line_id][2:4]]
+
+        return vec_set
+
+    def get_data(self, line_id):
+        """
+        Get line's vector x and vector y
+        :param line_id:
+        :return:
+        """
+        return self._lineManager[line_id][0], self._lineManager[line_id][1]
+
+    def get_line_style(self, line_id=None):
+        """
+
+        :param line_id:
+        :return:
+        """
+        assert isinstance(line_id, None)
+        return '--'
+
+    def get_live_indicator_ids(self):
+        """
+
+        :return:
+        """
+        return sorted(self._lineManager.keys())
+
+    def get_marker(self):
+        """
+        Get the marker a line
+        :param line_id:
+        :return:
+        """
+        return 'o'
+
+    def get_next_color(self):
+        """
+        Get next color by auto color index
+        :return: string as color
+        """
+        next_color = MplBasicColors[self._colorIndex]
+
+        # Advance and possibly reset color scheme
+        self._colorIndex += 1
+        if self._colorIndex == len(MplBasicColors):
+            self._colorIndex = 0
+
+        return next_color
+
+    def set_canvas_line_index(self, my_id, canvas_line_index):
+        """
+
+        :param my_id:
+        :param canvas_line_index:
+        :return:
+        """
+        self._canvasLineKeyDict[my_id] = canvas_line_index
+
+    def shift(self, my_id, dx, dy):
+        """
+
+        :param my_id:
+        :param dx:
+        :param dy:
+        :return:
+        """
+        print self._lineManager[my_id][0]
+
+        if self._indicatorTypeDict[my_id] == 0:
+            # horizontal
+            self._lineManager[my_id][1] += dy
+
+        elif self._indicatorTypeDict[my_id] == 1:
+            # vertical
+            self._lineManager[my_id][0] += dx
+
+        elif self._indicatorTypeDict[my_id] == 2:
+            # 2-way
+            self._lineManager[my_id][2] += dx
+            self._lineManager[my_id][1] += dy
+
+        else:
+            raise RuntimeError('Unsupported indicator of type %d' % self._indicatorTypeDict[my_id])
+
+        return
+
+    def update_indicators_range(self, x_range, y_range):
+        """
+        Update indicator's range
+        :param x_range:
+        :param y_range:
+        :return:
+        """
+        for i_id in self._lineManager.keys():
+            # NEXT - Need a new flag for direction of the indicating line, vertical or horizontal
+            if True:
+                self._lineManager[i_id][1][0] = y_range[0]
+                self._lineManager[i_id][1][-1] = y_range[1]
+            else:
+                self._lineManager[i_id][0][0] = x_range[0]
+                self._lineManager[i_id][0][-1] = x_range[1]
+
+        return
+
+
+class MplGraphicsView(QtGui.QWidget):
+    """ A combined graphics view including matplotlib canvas and
+    a navigation tool bar
+
+    Note: Merged with HFIR_Powder_Reduction.MplFigureCAnvas
+    """
+    def __init__(self, parent):
+        """ Initialization
+        """
+        # Initialize parent
+        QtGui.QWidget.__init__(self, parent)
+
+        # set up canvas
+        self._myCanvas = Qt4MplCanvas(self)
+        self._myToolBar = MyNavigationToolbar(self, self._myCanvas)
+
+        # set up layout
+        self._vBox = QtGui.QVBoxLayout(self)
+        self._vBox.addWidget(self._myCanvas)
+        self._vBox.addWidget(self._myToolBar)
+
+        # auto line's maker+color list
+        self._myLineMarkerColorList = []
+        self._myLineMarkerColorIndex = 0
+        self.setAutoLineMarkerColorCombo()
+
+        # Declaration of class variables
+        self._indicatorKey = None
+
+        # Indicator manager
+        self._myIndicatorsManager = IndicatorManager()
+
+        return
+
+    def add_line_set(self, vec_set, color, marker, line_style, line_width):
+        """ Add a set of line and manage together
+        :param vec_set:
+        :param color:
+        :param marker:
+        :param line_style:
+        :param line_width:
+        :return:
+        """
+        key_list = list()
+        for vec_x, vec_y in vec_set:
+            temp_key = self._myCanvas.add_plot_1d(vec_x, vec_y, color=color, marker=marker,
+                                                  line_style=line_style, line_width=line_width)
+            assert isinstance(temp_key, int)
+            assert temp_key >= 0
+            key_list.append(temp_key)
+
+        return key_list
+
+    def add_plot_1d(self, vec_x, vec_y, y_err=None, color=None, label="", x_label=None, y_label=None,
+                    marker=None, line_style=None, line_width=1):
+        """ Add a new plot
+        """
+        line_key = self._myCanvas.add_plot_1d(vec_x, vec_y, y_err, color, label, x_label, y_label, marker, line_style,
+                                              line_width)
+
+        return line_key
+
+    def add_plot_1d_right(self, vec_x, vec_y, color=None, label='', marker=None, line_style=None, line_width=1):
+        """
+        Add 1 line (1-d plot) to right axis
+        :param vec_x:
+        :param vec_y:
+        :param color:
+        :param label:
+        :param marker:
+        :param line_style:
+        :param line_width:
+        :return:
+        """
+        line_key = self._myCanvas.add_1d_plot_right(vec_x, vec_y, label=label,
+                                                    color=color, marker=marker,
+                                                    linestyle=line_style, linewidth=line_width)
+
+        return line_key
+
+    def add_2way_indicator(self, x=None, y=None, color=None, master_line=None):
+        """ Add a 2-way indicator following an existing line?
+        :param x:
+        :param y:
+        :param color:
+        :return:
+        """
+        if master_line is not None:
+            raise RuntimeError('Implement how to use master_line ASAP.')
+
+        x_min, x_max = self._myCanvas.getXLimit()
+        if x is None:
+            x = (x_min + x_max) * 0.5
+        else:
+            assert isinstance(x, float)
+
+        y_min, y_max = self._myCanvas.getYLimit()
+        if y is None:
+            y = (y_min + y_max) * 0.5
+        else:
+            assert isinstance(y, float)
+
+        if color is None:
+            color = self._myIndicatorsManager.get_next_color()
+        else:
+            assert isinstance(color, str)
+
+        my_id = self._myIndicatorsManager.add_2way_indicator(x, x_min, x_max,
+                                                             y, y_min, y_max,
+                                                             color)
+        vec_set = self._myIndicatorsManager.get_2way_data(my_id)
+
+        canvas_line_index = self.add_line_set(vec_set, color=color,
+                                              marker=self._myIndicatorsManager.get_marker(),
+                                              line_style=self._myIndicatorsManager.get_line_style(),
+                                              line_width=1)
+        self._myIndicatorsManager.set_canvas_line_index(my_id, canvas_line_index)
+
+        return my_id
+
+    def add_horizontal_indicator(self, y=None, color=None):
+        """ Add an indicator line
+        """
+        # Default
+        if y is None:
+            y_min, y_max = self._myCanvas.getYLimit()
+            y = (y_min + y_max) * 0.5
+        else:
+            assert isinstance(y, float)
+
+        x_min, x_max = self._myCanvas.getXLimit()
+
+        # For color
+        if color is None:
+            color = self._myIndicatorsManager.get_next_color()
+        else:
+            assert isinstance(color, str)
+
+        # Form
+        my_id = self._myIndicatorsManager.add_horizontal_indicator(y, x_min, x_max, color)
+        vec_x, vec_y = self._myIndicatorsManager.get_data(my_id)
+
+        canvas_line_index = self._myCanvas.add_plot_1d(vec_x=vec_x, vec_y=vec_y,
+                                                       color=color, marker=self._myIndicatorsManager.get_marker(),
+                                                       line_style=self._myIndicatorsManager.get_line_style(),
+                                                       line_width=1)
+
+        self._myIndicatorsManager.set_canvas_line_index(my_id, canvas_line_index)
+
+        return my_id
+
+    def add_vertical_indicator(self, x=None, color=None):
+        """
+        Add a vertical indicator line
+        :param x: None as the automatic mode using default from middle of canvas
+        :param color: None as the automatic mode using default
+        :return: indicator ID
+        """
+        # For indicator line's position
+        if x is None:
+            x_min, x_max = self._myCanvas.getXLimit()
+            x = (x_min + x_max) * 0.5
+        else:
+            assert isinstance(x, float)
+
+        y_min, y_max = self._myCanvas.getYLimit()
+
+        # For color
+        if color is None:
+            color = self._myIndicatorsManager.get_next_color()
+        else:
+            assert isinstance(color, str)
+
+        # Form
+        my_id = self._myIndicatorsManager.add_vertical_indicator(x, y_min, y_max, color)
+        vec_x, vec_y = self._myIndicatorsManager.get_data(my_id)
+
+        canvas_line_index = self._myCanvas.add_plot_1d(vec_x=vec_x, vec_y=vec_y,
+                                                       color=color, marker=self._myIndicatorsManager.get_marker(),
+                                                       line_style=self._myIndicatorsManager.get_line_style(),
+                                                       line_width=1)
+
+        self._myIndicatorsManager.set_canvas_line_index(my_id, canvas_line_index)
+
+        return my_id
+
+    def add_plot_2d(self, array2d, x_min, x_max, y_min, y_max, hold_prev_image=True, y_tick_label=None):
+        """
+        Add a 2D image to canvas
+        :param array2d: numpy 2D array
+        :param x_min:
+        :param x_max:
+        :param y_min:
+        :param y_max:
+        :param hold_prev_image:
+        :param y_tick_label:
+        :return:
+        """
+        self._myCanvas.addPlot2D(array2d, x_min, x_max, y_min, y_max, hold_prev_image, y_tick_label)
+
+        return
+
+
+    def addImage(self, imagefilename):
+        """ Add an image by file
+        """
+        # check
+        if os.path.exists(imagefilename) is False:
+            raise NotImplementedError("Image file %s does not exist." % (imagefilename))
+
+        self._myCanvas.addImage(imagefilename)
+
+        return
+
+    def clear_all_lines(self):
+        """
+        """
+        self._myCanvas.clear_all_1d_plots()
+
+    def clear_canvas(self):
+        """ Clear canvas
+        """
+        return self._myCanvas.clear_canvas()
+
+    def draw(self):
+        """ Draw to commit the change
+        """
+        return self._myCanvas.draw()
+
+    def evt_view_updated(self):
+        """ Event handling as canvas size updated
+        :return:
+        """
+        # update the indicator
+        new_x_range = self.getXLimit()
+        new_y_range = self.getYLimit()
+
+        self._myIndicatorsManager.update_indicators_range(new_x_range, new_y_range)
+        for indicator_key in self._myIndicatorsManager.get_live_indicator_ids():
+            canvas_line_id = self._myIndicatorsManager.get_canvas_line_index(indicator_key)
+            data_x, data_y = self._myIndicatorsManager.get_data(indicator_key)
+            self.updateLine(canvas_line_id, data_x, data_y)
+        # END-FOR
+
+        return
+
+    def getPlot(self):
+        """
+        """
+        return self._myCanvas.getPlot()
+
+    def getLastPlotIndexKey(self):
+        """ Get ...
+        """
+        return self._myCanvas.getLastPlotIndexKey()
+
+    def getXLimit(self):
+        """ Get limit of Y-axis
+        """
+        return self._myCanvas.getXLimit()
+
+    def getYLimit(self):
+        """ Get limit of Y-axis
+        """
+        return self._myCanvas.getYLimit()
+
+    def move_indicator(self, line_id, dx, dy):
+        """
+        Move the indicator line in horizontal
+        :param line_id:
+        :param dx:
+        :return:
+        """
+        # Shift value
+        self._myIndicatorsManager.shift(line_id, dx=dx, dy=dy)
+
+        # apply to plot on canvas
+        if self._myIndicatorsManager.get_line_type(line_id) < 2:
+            # horizontal or vertical
+            canvas_line_index = self._myIndicatorsManager.get_canvas_line_index(line_id)
+            vec_x, vec_y = self._myIndicatorsManager.get_data(line_id)
+            self._myCanvas.updateLine(ikey=canvas_line_index, vecx=vec_x, vecy=vec_y)
+        else:
+            # 2-way
+            canvas_line_index_h, canvas_line_index_v = self._myIndicatorsManager.get_canvas_line_index(line_id)
+            h_vec_set, v_vec_set = self._myIndicatorsManager.get_2way_data(line_id)
+
+            self._myCanvas.updateLine(ikey=canvas_line_index_h, vecx=h_vec_set[0], vecy=h_vec_set[1])
+            self._myCanvas.updateLine(ikey=canvas_line_index_v, vecx=v_vec_set[0], vecy=v_vec_set[1])
+
+        return
+
+    def remove_indicator(self, indicator_key):
+        """ Remove indicator line
+        :param indicator_key:
+        :return:
+        """
+        #
+        plot_id = self._myIndicatorsManager.get_canvas_line_index(indicator_key)
+        self._myCanvas.remove_plot_1d(plot_id)
+
+        return
+
+    def removePlot(self, ikey):
+        """
+        """
+        return self._myCanvas.remove_plot_1d(ikey)
+
+    def updateLine(self, ikey, vecx, vecy, linestyle=None, linecolor=None, marker=None, markercolor=None):
+        """
+        """
+        return self._myCanvas.updateLine(ikey, vecx, vecy, linestyle, linecolor, marker, markercolor)
+
+    def update_indicator(self, i_key, color):
+        """
+        Update indicator with new color
+        :param i_key:
+        :param vec_x:
+        :param vec_y:
+        :param color:
+        :return:
+        """
+        if self._myIndicatorsManager.get_line_type(i_key) < 2:
+            # horizontal or vertical
+            canvas_line_index = self._myIndicatorsManager.get_canvas_line_index(i_key)
+            self._myCanvas.updateLine(ikey=canvas_line_index, vecx=None, vecy=None, linecolor=color)
+        else:
+            # 2-way
+            canvas_line_index_h, canvas_line_index_v = self._myIndicatorsManager.get_canvas_line_index(i_key)
+            # h_vec_set, v_vec_set = self._myIndicatorsManager.get_2way_data(i_key)
+
+            self._myCanvas.updateLine(ikey=canvas_line_index_h, vecx=None, vecy=None, linecolor=color)
+            self._myCanvas.updateLine(ikey=canvas_line_index_v, vecx=None, vecy=None, linecolor=color)
+
+        return
+
+    def get_indicator_position(self, indicator_key):
+        """ Get position (x or y) of the indicator
+        :return:
+        """
+        # NEXT - Consider a better and more consistent return
+        vec_x, vec_y = self._myIndicatorsManager.get_data(indicator_key)
+        if vec_x[0] == vec_x[1]:
+            return vec_x[0]
+
+        return vec_y[0]
+
+    def getLineStyleList(self):
+        """
+        """
+        return MplLineStyles
+
+    def getLineMarkerList(self):
+        """
+        """
+        return MplLineMarkers
+
+    def getLineBasicColorList(self):
+        """
+        """
+        return MplBasicColors
+
+    def getDefaultColorMarkerComboList(self):
+        """ Get a list of line/marker color and marker style combination
+        as default to add more and more line to plot
+        """
+        return self._myCanvas.getDefaultColorMarkerComboList()
+
+    def getNextLineMarkerColorCombo(self):
+        """ As auto line's marker and color combo list is used,
+        get the NEXT marker/color combo
+        """
+        # get from list
+        marker, color = self._myLineMarkerColorList[self._myLineMarkerColorIndex]
+        # process marker if it has information
+        if marker.count(' (') > 0:
+            marker = marker.split(' (')[0]
+        print "[DB] Print line %d: marker = %s, color = %s" % (self._myLineMarkerColorIndex, marker, color)
+
+        # update the index
+        self._myLineMarkerColorIndex += 1
+        if self._myLineMarkerColorIndex == len(self._myLineMarkerColorList):
+            self._myLineMarkerColorIndex = 0
+
+        return marker, color
+
+    def resetLineColorStyle(self):
+        """ Reset the auto index for line's color and style
+        """
+        self._myLineMarkerColorIndex = 0
+        return
+
+    # NEXT-Urgent! - Find out difference between setXYLimit() and setXYLimits()
+    def setXYLimit(self, xmin, xmax, ymin, ymax):
+        """ Set X-Y limit automatically
+        """
+        self._myCanvas.axes.set_xlim([xmin, xmax])
+        self._myCanvas.axes.set_ylim([ymin, ymax])
+
+        self._myCanvas.draw()
+
+        return
+
+    def setXYLimits(self, xmin=None, xmax=None, ymin=None, ymax=None):
+        """
+        """
+        return self._myCanvas.setXYLimit(xmin, xmax, ymin, ymax)
+
+    def setAutoLineMarkerColorCombo(self):
+        """
+        """
+        self._myLineMarkerColorList = []
+        for marker in MplLineMarkers:
+            for color in MplBasicColors:
+                self._myLineMarkerColorList.append( (marker, color) )
+
+        return
+
+    def setLineMarkerColorIndex(self, newindex):
+        """
+        """
+        self._myLineMarkerColorIndex = newindex
+
+        return
+
+
+class Qt4MplCanvas(FigureCanvas):
+    """  A customized Qt widget for matplotlib figure.
+    It can be used to replace GraphicsView of QtGui
+    """
+    def __init__(self, parent):
+        """  Initialization
+        """
+        # from mpl_toolkits.axes_grid1 import host_subplot
+        # import mpl_toolkits.axisartist as AA
+        # import matplotlib.pyplot as plt
+
+        # Instantiating matplotlib Figure
+        self.fig = Figure()
+        self.fig.patch.set_facecolor('white')
+
+        if True:
+            self.axes = self.fig.add_subplot(111) # return: matplotlib.axes.AxesSubplot
+            self.axes2 = None
+        else:
+            self.axes = self.fig.add_host_subplot(111)
+
+        # Initialize parent class and set parent
+        FigureCanvas.__init__(self, self.fig)
+        self.setParent(parent)
+
+        # Set size policy to be able to expanding and resizable with frame
+        FigureCanvas.setSizePolicy(self, QtGui.QSizePolicy.Expanding,QtGui.QSizePolicy.Expanding)
+        FigureCanvas.updateGeometry(self)
+
+        # Variables to manage all lines/subplot
+        self._lineDict = {}
+        self._lineIndex = 0
+
+        # legend and color bar
+        self._colorBar = None
+
+        return
+
+    def add_plot_1d(self, vec_x, vec_y, y_err=None, color=None, label="", x_label=None, y_label=None,
+                    marker=None, line_style=None, line_width=1):
+        """
+
+        :param vec_x: numpy array X
+        :param vec_y: numpy array Y
+        :param y_err:
+        :param color:
+        :param label:
+        :param x_label:
+        :param y_label:
+        :param marker:
+        :param line_style:
+        :param line_width:
+        :return: new key
+        """
+        # Check input
+        if isinstance(vec_x, np.ndarray) is False or isinstance(vec_y, np.ndarray) is False:
+            raise NotImplementedError('Input vec_x or vec_y for addPlot() must be numpy.array.')
+        plot_error = y_err is not None
+        if plot_error is True:
+            if isinstance(y_err, np.ndarray) is False:
+                raise NotImplementedError('Input y_err must be either None or numpy.array.')
+
+        if len(vec_x) != len(vec_y):
+            raise NotImplementedError('Input vec_x and vec_y must have same size.')
+        if plot_error is True and len(y_err) != len(vec_x):
+            raise NotImplementedError('Input vec_x, vec_y and y_error must have same size.')
+
+        # Hold previous data
+        self.axes.hold(True)
+
+        # process inputs and defaults
+        if color is None:
+            color = (0,1,0,1)
+        if marker is None:
+            marker = 'o'
+        if line_style is None:
+            line_style = '-'
+
+        # color must be RGBA (4-tuple)
+        if plot_error is False:
+            print "[DB] line_style = ", line_style, "line_width = ", line_width, "marker = ", marker, "color = ", color
+            r = self.axes.plot(vec_x, vec_y, color=color, marker=marker, linestyle=line_style,
+                               label=label, linewidth=line_width)
+            # return: list of matplotlib.lines.Line2D object
+        else:
+            r = self.axes.errorbar(vec_x, vec_y, yerr=y_err, color=color, marker=marker, linestyle=line_style,
+                                   label=label, linewidth=line_width)
+
+        self.axes.set_aspect('auto')
+
+        # set x-axis and y-axis label
+        if x_label is not None:
+            self.axes.set_xlabel(x_label, fontsize=20)
+        if y_label is not None:
+            self.axes.set_ylabel(y_label, fontsize=20)
+
+        # set/update legend
+        self._setupLegend()
+
+        # Register
+        line_key = self._lineIndex
+        if len(r) == 1:
+            self._lineDict[line_key] = r[0]
+            self._lineIndex += 1
+        else:
+            print "Impoooooooooooooooosible!  Return from plot is a %d-tuple. " % (len(r))
+
+        # Flush/commit
+        self.draw()
+
+        return line_key
+
+    def add_1d_plot_right(self, x, y, color=None, label="", x_label=None, ylabel=None, marker=None, linestyle=None,
+                          linewidth=1):
+        """ Add a line (1-d plot) at right axis
+        """
+        if self.axes2 is None:
+            self.axes2 = self.axes.twinx()
+            # print self.par1, type(self.par1)
+
+        # Hold previous data
+        self.axes2.hold(True)
+
+        # Default
+        if color is None:
+            color = (0, 1, 0, 1)
+        if marker is None:
+            marker = 'o'
+        if linestyle is None:
+            linestyle = '-'
+
+        # Special default
+        if len(label) == 0:
+            label = 'right'
+            color = 'red'
+
+        # color must be RGBA (4-tuple)
+        r = self.axes2.plot(x, y, color=color, marker=marker, linestyle=linestyle,
+                            label=label, linewidth=linewidth)
+        # return: list of matplotlib.lines.Line2D object
+
+        self.axes2.set_aspect('auto')
+
+        # set x-axis and y-axis label
+        if x_label is not None:
+            self.axes2.set_xlabel(x_label, fontsize=20)
+        if ylabel is not None:
+            self.axes2.set_ylabel(ylabel, fontsize=20)
+
+        # set/update legend
+        self._setupLegend()
+
+        # Register
+        line_key = -1
+        if len(r) == 1:
+            line_key = self._lineIndex
+            self._lineDict[line_key] = r[0]
+            self._lineIndex += 1
+        else:
+            print "Impoooooooooooooooosible!"
+
+        # Flush/commit
+        self.draw()
+
+        return line_key
+
+
+    def addPlot2D(self, array2d, xmin, xmax, ymin, ymax, holdprev, yticklabels=None):
+        """ Add a 2D plot
+
+        Arguments:
+         - yticklabels :: list of string for y ticks
+        """
+        # Release the current image
+        self.axes.hold(holdprev)
+
+        # Do plot
+        # y ticks will be shown on line 1, 4, 23, 24 and 30
+        # yticks = [1, 4, 23, 24, 30]
+        # self.axes.set_yticks(yticks)
+
+        # show image
+        imgplot = self.axes.imshow(array2d, extent=[xmin,xmax,ymin,ymax], interpolation='none')
+        # set y ticks as an option:
+        if yticklabels is not None:
+            # it will always label the first N ticks even image is zoomed in
+            print "--------> [FixMe]: Set up the Y-axis ticks is erroreous"
+            #self.axes.set_yticklabels(yticklabels)
+
+        # explicitly set aspect ratio of the image
+        self.axes.set_aspect('auto')
+
+        # Set color bar.  plt.colorbar() does not work!
+        if self._colorBar is None:
+            # set color map type
+            imgplot.set_cmap('spectral')
+            self._colorBar = self.fig.colorbar(imgplot)
+        else:
+            self._colorBar.update_bruteforce(imgplot)
+
+        # Flush...
+        self._flush()
+
+        return
+
+    def addImage(self, imagefilename):
+        """ Add an image by file
+        """
+        #import matplotlib.image as mpimg
+
+        # set aspect to auto mode
+        self.axes.set_aspect('auto')
+
+        img = matplotlib.image.imread(str(imagefilename))
+        # lum_img = img[:,:,0]
+        # FUTURE : refactor for image size, interpolation and origin
+        imgplot = self.axes.imshow(img, extent=[0, 1000, 800, 0], interpolation='none', origin='lower')
+
+        # Set color bar.  plt.colorbar() does not work!
+        if self._colorBar is None:
+            # set color map type
+            imgplot.set_cmap('spectral')
+            self._colorBar = self.fig.colorbar(imgplot)
+        else:
+            self._colorBar.update_bruteforce(imgplot)
+
+        self._flush()
+
+        return
+
+    def clear_all_1d_plots(self):
+        """ Remove all lines from the canvas
+        """
+        for ikey in self._lineDict.keys():
+            plot = self._lineDict[ikey]
+            if plot is None:
+                continue
+            if isinstance(plot, tuple) is False:
+                try:
+                    self.axes.lines.remove(plot)
+                except ValueError as e:
+                    print "[Error] Plot %s is not in axes.lines which has %d lines. Error mesage: %s" % (
+                        str(plot), len(self.axes.lines), str(e))
+                self._lineDict[ikey] = None
+            else:
+                # error bar
+                plot[0].remove()
+                for line in plot[1]:
+                    line.remove()
+                for line in plot[2]:
+                    line.remove()
+                self._lineDict[ikey] = None
+            # ENDIF(plot)
+        # ENDFOR
+
+        self._setupLegend()
+
+        self.draw()
+
+        return
+
+    def clear_canvas(self):
+        """ Clear data including lines and image from canvas
+        """
+        # clear the image for next operation
+        self.axes.hold(False)
+
+        # Clear all lines
+        self.clear_all_1d_plots()
+
+        # clear image
+        self.axes.cla()
+        # Try to clear the color bar
+        if len(self.fig.axes) > 1:
+            self.fig.delaxes(self.fig.axes[1])
+            self._colorBar = None
+            # This clears the space claimed by color bar but destroys sub_plot too.
+            self.fig.clear()
+            # Re-create subplot
+            self.axes = self.fig.add_subplot(111)
+
+        # flush/commit
+        self._flush()
+
+        return
+
+
+    def getLastPlotIndexKey(self):
+        """ Get the index/key of the last added line
+        """
+        return self._lineIndex-1
+
+
+    def getPlot(self):
+        """ reture figure's axes to expose the matplotlib figure to PyQt client
+        """
+        return self.axes
+
+    def getXLimit(self):
+        """ Get limit of Y-axis
+        """
+        return self.axes.get_xlim()
+
+    def getYLimit(self):
+        """ Get limit of Y-axis
+        """
+        return self.axes.get_ylim()
+
+    def setXYLimit(self, xmin, xmax, ymin, ymax):
+        """
+        """
+        # for X
+        xlims = self.axes.get_xlim()
+        xlims = list(xlims)
+        if xmin is not None:
+            xlims[0] = xmin
+        if xmax is not None:
+            xlims[1] = xmax
+        self.axes.set_xlim(xlims)
+
+        # for Y
+        ylims = self.axes.get_ylim()
+        ylims = list(ylims)
+        if ymin is not None:
+            ylims[0] = ymin
+        if ymax is not None:
+            ylims[1] = ymax
+        self.axes.set_ylim(ylims)
+
+        # try draw
+        self.draw()
+
+        return
+
+    def remove_plot_1d(self, plot_key):
+        """ Remove the line with its index as key
+        :param plot_key:
+        :return:
+        """
+        # self._lineDict[ikey].remove()
+        print 'Remove line... ',
+
+        # Get all lines in list
+        lines = self.axes.lines
+        assert isinstance(lines, list)
+
+        print 'Number of lines = %d, List: %s' % (len(lines), str(lines))
+        print 'Line to remove: key = %s, Line Dict has key = %s' % (str(plot_key), str(self._lineDict.has_key(plot_key)))
+
+        if plot_key in self._lineDict:
+            self.axes.lines.remove(self._lineDict[plot_key])
+            self._lineDict[plot_key] = None
+        else:
+            raise RuntimeError('Line with ID %s is not recorded.' % plot_key)
+
+        # Draw
+        self.draw()
+
+        return
+
+    def updateLine(self, ikey, vecx, vecy, linestyle=None, linecolor=None, marker=None, markercolor=None):
+        """
+        """
+        line = self._lineDict[ikey]
+
+        if vecx is not None and vecy is not None:
+            line.set_xdata(vecx)
+            line.set_ydata(vecy)
+
+        if linecolor is not None:
+            line.set_color(linecolor)
+
+        if linestyle is not None:
+            line.set_linestyle(linestyle)
+
+        if marker is not None:
+            line.set_marker(marker)
+
+        if markercolor is not None:
+            line.set_markerfacecolor(markercolor)
+
+        oldlabel = line.get_label()
+        line.set_label(oldlabel)
+
+        self.axes.legend()
+
+        # commit
+        self.draw()
+
+        return
+
+    def getLineStyleList(self):
+        """
+        """
+        return MplLineStyles
+
+
+    def getLineMarkerList(self):
+        """
+        """
+        return MplLineMarkers
+
+    def getLineBasicColorList(self):
+        """
+        """
+        return MplBasicColors
+
+    def getDefaultColorMarkerComboList(self):
+        """ Get a list of line/marker color and marker style combination
+        as default to add more and more line to plot
+        """
+        combolist = []
+        nummarkers = len(MplLineMarkers)
+        numcolors = len(MplBasicColors)
+
+        for i in xrange(nummarkers):
+            marker = MplLineMarkers[i]
+            for j in xrange(numcolors):
+                color = MplBasicColors[j]
+                combolist.append( (marker, color) )
+            # ENDFOR (j)
+        # ENDFOR(i)
+
+        return combolist
+
+    def _flush(self):
+        """ A dirty hack to flush the image
+        """
+        w, h = self.get_width_height()
+        self.resize(w+1,h)
+        self.resize(w,h)
+
+        return
+
+    def _setupLegend(self, location='best'):
+        """ Set up legend
+        self.axes.legend()
+        Handler is a Line2D object. Lable maps to the line object
+        """
+        loclist = [
+            "best",
+            "upper right",
+            "upper left",
+            "lower left",
+            "lower right",
+            "right",
+            "center left",
+            "center right",
+            "lower center",
+            "upper center",
+            "center"]
+
+        # Check legend location valid or not
+        if location not in loclist:
+            location = 'best'
+
+        handles, labels = self.axes.get_legend_handles_labels()
+        self.axes.legend(handles, labels, loc=location)
+        # print handles
+        # print labels
+        #self.axes.legend(self._myLegendHandlers, self._myLegentLabels)
+
+        return
+
+# END-OF-CLASS (MplGraphicsView)
+
+
+class MyNavigationToolbar(NavigationToolbar2):
+    """ A customized navigation tool bar attached to canvas
+    Note:
+    * home, left, right: will not disable zoom/pan mode
+    * zoom and pan: will turn on/off both's mode
+
+    Other methods
+    * drag_pan(self, event): event handling method for dragging canvas in pan-mode
+    """
+    NAVIGATION_MODE_NONE = 0
+    NAVIGATION_MODE_PAN = 1
+    NAVIGATION_MODE_ZOOM = 2
+
+    def __init__(self, parent, canvas):
+        """ Initialization
+        """
+        NavigationToolbar2.__init__(self, canvas, canvas)
+
+        self._myParent = parent
+        self._navigationMode = MyNavigationToolbar.NAVIGATION_MODE_NONE
+
+        return
+
+    def get_mode(self):
+        """
+        :return: integer as none/pan/zoom mode
+        """
+        return self._navigationMode
+
+    # Overriding base's methods
+    def draw(self):
+        """
+        Canvas is drawn called by pan(), zoom()
+        :return:
+        """
+        NavigationToolbar2.draw(self)
+
+        self._myParent.evt_view_updated()
+
+        return
+
+    def pan(self, *args):
+        """
+
+        :param args:
+        :return:
+        """
+        NavigationToolbar2.pan(self, args)
+
+        if self._navigationMode == MyNavigationToolbar.NAVIGATION_MODE_PAN:
+            # out of pan mode
+            self._navigationMode = MyNavigationToolbar.NAVIGATION_MODE_NONE
+        else:
+            # into pan mode
+            self._navigationMode = MyNavigationToolbar.NAVIGATION_MODE_PAN
+
+        return
+
+    def zoom(self, *args):
+        """
+        Turn on/off zoom (zoom button)
+        :param args:
+        :return:
+        """
+        NavigationToolbar2.zoom(self, args)
+
+        if self._navigationMode == MyNavigationToolbar.NAVIGATION_MODE_ZOOM:
+            # out of zoom mode
+            self._navigationMode = MyNavigationToolbar.NAVIGATION_MODE_NONE
+        else:
+            # into zoom mode
+            self._navigationMode = MyNavigationToolbar.NAVIGATION_MODE_ZOOM
+
+        return
+
+    def _update_view(self):
+        """
+        view update called by home(), back() and forward()
+        :return:
+        """
+        NavigationToolbar2._update_view(self)
+
+        self._myParent.evt_view_updated()
+
+        return
+
diff --git a/scripts/HFIR_4Circle_Reduction/reduce4circleControl.py b/scripts/HFIR_4Circle_Reduction/reduce4circleControl.py
new file mode 100644
index 0000000000000000000000000000000000000000..bb11355d3c1b09e8e5b011cd8b698d64614939aa
--- /dev/null
+++ b/scripts/HFIR_4Circle_Reduction/reduce4circleControl.py
@@ -0,0 +1,1263 @@
+#pylint: disable=C0302,C0103,R0902,R0904,R0913,W0212,W0621,R0912
+################################################################################
+#
+# Controlling class
+#
+# == Data download and storage ==
+# - Local data storage (local-mode)
+# - Download from internet to cache (download-mode)
+#
+################################################################################
+import os
+import urllib2
+
+import numpy
+
+import mantid
+import mantid.simpleapi as api
+from mantid.api import AnalysisDataService
+
+DebugMode = True
+
+DET_X_SIZE = 256
+DET_Y_SIZE = 256
+
+
+class PeakInfo(object):
+    """ Class containing a peak's information for GUI
+    In order to manage some operations for a peak
+    It does not contain peak workspace but will hold
+    """
+    def __init__(self, parent):
+        """ Init
+        """
+        assert isinstance(parent, CWSCDReductionControl)
+
+        # Define class variable
+        self._myParent = parent
+        self._userHKL = [0, 0, 0]
+
+        self._myExpNumber = None
+        self._myScanNumber = None
+        self._myPtNumber = None
+
+        self._myPeakWSKey = (None, None, None)
+        self._myPeakIndex = None
+        # IPeak instance
+        self._myPeak = None
+
+        self._myLastPeakUB = None
+
+        return
+
+    def get_peak_workspace(self):
+        """
+        Get peak workspace related
+        :return:
+        """
+        assert isinstance(self._myPeakWSKey, tuple)
+        exp_number, scan_number, pt_number = self._myPeakWSKey
+
+        return self._myParent.get_ub_peak_ws(exp_number, scan_number, pt_number)[1]
+
+    def get_peak_ws_hkl(self):
+        """ Get HKL from PeakWorkspace
+        :return:
+        """
+        hkl = self._myPeak.getHKL()
+
+        return hkl.getX(), hkl.getY(), hkl.getZ()
+
+    def get_user_hkl(self):
+        """
+        Get HKL set to this object by client
+        :return: 3-tuple of float as (H, K, L)
+        """
+        hkl = self._userHKL
+
+        return hkl[0], hkl[1], hkl[2]
+
+    def set_from_run_info(self, exp_number, scan_number, pt_number):
+        """ Set from run information with parent
+        :param exp_number:
+        :param scan_number:
+        :param pt_number:
+        :return:
+        """
+        assert isinstance(exp_number, int)
+        assert isinstance(scan_number, int)
+        assert isinstance(pt_number, int)
+
+        status, peak_ws = self._myParent.get_ub_peak_ws(exp_number, scan_number, pt_number)
+        if status is True:
+            self._myPeakWSKey = (exp_number, scan_number, pt_number)
+            self._myPeakIndex = 0
+            self._myPeak = peak_ws.getPeak(0)
+        else:
+            error_message = peak_ws
+            return False, error_message
+
+        self._myExpNumber = exp_number
+        self._myScanNumber = scan_number
+        self._myPtNumber = pt_number
+
+        return True, ''
+
+    def set_from_peak_ws(self, peak_ws, peak_index):
+        """
+        Set from peak workspace
+        :param peak_ws:
+        :return:
+        """
+        # Check
+        assert isinstance(peak_ws, mantid.dataobjects.PeaksWorkspace)
+
+        # Get peak
+        try:
+            peak = peak_ws.getPeak(peak_index)
+        except RuntimeError as run_err:
+            raise RuntimeError(run_err)
+
+        self._myPeak = peak
+
+        return
+
+    def set_peak_ws_hkl_from_user(self):
+        """
+
+        :return:
+        """
+        # Check
+        if isinstance(self._myPeak, mantid.api.IPeak) is False:
+            raise RuntimeError('self._myPeakWS should be an instance of  mantid.api.IPeak. '
+                               'But it is of instance of %s now.' % str(type(self._myPeak)))
+
+        # Get hkl
+        h, k, l = self._userHKL
+        print '[DB] PeakInfo Get User HKL = (%f, %f, %f) to IPeak ' % (h, k, l)
+
+        self._myPeak.setHKL(h, k, l)
+
+        return
+
+    def set_user_hkl(self, h, k, l):
+        """
+        Set HKL to this peak Info
+        :return:
+        """
+        assert isinstance(h, float)
+        assert isinstance(k, float)
+        assert isinstance(l, float)
+
+        self._userHKL[0] = h
+        self._userHKL[1] = k
+        self._userHKL[2] = l
+
+        print '[DB] PeakInfo Set User HKL to (%f, %f, %f) ' % (self._userHKL[0], self._userHKL[1], self._userHKL[2])
+
+        return
+
+    def getExpInfo(self):
+        """
+
+        :return: 3-tuple of integer as experiment number, scan number and Pt number
+        """
+        return self._myExpNumber, self._myScanNumber, self._myPtNumber
+
+    def getQSample(self):
+        """
+
+        :return: 3-tuple of floats as Qx, Qy, Qz
+        """
+        q_sample = self._myPeak.getQSampleFrame()
+        return q_sample.getX(), q_sample.getY(), q_sample.getZ()
+
+
+class CWSCDReductionControl(object):
+    """ Controlling class for reactor-based single crystal diffraction reduction
+    """
+    def __init__(self, instrument_name=None):
+        """ init
+        """
+        if isinstance(instrument_name, str):
+            self._instrumentName = instrument_name
+        elif instrument_name is None:
+            self._instrumentName = ''
+        else:
+            raise RuntimeError('Instrument name %s of type %s is not allowed.' % (str(instrument_name),
+                                                                                  str(type(instrument_name))))
+
+        # Experiment number, data storage
+        # No Use/Confusing: self._expNumber = 0
+
+        self._dataDir = None
+        self._workDir = '/tmp'
+
+        self._myServerURL = ''
+
+        # Some set up
+        self._expNumber = None
+
+        # Container for MDEventWorkspace for each Pt.
+        self._myPtMDDict = dict()
+        # Container for loaded workspaces
+        self._mySpiceTableDict = {}
+        # Container for loaded raw pt workspace
+        self._myRawDataWSDict = dict()
+        # Container for PeakWorkspaces for calculating UB matrix
+        self._myUBPeakWSDict = dict()
+        # Container for UB  matrix
+        self._myUBMatrixDict = dict()
+
+        # Peak Info
+        self._myPeakInfoDict = dict()
+        # Last UB matrix calculated
+        self._myLastPeakUB = None
+        # Flag for data storage
+        self._cacheDataOnly = False
+
+        # A dictionary to manage all loaded and processed MDEventWorkspaces
+        # self._expDataDict = {}
+
+        return
+
+    def add_peak_info(self, exp_number, scan_number, pt_number):
+        """ Add a peak info for calculating UB matrix
+        :param exp_number:
+        :param scan_number:
+        :param pt_number:
+        :return: (boolean, PeakInfo/string)
+        """
+        has_peak_ws, peak_ws = self.get_ub_peak_ws(exp_number, scan_number, pt_number)
+        if has_peak_ws is False:
+            err_msg = 'No peak workspace found for Exp %s Scan %s Pt %s' % (
+                exp_number, scan_number, pt_number)
+            print '\n[DB] Fail to add peak info due to %s\n' % err_msg
+            return False, err_msg
+
+        if peak_ws.rowCount() > 1:
+            err_msg = 'There are more than 1 peak in PeaksWorkspace.'
+            print '\n[DB] Fail to add peak info due to %s\n' % err_msg
+            return False, err_msg
+
+        peak_info = PeakInfo(self)
+        peak_info.set_from_run_info(exp_number, scan_number, pt_number)
+
+        # Add to data management
+        self._myPeakInfoDict[(exp_number, scan_number, pt_number)] = peak_info
+
+        return True, peak_info
+
+    def calculate_ub_matrix(self, peak_info_list, a, b, c, alpha, beta, gamma):
+        """
+        Calculate UB matrix
+
+        Set Miller index from raw data in Workspace2D.
+        :param peakws:
+        :param a:
+        :param b:
+        :param c:
+        :param alpha:
+        :param beta:
+        :param gamma:
+        :return:
+        """
+        # Check
+        assert isinstance(peak_info_list, list)
+        for peak_info in peak_info_list:
+            if isinstance(peak_info, PeakInfo) is False:
+                raise NotImplementedError('Input PeakList is of type %s.' % str(type(peak_info_list[0])))
+            assert isinstance(peak_info, PeakInfo)
+
+        if len(peak_info_list) < 2:
+            return False, 'Too few peaks are input to calculate UB matrix.  Must be >= 2.'
+
+        # Construct a new peak workspace by combining all single peak
+        ub_peak_ws_name = 'Temp_UB_Peak'
+        ub_peak_ws = api.CloneWorkspace(InputWorkspace=peak_info_list[0].get_peak_workspace(),
+                                        OutputWorkspace=ub_peak_ws_name)
+
+        for i_peak_info in xrange(1, len(peak_info_list)):
+            # Set HKL as optional
+            peak_ws = peak_info_list[i_peak_info].get_peak_workspace()
+
+            # Combine peak workspace
+            ub_peak_ws = api.CombinePeaksWorkspaces(LHSWorkspace=ub_peak_ws,
+                                                    RHSWorkspace=peak_ws,
+                                                    CombineMatchingPeaks=False,
+                                                    OutputWorkspace=ub_peak_ws_name)
+        # END-FOR(i_peak_info)
+
+        # Calculate UB matrix
+        try:
+            api.CalculateUMatrix(PeaksWorkspace=ub_peak_ws_name,
+                                 a=a, b=b, c=c, alpha=alpha, beta=beta, gamma=gamma)
+        except ValueError as val_err:
+            return False, str(val_err)
+
+        ub_matrix = ub_peak_ws.sample().getOrientedLattice().getUB()
+
+        self._myLastPeakUB = ub_peak_ws
+
+        return True, ub_matrix
+
+    def does_raw_loaded(self, exp_no, scan_no, pt_no):
+        """
+        Check whether the raw Workspace2D for a Pt. exists
+        :param exp_no:
+        :param scan_no:
+        :param pt_no:
+        :return:
+        """
+        return (exp_no, scan_no, pt_no) in self._myRawDataWSDict
+
+    def does_spice_loaded(self, exp_no, scan_no):
+        """ Check whether a SPICE file has been loaded
+        :param exp_no:
+        :param scan_no:
+        :return:
+        """
+        return (exp_no, scan_no) in self._mySpiceTableDict
+
+    def download_spice_file(self, exp_number, scan_number, over_write):
+        """
+        Download a scan/pt data from internet
+        :param exp_number: experiment number
+        :param scan_number:
+        :return:
+        """
+        # Check
+        if exp_number is None:
+            exp_number = self._expNumber
+        assert isinstance(exp_number, int)
+        assert isinstance(scan_number, int)
+
+        # Generate the URL for SPICE data file
+        file_url = '%sexp%d/Datafiles/HB3A_exp%04d_scan%04d.dat' % (self._myServerURL, exp_number,
+                                                                    exp_number, scan_number)
+        file_name = '%s_exp%04d_scan%04d.dat' % (self._instrumentName, exp_number, scan_number)
+        file_name = os.path.join(self._dataDir, file_name)
+        if os.path.exists(file_name) is True and over_write is False:
+            return True, file_name
+
+        # Download
+        try:
+            api.DownloadFile(Address=file_url, Filename=file_name)
+        except RuntimeError as run_err:
+            return False, str(run_err)
+
+        # Check file exist?
+        if os.path.exists(file_name) is False:
+            return False, "Unable to locate downloaded file %s." % file_name
+
+        return True, file_name
+
+    def download_spice_xml_file(self, scan_no, pt_no, exp_no=None, overwrite=False):
+        """ Download a SPICE XML file for one measurement in a scan
+        :param scan_no:
+        :param pt_no:
+        :param exp_no:
+        :param overwrite:
+        :return: tuple (boolean, local file name/error message)
+        """
+        # Experiment number
+        if exp_no is None:
+            exp_no = self._expNumber
+
+        # Form the target file name and path
+        xml_file_name = '%s_exp%d_scan%04d_%04d.xml' % (self._instrumentName, exp_no, scan_no, pt_no)
+        local_xml_file_name = os.path.join(self._dataDir, xml_file_name)
+        if os.path.exists(local_xml_file_name) is True and overwrite is False:
+            return True, local_xml_file_name
+
+        # Generate the URL for XML file
+        xml_file_url = '%sexp%d/Datafiles/%s' % (self._myServerURL, exp_no, xml_file_name)
+
+        # Download
+        try:
+            api.DownloadFile(Address=xml_file_url,
+                             Filename=local_xml_file_name)
+        except RuntimeError as run_err:
+            return False, 'Unable to download Detector XML file %s dur to %s.' % (xml_file_name, str(run_err))
+
+        # Check file exist?
+        if os.path.exists(local_xml_file_name) is False:
+            return False, "Unable to locate downloaded file %s."%(local_xml_file_name)
+
+        return True, local_xml_file_name
+
+    def download_data_set(self, scan_list, overwrite=False):
+        """
+        Download data set including (1) spice file for a scan and (2) XML files for measurements
+        :param scan_list:
+        :return:
+        """
+        # Check
+        if self._expNumber is None:
+            raise RuntimeError('Experiment number is not set up for controller.')
+
+        error_message = ''
+
+        for scan_no in scan_list:
+            # Download single spice file for a run
+            status, ret_obj = self.download_spice_file(exp_number=self._expNumber,
+                                                       scan_number=scan_no,
+                                                       over_write=overwrite)
+
+            # Reject if SPICE file cannot download
+            if status is False:
+                error_message += '%s\n' % ret_obj
+                continue
+
+            # Load SPICE file to Mantid
+            spice_file_name = ret_obj
+            status, ret_obj = self.load_spice_scan_file(self._expNumber, scan_no, spice_file_name)
+            if status is False:
+                error_message = ret_obj
+                return False, error_message
+            else:
+                spice_table = self._mySpiceTableDict[(self._expNumber, scan_no)]
+                assert spice_table
+            pt_no_list = self._get_pt_list_from_spice_table(spice_table)
+
+            # Download all single-measurement file
+            for pt_no in pt_no_list:
+                status, ret_obj = self.download_spice_xml_file(scan_no, pt_no, overwrite=overwrite)
+                if status is False:
+                    error_message += '%s\n' % ret_obj
+            # END-FOR
+        # END-FOR (scan_no)
+
+        return True, error_message
+
+    def existDataFile(self, scanno, ptno):
+        """
+        Check whether data file for a scan or pt number exists
+        :param scanno:
+        :param ptno:
+        :return:
+        """
+        # Check spice file
+        spice_file_name = '%s_exp%04d_scan%04d.dat'%(self._instrumentName,
+                                                   self._expNumber, scanno)
+        spice_file_name = os.path.join(self._dataDir, spice_file_name)
+        if os.path.exists(spice_file_name) is False:
+            return False, 'Spice data file %s cannot be found.'% spice_file_name
+
+        # Check xml file
+        xmlfilename = '%s_exp%d_scan%04d_%04d.xml'%(self._instrumentName, self._expNumber,
+                scanno, ptno)
+        xmlfilename = os.path.join(self._dataDir, xmlfilename)
+        if os.path.exists(xmlfilename) is False:
+            return (False, "Pt. XML file %s cannot be found."%(xmlfilename))
+
+        return True, ""
+
+    def find_peak(self, exp_number, scan_number, pt_number):
+        """ Find 1 peak in sample Q space for UB matrix
+        :param scan_number:
+        :param pt_number:
+        :return:tuple as (boolean, object) such as (false, error message) and (true, PeakInfo object)
+
+        This part will be redo as 11847_Load_HB3A_Experiment
+        """
+        # Check
+        assert isinstance(exp_number, int)
+        assert isinstance(scan_number, int)
+        assert isinstance(pt_number, int)
+
+        # Download or make sure data are there
+        status_sp, err_msg_sp = self.download_spice_file(exp_number, scan_number, over_write=False)
+        status_det, err_msg_det = self.download_spice_xml_file(scan_number, pt_number, exp_number,
+                                                               overwrite=False)
+        if status_sp is False or status_det is False:
+            return False, 'Unable to access data (1) %s (2) %s' % (err_msg_sp, err_msg_det)
+
+        # Collect reduction information: example
+        exp_info_ws_name = get_pt_info_ws_name(exp_number, scan_number)
+        virtual_instrument_info_table_name = get_virtual_instrument_table_name(exp_number, scan_number, pt_number)
+        api.CollectHB3AExperimentInfo(
+            ExperimentNumber=exp_number,
+            GenerateVirtualInstrument=False,
+            ScanList=[scan_number],
+            PtLists=[-1, pt_number],
+            DataDirectory=self._dataDir,
+            GetFileFromServer=False,
+            Detector2ThetaTolerance=0.01,
+            OutputWorkspace=exp_info_ws_name,
+            DetectorTableWorkspace=virtual_instrument_info_table_name)
+
+        # Load XML file to MD
+        pt_md_ws_name = get_single_pt_md_name(exp_number, scan_number, pt_number)
+        api.ConvertCWSDExpToMomentum(InputWorkspace=exp_info_ws_name,
+                                     CreateVirtualInstrument=False,
+                                     OutputWorkspace=pt_md_ws_name,
+                                     Directory=self._dataDir)
+
+        # Find peak in Q-space
+        pt_peak_ws_name = get_single_pt_peak_ws_name(exp_number, scan_number, pt_number)
+        api.FindPeaksMD(InputWorkspace=pt_md_ws_name, MaxPeaks=10,
+                        DensityThresholdFactor=0.01, OutputWorkspace=pt_peak_ws_name)
+        peak_ws = AnalysisDataService.retrieve(pt_peak_ws_name)
+        pt_md_ws = AnalysisDataService.retrieve(pt_md_ws_name)
+        self._myPtMDDict[(exp_number, scan_number, pt_number)] = pt_md_ws
+
+        num_peaks = peak_ws.getNumberPeaks()
+        if num_peaks != 1:
+            err_msg = 'Find %d peak from scan %d pt %d.  ' \
+                      'For UB matrix calculation, 1 and only 1 peak is allowed' % (num_peaks, scan_number, pt_number)
+            return False, err_msg
+        else:
+            self._add_ub_peak_ws(exp_number, scan_number, pt_number, peak_ws)
+            status, ret_obj = self.add_peak_info(exp_number, scan_number, pt_number)
+            if status is True:
+                pass
+                # peak_info = ret_obj
+                # peak_info.set_md_ws(pt_md_ws)
+            else:
+                err_msg = ret_obj
+                return False, err_msg
+
+        return True, ''
+
+    def get_experiment(self):
+        """
+        Get experiment number
+        :return:
+        """
+        return self._expNumber
+
+    def get_pt_numbers(self, exp_no, scan_no, load_spice_scan=False):
+        """ Get Pt numbers (as a list) for a scan in an experiment
+        :param exp_no:
+        :param scan_no:
+        :param load_spice_scan:
+        :return: (Boolean, Object) as (status, pt number list/error message)
+        """
+        # Check
+        if exp_no is None:
+            exp_no = self._expNumber
+        assert isinstance(exp_no, int)
+        assert isinstance(scan_no, int)
+
+        # Get workspace
+        table_ws = self._get_spice_workspace(exp_no, scan_no)
+        if table_ws is None:
+            if load_spice_scan is False:
+                return False, 'Spice file for Exp %d Scan %d is not loaded.' % (exp_no, scan_no)
+            else:
+                status, error_message = self.load_spice_scan_file(exp_no, scan_no)
+                if status is True:
+                    table_ws = self._get_spice_workspace(exp_no, scan_no)
+                    if table_ws is None:
+                        raise NotImplementedError('Logic error! Cannot happen!')
+                else:
+                    return False, 'Unable to load Spice file for Exp %d Scan %d due to %s.' % (
+                        exp_no, scan_no, error_message)
+
+        col_name_list = table_ws.getColumnNames()
+        i_pt = col_name_list.index('Pt.')
+        if i_pt < 0 or i_pt >= len(col_name_list):
+            return False, 'No column with name Pt. can be found in SPICE table.'
+
+        pt_number_list = []
+        num_rows = table_ws.rowCount()
+        for i in xrange(num_rows):
+            pt_number = table_ws.cell(i, i_pt)
+            pt_number_list.append(pt_number)
+
+        return True, pt_number_list
+
+    def get_raw_detector_counts(self, exp_no, scan_no, pt_no):
+        """
+        Get counts on raw detector
+        :param scan_no:
+        :param pt_no:
+        :return: boolean, 2D numpy data
+        """
+        # Get workspace (in memory or loading)
+        raw_ws = self.get_raw_data_workspace(exp_no, scan_no, pt_no)
+        if raw_ws is None:
+            return False, 'Raw data for Exp %d Scan %d Pt %d is not loaded.' % (exp_no, scan_no, pt_no)
+
+        # Convert to numpy array
+        array2d = numpy.ndarray(shape=(DET_X_SIZE, DET_Y_SIZE), dtype='float')
+        for i in xrange(DET_X_SIZE):
+            for j in xrange(DET_Y_SIZE):
+                array2d[i][j] = raw_ws.readY(i * DET_X_SIZE + j)[0]
+
+        return array2d
+
+    def get_sample_log_value(self, exp_number, scan_number, pt_number, log_name):
+        """
+        Get sample log's value
+        :param exp_number:
+        :param scan_number:167
+        :param pt_number:
+        :param log_name:
+        :return: float
+        """
+        assert isinstance(exp_number, int)
+        assert isinstance(scan_number, int)
+        assert isinstance(pt_number, int)
+        assert isinstance(log_name, str)
+        try:
+            md_ws = self._myPtMDDict[(exp_number, scan_number, pt_number)]
+        except KeyError as ke:
+            return 'Unable to find log value %s due to %s.' % (log_name, str(ke))
+
+        return md_ws.getExperimentInfo(0).run().getProperty(log_name).value
+
+    def get_peak_info(self, exp_number, scan_number, pt_number):
+        """
+        get peak information instance
+        :param exp_number: experiment number.  if it is None, then use the current exp number
+        :param scan_number:
+        :param pt_number:
+        :return:
+        """
+        # Check for type
+        if exp_number is None:
+            exp_number = self._expNumber
+
+        assert isinstance(exp_number, int)
+        assert isinstance(scan_number, int)
+        assert isinstance(pt_number, int)
+
+        # Check for existence
+        if (exp_number, scan_number, pt_number) not in self._myUBPeakWSDict:  # self._myPeakInfoDict:
+            err_msg = 'Unable to find PeakInfo for Exp %d Scan %d Pt %d. ' \
+                      'Existing keys are %s' % (exp_number, scan_number, pt_number,
+                                                str(self._myUBPeakWSDict.keys()))
+            return False, err_msg
+
+        print '[DB] PeakInfoDictionary Keys = %s' % str(self._myPeakInfoDict.keys())
+
+        return True, self._myPeakInfoDict[(exp_number, scan_number, pt_number)]
+
+    def get_ub_peak_ws(self, exp_number, scan_number, pt_number):
+        """
+        Get peak workspace for the peak picked to calculate UB matrix
+        :param exp_number:
+        :param scan_number:
+        :param pt_number:
+        :return:
+        """
+        assert isinstance(exp_number, int)
+        assert isinstance(scan_number, int)
+        assert isinstance(pt_number, int)
+
+        if (exp_number, scan_number, pt_number) not in self._myUBPeakWSDict:
+            return False, 'Exp %d Scan %d Pt %d has no peak workspace.' % (exp_number,
+                                                                           scan_number,
+                                                                           pt_number)
+
+        return True, self._myUBPeakWSDict[(exp_number, scan_number, pt_number)]
+
+    def index_peak(self, ub_matrix, scan_number, pt_number):
+        """ Index peaks in a Pt.
+        :param ub_matrix: numpy.ndarray (3, 3)
+        :param scan_number:
+        :param pt_number:
+        :return: boolean, object (list of HKL or error message)
+        """
+        # Check
+        assert isinstance(ub_matrix, numpy.ndarray)
+        assert ub_matrix.shape == (3, 3)
+        assert isinstance(scan_number, int)
+        assert isinstance(pt_number, int)
+
+        # Find out the peak workspace
+        exp_num = self._expNumber
+        if (exp_num, scan_number, pt_number) in self._myUBPeakWSDict is False:
+            err_msg = 'No PeakWorkspace is found for exp %d scan %d pt %d' % (
+                exp_num, scan_number, pt_number)
+            return False, err_msg
+
+        peak_ws = self._myUBPeakWSDict[(exp_num, scan_number, pt_number)]
+        ub_1d = ub_matrix.reshape(9,)
+        print '[DB] UB matrix = ', ub_1d
+
+        # Set UB
+        api.SetUB(Workspace=peak_ws, UB=ub_1d)
+
+        # Note: IndexPeaks and CalcualtePeaksHKL do the same job
+        #       while IndexPeaks has more control on the output
+        num_peak_index, error = api.IndexPeaks(PeaksWorkspace=peak_ws,
+                                               Tolerance=0.4,
+                                               RoundHKLs=False)
+
+        if num_peak_index == 0:
+            return False, 'No peak can be indexed.'
+        elif num_peak_index > 1:
+            raise RuntimeError('Case for PeaksWorkspace containing more than 1 peak is not '
+                               'considered. Contact developer for this issue.')
+        else:
+            hkl_v3d = peak_ws.getPeak(0).getHKL()
+            hkl = [hkl_v3d.X(), hkl_v3d.Y(), hkl_v3d.Z()]
+
+        return True, (hkl, error)
+
+    def load_spice_scan_file(self, exp_no, scan_no, spice_file_name=None):
+        """
+        Load a SPICE scan file to table workspace and run information matrix workspace.
+        :param scan_no:
+        :param spice_file_name:
+        :return: status (boolean), error message (string)
+        """
+        # Default for exp_no
+        if exp_no is None:
+            exp_no = self._expNumber
+
+        # Check whether the workspace has been loaded
+        assert isinstance(exp_no, int)
+        assert isinstance(scan_no, int)
+        out_ws_name = get_spice_table_name(exp_no, scan_no)
+        if (exp_no, scan_no) in self._mySpiceTableDict:
+            return True, out_ws_name
+
+        # Form standard name for a SPICE file if name is not given
+        if spice_file_name is None:
+            spice_file_name = os.path.join(self._dataDir, get_spice_file_name(exp_no, scan_no))
+
+        # Download SPICE file if necessary
+        if os.path.exists(spice_file_name) is False:
+            self.download_spice_file(exp_no, scan_no, over_write=True)
+
+        try:
+            spice_table_ws, info_matrix_ws = api.LoadSpiceAscii(Filename=spice_file_name,
+                                                                OutputWorkspace=out_ws_name,
+                                                                RunInfoWorkspace='TempInfo')
+            api.DeleteWorkspace(Workspace=info_matrix_ws)
+        except RuntimeError as run_err:
+            return False, 'Unable to load SPICE data %s due to %s' % (spice_file_name, str(run_err))
+
+        # Store
+        self._add_spice_workspace(exp_no, scan_no, spice_table_ws)
+
+        return True, out_ws_name
+
+    def load_spice_xml_file(self, exp_no, scan_no, pt_no, xml_file_name=None):
+        """
+        Load SPICE's XML file to
+        :param scan_no:
+        :param pt_no:
+        :return:
+        """
+        # Form XMIL file as ~/../HB3A_exp355_scan%04d_%04d.xml'%(scan_no, pt)
+        if xml_file_name is None:
+            xml_file_name = os.path.join(self._dataDir,
+                                         'HB3A_exp%d_scan%04d_%04d.xml' % (exp_no, scan_no, pt_no))
+
+        # Get spice table
+        spice_table_ws = self._get_spice_workspace(exp_no, scan_no)
+        assert isinstance(spice_table_ws, mantid.dataobjects.TableWorkspace)
+        spice_table_name = spice_table_ws.name()
+
+        # Load SPICE Pt. file
+        # spice_table_name = 'Table_Exp%d_Scan%04d' % (exp_no, scan_no)
+        pt_ws_name = get_raw_data_workspace_name(exp_no, scan_no, pt_no)
+        try:
+            ret_obj = api.LoadSpiceXML2DDet(Filename=xml_file_name,
+                                            OutputWorkspace=pt_ws_name,
+                                            DetectorGeometry='256,256',
+                                            SpiceTableWorkspace=spice_table_name,
+                                            PtNumber=pt_no)
+        except RuntimeError as run_err:
+            return False, str(run_err)
+
+        pt_ws = ret_obj
+
+        # Add data storage
+        self._add_raw_workspace(exp_no, scan_no, pt_no, pt_ws)
+
+        return True, pt_ws_name
+
+    def group_workspaces(self, exp_number, group_name):
+        """
+
+        :return:
+        """
+        # Find out the input workspace name
+        ws_names_str = ''
+        for key in self._myRawDataWSDict.keys():
+            if key[0] == exp_number:
+                ws_names_str += '%s,' % self._myRawDataWSDict[key].name()
+
+        for key in self._mySpiceTableDict.keys():
+            if key[0] == exp_number:
+                ws_names_str += '%s,' % self._mySpiceTableDict[key].name()
+
+        # Check
+        if len(ws_names_str) == 0:
+            return False, 'No workspace is found for experiment %d.' % exp_number
+
+        # Remove last ','
+        ws_names_str = ws_names_str[:-1]
+
+        # Group
+        api.GroupWorkspaces(InputWorkspaces=ws_names_str,
+                            OutputWorkspace=group_name)
+
+        return
+
+    def merge_pts_in_scan(self, exp_no, scan_no, target_ws_name, target_frame):
+        """
+        Merge Pts in Scan
+        All the workspaces generated as internal results will be grouped
+        :param exp_no:
+        :param scan_no:
+        :param target_ws_name:
+        :param target_frame:
+        :return: (merged workspace name, workspace group name)
+        """
+        # Check
+        if exp_no is None:
+            exp_no = self._expNumber
+        assert isinstance(exp_no, int)
+        assert isinstance(scan_no, int)
+        assert isinstance(target_frame, str)
+        assert isinstance(target_ws_name, str)
+
+        ub_matrix_1d = None
+
+        # Target frame
+        if target_frame.lower().startswith('hkl'):
+            target_frame = 'hkl'
+            ub_matrix_1d = self._myUBMatrixDict[self._expNumber].reshape(9,)
+        elif target_frame.lower().startswith('q-sample'):
+            target_frame = 'qsample'
+
+        else:
+            raise RuntimeError('Target frame %s is not supported.' % target_frame)
+
+        # Process data and save
+        status, pt_num_list = self.get_pt_numbers(exp_no, scan_no, True)
+        if status is False:
+            err_msg = pt_num_list
+            return False, err_msg
+        else:
+            print '[DB] Number of Pts for Scan %d is %d' % (scan_no, len(pt_num_list))
+            print '[DB] Data directory: %s' % self._dataDir
+        max_pts = 0
+        ws_names_str = ''
+        ws_names_to_group = ''
+
+        for pt in pt_num_list:
+            try:
+                self.download_spice_xml_file(scan_no, pt, overwrite=False)
+                api.CollectHB3AExperimentInfo(ExperimentNumber=exp_no, ScanList='%d' % scan_no, PtLists='-1,%d' % pt,
+                                              DataDirectory=self._dataDir,
+                                              GenerateVirtualInstrument=False,
+                                              OutputWorkspace='ScanPtInfo_Exp%d_Scan%d' % (exp_no, scan_no),
+                                              DetectorTableWorkspace='MockDetTable')
+
+                out_q_name = 'HB3A_Exp%d_Scan%d_Pt%d_MD' % (exp_no, scan_no, pt)
+                api.ConvertCWSDExpToMomentum(InputWorkspace='ScanPtInfo_Exp406_Scan%d' % scan_no,
+                                             CreateVirtualInstrument=False,
+                                             OutputWorkspace=out_q_name,
+                                             Directory=self._dataDir)
+
+                ws_names_to_group += out_q_name + ','
+                if target_frame == 'hkl':
+                    out_hkl_name = 'HKL_Scan%d_Pt%d' % (scan_no, pt)
+                    api.ConvertCWSDMDtoHKL(InputWorkspace=out_q_name,
+                                           UBMatrix=ub_matrix_1d,
+                                           OutputWorkspace=out_hkl_name)
+                    ws_names_str += out_hkl_name + ','
+                    ws_names_to_group += out_hkl_name + ','
+                else:
+                    ws_names_str += out_q_name + ','
+
+            except RuntimeError as e:
+                print '[Error] Reducing scan %d pt %d due to %s' % (scan_no, pt, str(e))
+                continue
+
+            else:
+                max_pts = pt
+        # END-FOR
+
+        # Merge
+        if target_frame == 'qsample':
+            out_ws_name = target_ws_name + '_QSample'
+        elif target_frame == 'hkl':
+            out_ws_name = target_ws_name + '_HKL'
+        else:
+            raise RuntimeError('Impossible to have target frame %s' % target_frame)
+
+        ws_names_str = ws_names_str[:-1]
+        api.MergeMD(InputWorkspaces=ws_names_str, OutputWorkspace=out_ws_name, SplitInto=max_pts)
+
+        # Group workspaces
+        group_name = 'Group_Exp406_Scan%d' % scan_no
+        api.GroupWorkspaces(InputWorkspaces=ws_names_to_group, OutputWorkspace=group_name)
+        spice_table_name = get_spice_table_name(exp_no, scan_no)
+        api.GroupWorkspaces(InputWorkspaces='%s,%s' % (group_name, spice_table_name), OutputWorkspace=group_name)
+
+        ret_tup = out_ws_name, group_name
+
+        return ret_tup
+
+    def set_server_url(self, server_url):
+        """
+        Set URL for server to download the data
+        :param server_url:
+        :return:
+        """
+        # Server URL must end with '/'
+        self._myServerURL = str(server_url)
+        if self._myServerURL.endswith('/') is False:
+            self._myServerURL += '/'
+
+        # Test URL valid or not
+        is_url_good = False
+        error_message = None
+        try:
+            result = urllib2.urlopen(self._myServerURL)
+        except urllib2.HTTPError, err:
+            error_message = str(err.code)
+        except urllib2.URLError, err:
+            error_message = str(err.args)
+        else:
+            is_url_good = True
+            result.close()
+
+        if error_message is None:
+            error_message = ''
+        else:
+            error_message = 'Unable to open data server URL: %s due to %s.' % (server_url, error_message)
+
+        return is_url_good, error_message
+
+    def setWebAccessMode(self, mode):
+        """
+        Set data access mode form server
+        :param mode:
+        :return:
+        """
+        if isinstance(mode, str) is False:
+            raise RuntimeError('Input mode is not string')
+
+        if mode == 'cache':
+            self._cacheDataOnly = True
+        elif mode == 'download':
+            self._cacheDataOnly = False
+
+        return
+
+    def set_local_data_dir(self, local_dir):
+        """
+        Set local data storage
+        :param local_dir:
+        :return:
+        """
+        # Get absolute path
+        if os.path.isabs(local_dir) is False:
+            # Input is relative path to current working directory
+            cwd = os.getcwd()
+            local_dir = os.path.join(cwd, local_dir)
+
+        # Create cache directory if necessary
+        if os.path.exists(local_dir) is False:
+            try:
+                os.mkdir(local_dir)
+            except OSError as os_err:
+                return False, str(os_err)
+
+        # Check whether the target is writable
+        if os.access(local_dir, os.W_OK) is False:
+            return False, 'Specified local data directory %s is not writable.' % local_dir
+
+        # Successful
+        self._dataDir = local_dir
+
+        return True, ''
+
+    def set_ub_matrix(self, exp_number, ub_matrix):
+        """
+        Set up UB matrix to _UBMatrix dictionary
+        :param exp_number:
+        :param ub_matrix:
+        :return:
+        """
+        # Check
+        if exp_number is None:
+            exp_number = self._expNumber
+
+        assert isinstance(exp_number, int)
+        assert isinstance(ub_matrix, numpy.ndarray)
+        assert ub_matrix.shape == (3, 3)
+
+        # Set up
+        self._myUBMatrixDict[exp_number] = ub_matrix
+
+    def set_working_directory(self, work_dir):
+        """
+        Set up the directory for working result
+        :return: (boolean, string)
+        """
+        if os.path.exists(work_dir) is False:
+            try:
+                os.mkdir(work_dir)
+            except OSError as os_err:
+                return False, 'Unable to create working directory %s due to %s.' % (work_dir, str(os_err))
+        elif os.access(work_dir, os.W_OK) is False:
+            return False, 'User specified working directory %s is not writable.' % work_dir
+
+        self._workDir = work_dir
+
+        return True, ''
+
+    def set_instrument_name(self, instrument_name):
+        """
+        Set instrument name
+        :param instrument_name:
+        :return:
+        """
+        # Check
+        if isinstance(instrument_name, str) is False:
+            return False, 'Input instrument name is not a string but of type %s.' % str(type(instrument_name))
+        if len(instrument_name) == 0:
+            return False, 'Input instrument name is an empty string.'
+
+        self._instrumentName = instrument_name
+
+        return True, ''
+
+    def set_exp_number(self, exp_number):
+        """ Add experiment number
+        :param exp_number:
+        :return:
+        """
+        assert isinstance(exp_number, int)
+        self._expNumber = exp_number
+
+        return True
+
+    def set_hkl_to_peak(self, exp_number, scan_number, pt_number):
+        """
+        Get HKL as _h, _k, _l from MDEventWorkspace.  It is for HB3A only
+        :return:
+        """
+        status, peak_info = self.get_peak_info(exp_number, scan_number, pt_number)
+        if status is False:
+            err_msg = peak_info
+            return False, err_msg
+
+        md_ws = self._myPtMDDict[(exp_number, scan_number, pt_number)]
+        assert md_ws.getNumExperimentInfo() == 1
+        exp_info = md_ws.getExperimentInfo(0)
+
+        try:
+            m_h = float(exp_info.run().getProperty('_h').value)
+            m_k = float(exp_info.run().getProperty('_k').value)
+            m_l = float(exp_info.run().getProperty('_l').value)
+        except RuntimeError as error:
+            return False, 'Unable to retrieve HKL due to %s.' % (str(error))
+
+        peak_ws = peak_info.get_peak_workspace()
+        peak = peak_ws.getPeak(0)
+        peak.setHKL(m_h, m_k, m_l)
+
+        return True, (m_h, m_k, m_l)
+
+    def _add_raw_workspace(self, exp_no, scan_no, pt_no, raw_ws):
+        """ Add raw Pt.'s workspace
+        :param exp_no:
+        :param scan_no:
+        :param pt_no:
+        :param raw_ws: workspace or name of the workspace
+        :return: None
+        """
+        # Check
+        assert isinstance(exp_no, int)
+        assert isinstance(scan_no, int)
+        assert isinstance(pt_no, int)
+
+        if isinstance(raw_ws, str):
+            # Given by name
+            matrix_ws = AnalysisDataService.retrieve(raw_ws)
+        else:
+            matrix_ws = raw_ws
+        assert isinstance(matrix_ws, mantid.dataobjects.Workspace2D)
+
+        self._myRawDataWSDict[(exp_no, scan_no, pt_no)] = matrix_ws
+
+        return
+
+    def _add_md_workspace(self, exp_no, scan_no, pt_no, md_ws):
+        """
+         Add MD workspace to storage
+        :param exp_no:
+        :param scan_no:
+        :param pt_no:
+        :param md_ws:
+        :return:
+        """
+        # Check input
+        print '[DB] Type of md_ws is %s.' % str(type(md_ws))
+        assert isinstance(md_ws, mantid.dataobjects.MDEventWorkspace)
+
+        assert isinstance(exp_no, int)
+        assert isinstance(scan_no, int)
+        assert isinstance(pt_no)
+
+        self._myPtMDDict[(exp_no, scan_no, pt_no)] = md_ws
+
+        return
+
+    def _add_ub_peak_ws(self, exp_number, scan_number, pt_number, peak_ws):
+        """
+        Add peak workspace for UB matrix
+        :param exp_number:
+        :param scan_number:
+        :param pt_number:
+        :param peak_ws:
+        :return:
+        """
+        # Check
+        assert isinstance(peak_ws, mantid.dataobjects.PeaksWorkspace)
+
+        assert isinstance(exp_number, int)
+        assert isinstance(scan_number, int)
+        assert isinstance(pt_number, int)
+
+        # Add
+        self._myUBPeakWSDict[(exp_number, scan_number, pt_number)] = peak_ws
+
+        return
+
+    def _add_spice_workspace(self, exp_no, scan_no, spice_table_ws):
+        """
+        """
+        assert isinstance(exp_no, int)
+        assert isinstance(scan_no, int)
+        assert isinstance(spice_table_ws, mantid.dataobjects.TableWorkspace)
+        self._mySpiceTableDict[(exp_no, scan_no)] = spice_table_ws
+
+        return
+
+    def _get_spice_workspace(self, exp_no, scan_no):
+        """ Get SPICE's scan table workspace
+        :param exp_no:
+        :param scan_no:
+        :return: Table workspace or None
+        """
+        try:
+            ws = self._mySpiceTableDict[(exp_no, scan_no)]
+        except KeyError:
+            print '[DB] Keys to SPICE TABLE: %s' % str(self._mySpiceTableDict.keys())
+            return None
+
+        return ws
+
+    def get_raw_data_workspace(self, exp_no, scan_no, pt_no):
+        """ Get raw workspace
+        """
+        try:
+            ws = self._myRawDataWSDict[(exp_no, scan_no, pt_no)]
+            assert isinstance(ws, mantid.dataobjects.Workspace2D)
+        except KeyError:
+            return None
+
+        return ws
+
+    def _get_pt_list_from_spice_table(self, spice_table_ws):
+        """
+        Get list of Pt. from a SPICE table workspace
+        :param spice_table_ws: SPICE table workspace
+        :return: list of Pt.
+        """
+        numrows = spice_table_ws.rowCount()
+        ptlist = []
+        for irow in xrange(numrows):
+            ptno = int(spice_table_ws.cell(irow, 0))
+            ptlist.append(ptno)
+
+        return ptlist
+
+
+def get_spice_file_name(exp_number, scan_number):
+    """
+    Get standard HB3A SPICE file name from experiment number and scan number
+    :param exp_number:
+    :param scan_num:
+    :return:
+    """
+    file_name = 'HB3A_exp%04d_scan%04d.dat' % (exp_number, scan_number)
+
+    return file_name
+
+
+def get_spice_table_name(exp_number, scan_number):
+    """ Form the name of the table workspace for SPICE
+    :param exp_number:
+    :param scan_number:
+    :return:
+    """
+    table_name = 'HB3A_%03d_%04d_SpiceTable' % (exp_number, scan_number)
+
+    return table_name
+
+
+def get_raw_data_workspace_name(exp_number, scan_number, pt_number):
+    """ Form the name of the matrix workspace to which raw pt. XML file is loaded
+    :param exp_number:
+    :param scan_number:
+    :param pt_number:
+    :return:
+    """
+    ws_name = 'HB3A_exp%d_scan%04d_%04d' % (exp_number, scan_number, pt_number)
+
+    return ws_name
+
+
+def get_pt_info_ws_name(exp_number, scan_number):
+    """
+    Information table workspace'name from CollectHB3AInfo
+    :param exp_number:
+    :param scan_number:
+    :param pt_number:
+    :return:
+    """
+    ws_name = 'ScanPtInfo_Exp%d_Scan%d'  % (exp_number, scan_number)
+
+    return ws_name
+
+
+def get_single_pt_peak_ws_name(exp_number, scan_number, pt_number):
+    """
+    Form the name of the peak workspace
+    :param exp_number:
+    :param scan_number:
+    :param pt_number:
+    :return:
+    """
+    ws_name = 'Peak_Exp%d_Scan%d_Pt%d' % (exp_number, scan_number, pt_number)
+
+    return ws_name
+
+
+def get_single_pt_md_name(exp_number, scan_number, pt_number):
+    """ Form the name of the MDEvnetWorkspace for a single Pt. measurement
+    :param exp_number:
+    :param scan_number:
+    :param pt_number:
+    :return:
+    """
+    ws_name = 'HB3A_Exp%d_Scan%d_Pt%d_MD' % (exp_number, scan_number, pt_number)
+
+    return ws_name
+
+
+def get_virtual_instrument_table_name(exp_number, scan_number, pt_number):
+    """
+    Generate the name of the table workspace containing the virtual instrument information
+    :param exp_number:
+    :param scan_number:
+    :param pt_number:
+    :return:
+    """
+    ws_name = 'VirtualInstrument_Exp%d_Scan%d_Pt%d_Table' % (exp_number, scan_number, pt_number)
+
+    return ws_name
diff --git a/scripts/HFIR_4Circle_Reduction/reduce4circleGUI.py b/scripts/HFIR_4Circle_Reduction/reduce4circleGUI.py
new file mode 100644
index 0000000000000000000000000000000000000000..7009c1e8b8ec763ec515120f212242332cf5e2b9
--- /dev/null
+++ b/scripts/HFIR_4Circle_Reduction/reduce4circleGUI.py
@@ -0,0 +1,1092 @@
+#pylint: disable=invalid-name,relative-import,W0611,R0921,R0902,R0904,R0921,C0302
+################################################################################
+#
+# MainWindow application for reducing HFIR 4-circle
+#
+################################################################################
+import os
+import math
+import csv
+import time
+
+from PyQt4 import QtCore, QtGui
+
+import reduce4circleControl as r4c
+import guiutility as gutil
+import fourcircle_utility as fcutil
+
+try:
+    _fromUtf8 = QtCore.QString.fromUtf8
+except AttributeError:
+    def _fromUtf8(s):
+        return s
+
+# import line for the UI python class
+from ui_MainWindow import Ui_MainWindow
+
+
+class MainWindow(QtGui.QMainWindow):
+    """ Class of Main Window (top)
+    """
+    def __init__(self, parent=None):
+        """ Initialization and set up
+        """
+        # Base class
+        QtGui.QMainWindow.__init__(self,parent)
+
+        # UI Window (from Qt Designer)
+        self.ui = Ui_MainWindow()
+        self.ui.setupUi(self)
+
+        # Mantid configuration
+        self._instrument = str(self.ui.comboBox_instrument.currentText())
+        # config = ConfigService.Instance()
+        # self._instrument = config["default.instrument"]
+
+        # Event handling definitions
+        # Top
+        self.connect(self.ui.pushButton_setExp, QtCore.SIGNAL('clicked()'),
+                     self.do_set_experiment)
+
+        # Tab 'Data Access'
+        self.connect(self.ui.pushButton_applySetup, QtCore.SIGNAL('clicked()'),
+                     self.do_apply_setup)
+        self.connect(self.ui.pushButton_browseLocalDataDir, QtCore.SIGNAL('clicked()'),
+                     self.do_browse_local_spice_data)
+        self.connect(self.ui.pushButton_testURLs, QtCore.SIGNAL('clicked()'),
+                     self.do_test_url)
+        self.connect(self.ui.pushButton_ListScans, QtCore.SIGNAL('clicked()'),
+                     self.do_list_scans)
+        self.connect(self.ui.pushButton_downloadExpData, QtCore.SIGNAL('clicked()'),
+                     self.do_download_spice_data)
+        self.connect(self.ui.comboBox_mode, QtCore.SIGNAL('currentIndexChanged(int)'),
+                     self.change_data_access_mode)
+
+        # Tab 'View Raw Data'
+        self.connect(self.ui.pushButton_setScanInfo, QtCore.SIGNAL('clicked()'),
+                     self.do_load_scan_info)
+        self.connect(self.ui.pushButton_plotRawPt, QtCore.SIGNAL('clicked()'),
+                     self.do_plot_pt_raw)
+        self.connect(self.ui.pushButton_prevPtNumber, QtCore.SIGNAL('clicked()'),
+                     self.do_plot_prev_pt_raw)
+        self.connect(self.ui.pushButton_nextPtNumber, QtCore.SIGNAL('clicked()'),
+                     self.do_plot_next_pt_raw)
+        self.connect(self.ui.pushButton_showPtList, QtCore.SIGNAL('clicked()'),
+                     self.show_scan_pt_list)
+        self.connect(self.ui.pushButton_usePt4UB, QtCore.SIGNAL('clicked()'),
+                     self.do_add_peak_to_find)
+
+        # Tab 'calculate ub matrix'
+        self.connect(self.ui.pushButton_findPeak, QtCore.SIGNAL('clicked()'),
+                     self.do_find_peak)
+        self.connect(self.ui.pushButton_addPeakToCalUB, QtCore.SIGNAL('clicked()'),
+                     self.do_add_ub_peak)
+        self.connect(self.ui.pushButton_calUB, QtCore.SIGNAL('clicked()'),
+                     self.do_cal_ub_matrix)
+        self.connect(self.ui.pushButton_acceptUB, QtCore.SIGNAL('clicked()'),
+                     self.doAcceptCalUB)
+        self.connect(self.ui.pushButton_indexUBPeaks, QtCore.SIGNAL('clicked()'),
+                     self.do_index_ub_peaks)
+        self.connect(self.ui.pushButton_deleteUBPeak, QtCore.SIGNAL('clicked()'),
+                     self.do_del_ub_peaks)
+        self.connect(self.ui.pushButton_clearUBPeakTable, QtCore.SIGNAL('clicked()'),
+                     self.do_clear_ub_peaks)
+        self.connect(self.ui.pushButton_resetPeakHKLs, QtCore.SIGNAL('clicked()'),
+                     self.do_reset_ub_peaks_hkl)
+
+        # Tab 'Slice View'
+        self.connect(self.ui.pushButton_setUBSliceView, QtCore.SIGNAL('clicked()'),
+                     self.do_set_ub_sv)
+        self.connect(self.ui.pushButton_process4SliceView, QtCore.SIGNAL('clicked()'),
+                     self.do_merge_scans)
+
+        # Tab 'Advanced'
+        self.connect(self.ui.pushButton_useDefaultDir, QtCore.SIGNAL('clicked()'),
+                     self.do_setup_dir_default)
+        self.connect(self.ui.pushButton_browseLocalCache, QtCore.SIGNAL('clicked()'),
+                     self.do_browse_local_cache_dir)
+        self.connect(self.ui.pushButton_browseWorkDir, QtCore.SIGNAL('clicked()'),
+                     self.do_browse_working_dir)
+        self.connect(self.ui.comboBox_instrument, QtCore.SIGNAL('currentIndexChanged(int)'),
+                     self.change_instrument_name)
+
+        # Refine UB matrix
+        self.connect(self.ui.pushButton_addToRefine, QtCore.SIGNAL('clicked()'),
+                     self.do_refine_ub)
+        self.connect(self.ui.pushButton_addAllRefineUB, QtCore.SIGNAL('clicked()'),
+                     self.do_refine_ub)
+        self.connect(self.ui.pushButton_acceptRefinedUB, QtCore.SIGNAL('clicked()'),
+                     self.do_refine_ub)
+        self.connect(self.ui.pushButton_resetRefinedUB, QtCore.SIGNAL('clicked()'),
+                     self.do_refine_ub)
+
+        # Tab 'Integrate Peaks'
+        self.connect(self.ui.pushButton_integratePeak, QtCore.SIGNAL('clicked()'),
+                     self.do_integrate_peaks)
+
+        # Menu
+        self.connect(self.ui.actionExit, QtCore.SIGNAL('triggered()'),
+                     self.menu_quit)
+
+        self.connect(self.ui.actionSave_Session, QtCore.SIGNAL('triggered()'),
+                     self.save_current_session)
+        self.connect(self.ui.actionLoad_Session, QtCore.SIGNAL('triggered()'),
+                     self.load_session)
+
+        # Event handling for tab 'refine ub matrix'
+        self.connect(self.ui.pushButton_addToRefine, QtCore.SIGNAL('clicked()'),
+                     self.doAddScanPtToRefineUB)
+
+        # Validator ... (NEXT)
+
+        # Declaration of class variable
+        # some configuration
+        self._homeSrcDir = os.getcwd()
+        self._homeDir = os.getcwd()
+
+        # Control
+        self._myControl = r4c.CWSCDReductionControl(self._instrument)
+        self._allowDownload = True
+        self._dataAccessMode = 'Download'
+
+        # Initial setup
+        self.ui.tabWidget.setCurrentIndex(0)
+        self.ui.tabWidget.setTabEnabled(4, False)
+        self.ui.tabWidget.setTabEnabled(5, False)
+        self._init_ub_table()
+        self.ui.radioButton_ubFromTab1.setChecked(True)
+
+        # Tab 'Access'
+        self.ui.lineEdit_url.setText('http://neutron.ornl.gov/user_data/hb3a/')
+        self.ui.comboBox_mode.setCurrentIndex(0)
+        self.ui.lineEdit_localSpiceDir.setEnabled(True)
+        self.ui.pushButton_browseLocalDataDir.setEnabled(True)
+
+        return
+
+    def do_integrate_peaks(self):
+        """
+
+        :return:
+        """
+        raise RuntimeError('ASAP')
+
+    def do_refine_ub(self):
+        """
+
+        :return:
+        """
+        raise RuntimeError('Next Release')
+
+    def _init_ub_table(self):
+        """ DOC
+        :return:
+        """
+        # UB-peak table
+        # NOTE: have to call this because pyqt set column and row to 0 after __init__
+        #       thus a 2-step initialization has to been adopted
+        self.ui.tableWidget_peaksCalUB.setup()
+
+        self.ui.tableWidget_ubMatrix.setup()
+        self.ui.tableWidget_ubSiceView.setup()
+        self.ui.tableWidget_refinedUB.setup()
+
+        self.ui.tableWidget_sliceViewProgress.setup()
+
+        return
+
+    def change_data_access_mode(self):
+        """ Change data access mode between downloading from server and local
+        Event handling methods
+        :return:
+        """
+        new_mode = str(self.ui.comboBox_mode.currentText())
+        self._dataAccessMode = new_mode
+
+        if new_mode.startswith('Local') is True:
+            self.ui.lineEdit_localSpiceDir.setEnabled(True)
+            self.ui.pushButton_browseLocalDataDir.setEnabled(True)
+            self.ui.lineEdit_url.setEnabled(False)
+            self.ui.lineEdit_localSrcDir.setEnabled(False)
+            self.ui.pushButton_browseLocalCache.setEnabled(False)
+            self._allowDownload = False
+        else:
+            self.ui.lineEdit_localSpiceDir.setEnabled(False)
+            self.ui.pushButton_browseLocalDataDir.setEnabled(False)
+            self.ui.lineEdit_url.setEnabled(True)
+            self.ui.lineEdit_localSrcDir.setEnabled(True)
+            self.ui.pushButton_browseLocalCache.setEnabled(True)
+            self._allowDownload = True
+
+        return
+
+    def change_instrument_name(self):
+        """ Handing the event as the instrument name is changed
+        :return:
+        """
+        new_instrument = str(self.ui.comboBox_instrument.currentText())
+        self.pop_one_button_dialog('Change of instrument during data processing is dangerous.')
+        status, error_message = self._myControl.set_instrument_name(new_instrument)
+        if status is False:
+            self.pop_one_button_dialog(error_message)
+
+        return
+
+    def do_add_ub_peak(self):
+        """ Add current to ub peaks
+        :return:
+        """
+        # Add peak
+        status, int_list = gutil.parse_integers_editors([self.ui.lineEdit_exp,
+                                                         self.ui.lineEdit_scanNumber,
+                                                         self.ui.lineEdit_ptNumber])
+        if status is False:
+            self.pop_one_button_dialog(int_list)
+        exp_no, scan_no, pt_no = int_list
+
+        # Get HKL from GUI
+        status, float_list = gutil.parse_float_editors([self.ui.lineEdit_H,
+                                                        self.ui.lineEdit_K,
+                                                        self.ui.lineEdit_L])
+        if status is False:
+            err_msg = float_list
+            self.pop_one_button_dialog(err_msg)
+            return
+        h, k, l = float_list
+
+        status, peak_info_obj = self._myControl.get_peak_info(exp_no, scan_no, pt_no)
+        if status is False:
+            error_message = peak_info_obj
+            self.pop_one_button_dialog(error_message)
+            return
+        assert isinstance(peak_info_obj, r4c.PeakInfo)
+
+        if self.ui.checkBox_roundHKLInt.isChecked():
+            h = math.copysign(1, h)*int(abs(h)+0.5)
+            k = math.copysign(1, k)*int(abs(k)+0.5)
+            l = math.copysign(1, l)*int(abs(l)+0.5)
+        peak_info_obj.set_user_hkl(h, k, l)
+        self.set_ub_peak_table(peak_info_obj)
+
+        # Clear
+        self.ui.lineEdit_scanNumber.setText('')
+        self.ui.lineEdit_ptNumber.setText('')
+
+        self.ui.lineEdit_sampleQx.setText('')
+        self.ui.lineEdit_sampleQy.setText('')
+        self.ui.lineEdit_sampleQz.setText('')
+
+        self.ui.lineEdit_H.setText('')
+        self.ui.lineEdit_K.setText('')
+        self.ui.lineEdit_L.setText('')
+
+        return
+
+    def doAcceptCalUB(self):
+        """ Accept the calculated UB matrix
+        """
+        raise RuntimeError('ASAP')
+        return
+
+    def doAddScanPtToRefineUB(self):
+        """ Add scan/pt numbers to the list of data points for refining ub matrix
+
+        And the added scan number and pt numbers will be reflected in the (left sidebar)
+
+        """
+        raise RuntimeError("ASAP")
+
+    def do_add_peak_to_find(self):
+        """
+        Add the scan/pt to the next
+        :return:
+        """
+        scan_no = self.ui.lineEdit_run.text()
+        pt_no = self.ui.lineEdit_rawDataPtNo.text()
+
+        self.ui.lineEdit_scanNumber.setText(scan_no)
+        self.ui.lineEdit_ptNumber.setText(pt_no)
+
+        self.ui.tabWidget.setCurrentIndex(2)
+
+    def do_browse_local_cache_dir(self):
+        """ Browse local cache directory
+        :return:
+        """
+        local_cache_dir = str(QtGui.QFileDialog.getExistingDirectory(self,
+                                                                     'Get Local Cache Directory',
+                                                                     self._homeSrcDir))
+
+        # Set local directory to control
+        status, error_message = self._myControl.set_local_data_dir(local_cache_dir)
+        if status is False:
+            self.pop_one_button_dialog(error_message)
+            return
+
+        # Synchronize to local data/spice directory and local cache directory
+        if str(self.ui.lineEdit_localSpiceDir.text()) != '':
+            prev_dir = str(self.ui.lineEdit_localSrcDir.text())
+            self.pop_one_button_dialog('Local data directory was set up as %s' %
+                                       prev_dir)
+        self.ui.lineEdit_localSrcDir.setText(local_cache_dir)
+        self.ui.lineEdit_localSpiceDir.setText(local_cache_dir)
+
+        return
+
+    def do_browse_local_spice_data(self):
+        """ Browse local source SPICE data directory
+        """
+        src_spice_dir = str(QtGui.QFileDialog.getExistingDirectory(self, 'Get Directory',
+                                                                   self._homeSrcDir))
+        # Set local data directory to controller
+        status, error_message = self._myControl.set_local_data_dir(src_spice_dir)
+        if status is False:
+            self.pop_one_button_dialog(error_message)
+            return
+
+        self._homeSrcDir = src_spice_dir
+        self.ui.lineEdit_localSpiceDir.setText(src_spice_dir)
+
+        return
+
+    def do_browse_working_dir(self):
+        """
+        Browse and set up working directory
+        :return:
+        """
+        work_dir = str(QtGui.QFileDialog.getExistingDirectory(self, 'Get Working Directory', self._homeDir))
+        status, error_message = self._myControl.set_working_directory(work_dir)
+        if status is False:
+            self.pop_one_button_dialog(error_message)
+        else:
+            self.ui.lineEdit_workDir.setText(work_dir)
+
+        return
+
+    def do_cal_ub_matrix(self):
+        """ Calculate UB matrix by 2 or 3 reflections
+        """
+        # Get reflections
+        num_rows = self.ui.tableWidget_peaksCalUB.rowCount()
+        peak_info_list = list()
+        status, exp_number = gutil.parse_integers_editors(self.ui.lineEdit_exp)
+        for i_row in xrange(num_rows):
+            if self.ui.tableWidget_peaksCalUB.is_selected(i_row) is True:
+                scan_num, pt_num = self.ui.tableWidget_peaksCalUB.get_exp_info(i_row)
+                status, peak_info = self._myControl.get_peak_info(exp_number, scan_num, pt_num)
+                peak_info.set_peak_ws_hkl_from_user()
+                if status is False:
+                    self.pop_one_button_dialog(peak_info)
+                    return
+                assert isinstance(peak_info, r4c.PeakInfo)
+                peak_info_list.append(peak_info)
+        # END-FOR
+
+        # Get lattice
+        status, ret_obj = self._get_lattice_parameters()
+        if status is True:
+            a, b, c, alpha, beta, gamma = ret_obj
+        else:
+            err_msg = ret_obj
+            self.pop_one_button_dialog(err_msg)
+            return
+
+        # Calculate UB matrix
+        status, ub_matrix = self._myControl.calculate_ub_matrix(peak_info_list, a, b, c,
+                                                                alpha, beta, gamma)
+
+        # Deal with result
+        if status is True:
+            self._show_ub_matrix(ub_matrix)
+        else:
+            err_msg = ub_matrix
+            self.pop_one_button_dialog(err_msg)
+
+        return
+
+    def do_clear_ub_peaks(self):
+        """
+        Clear all peaks in UB-Peak table
+        :return:
+        """
+        self.ui.tableWidget_peaksCalUB.clear()
+
+        return
+
+    def do_del_ub_peaks(self):
+        """
+        Delete a peak in UB-Peak table
+        :return:
+        """
+        # Find out the lines to get deleted
+        row_num_list = self.ui.tableWidget_peaksCalUB.get_selected_rows()
+        print '[DB] Row %s are selected' % str(row_num_list)
+
+        # Delete
+        self.ui.tableWidget_peaksCalUB.delete_rows(row_num_list)
+
+        return
+
+    def do_download_spice_data(self):
+        """ Download SPICE data
+        :return:
+        """
+        # Check scans to download
+        scan_list_str = str(self.ui.lineEdit_downloadScans.text())
+        if len(scan_list_str) > 0:
+            # user specifies scans to download
+            valid, scan_list = fcutil.parse_int_array(scan_list_str)
+            if valid is False:
+                error_message = scan_list
+                self.pop_one_button_dialog(error_message)
+        else:
+            # Get all scans
+            status, ret_obj = gutil.parse_integers_editors([self.ui.lineEdit_exp])
+            if status is False:
+                self.pop_one_button_dialog(ret_obj)
+                return
+            exp_no = ret_obj
+            assert isinstance(exp_no, int)
+            server_url = str(self.ui.lineEdit_url.text())
+            scan_list = fcutil.get_scans_list(server_url, exp_no, return_list=True)
+        self.pop_one_button_dialog('Going to download scans %s.' % str(scan_list))
+
+        # Check location
+        destination_dir = str(self.ui.lineEdit_localSrcDir.text())
+        status, error_message = self._myControl.set_local_data_dir(destination_dir)
+        if status is False:
+            self.pop_one_button_dialog(error_message)
+        else:
+            self.pop_one_button_dialog('Spice files will be downloaded to %s.' % destination_dir)
+
+        # Set up myControl for downloading data
+        exp_no = int(self.ui.lineEdit_exp.text())
+        self._myControl.set_exp_number(exp_no)
+
+        server_url = str(self.ui.lineEdit_url.text())
+        status, error_message = self._myControl.set_server_url(server_url)
+        if status is False:
+            self.pop_one_button_dialog(error_message)
+            return
+
+        # Download
+        self._myControl.download_data_set(scan_list)
+
+        return
+
+    def do_find_peak(self):
+        """ Find peak in a given scan/pt and record it
+        """
+        # Get experiment, scan and pt
+        status, ret_obj = gutil.parse_integers_editors([self.ui.lineEdit_exp,
+                                                        self.ui.lineEdit_scanNumber,
+                                                        self.ui.lineEdit_ptNumber])
+        if status is True:
+            exp_no, scan_no, pt_no = ret_obj
+        else:
+            self.pop_one_button_dialog(ret_obj)
+            return
+
+        # Find peak
+        status, err_msg = self._myControl.find_peak(exp_no, scan_no, pt_no)
+        if status is False:
+            self.pop_one_button_dialog(ret_obj)
+            return
+        if self.ui.checkBox_loadHKLfromFile.isChecked() is True:
+            # This is the first time that in the workflow to get HKL from MD workspace
+            status, err_msg = self._myControl.set_hkl_to_peak(exp_no, scan_no, pt_no)
+            if status is False:
+                self.pop_one_button_dialog('Unable to locate peak info due to %s.' % err_msg)
+
+        # Set up correct values to table tableWidget_peaksCalUB
+        self._myControl.add_peak_info(exp_no, scan_no, pt_no)
+        status, peak_info = self._myControl.get_peak_info(exp_no, scan_no, pt_no)
+        if status is False:
+            err_msg = peak_info
+            raise KeyError(err_msg)
+        assert isinstance(peak_info, r4c.PeakInfo)
+
+        # Set the HKL value from PeakInfo directly
+        # BAD PROGRAMMING! THERE ARE TOO MANY WAYS TO ACCESS STORED HKL
+        h, k, l = peak_info.get_peak_ws_hkl()
+        self.ui.lineEdit_H.setText('%.2f' % h)
+        self.ui.lineEdit_K.setText('%.2f' % k)
+        self.ui.lineEdit_L.setText('%.2f' % l)
+
+        q_sample = peak_info.getQSample()
+        self.ui.lineEdit_sampleQx.setText('%.5E' % q_sample[0])
+        self.ui.lineEdit_sampleQy.setText('%.5E' % q_sample[1])
+        self.ui.lineEdit_sampleQz.setText('%.5E' % q_sample[2])
+
+        # self.set_ub_peak_table(peak_info)
+
+        return
+
+    def do_index_ub_peaks(self):
+        """ Index the peaks in the UB matrix peak table
+        :return:
+        """
+        # Get UB matrix
+        ub_matrix = self.ui.tableWidget_ubMatrix.get_matrix()
+        print '[DB] Get UB matrix ', ub_matrix
+
+        # Do it for each peak
+        num_peaks = self.ui.tableWidget_peaksCalUB.rowCount()
+        err_msg = ''
+        for i_peak in xrange(num_peaks):
+            scan_no, pt_no = self.ui.tableWidget_peaksCalUB.get_exp_info(i_peak)
+            status, ret_obj = self._myControl.index_peak(ub_matrix, scan_number=scan_no,
+                                                         pt_number=pt_no)
+            if status is True:
+                new_hkl = ret_obj[0]
+                error = ret_obj[1]
+                self.ui.tableWidget_peaksCalUB.set_hkl(i_peak, new_hkl, error)
+            else:
+                err_msg += ret_obj + '\n'
+        # END-FOR
+
+        if len(err_msg) > 0:
+            self.pop_one_button_dialog(err_msg)
+
+        return
+
+    def do_list_scans(self):
+        """ List all scans available
+        :return:
+        """
+        # Experiment number
+        exp_no = int(self.ui.lineEdit_exp.text())
+
+        access_mode = str(self.ui.comboBox_mode.currentText())
+        if access_mode == 'Local':
+            spice_dir = str(self.ui.lineEdit_localSpiceDir.text())
+            message = fcutil.get_scans_list_local_disk(spice_dir, exp_no)
+        else:
+            url = str(self.ui.lineEdit_url.text())
+            message = fcutil.get_scans_list(url, exp_no)
+
+        self.pop_one_button_dialog(message)
+
+        return
+
+    def do_load_scan_info(self):
+        """ Load SIICE's scan file
+        :return:
+        """
+        # Get scan number
+        status, ret_obj = gutil.parse_integers_editors([self.ui.lineEdit_run])
+        if status is True:
+            scan_no = ret_obj[0]
+        else:
+            err_msg = ret_obj
+            self.pop_one_button_dialog('Unable to get scan number in raw data tab due to %s.' % err_msg)
+            return
+
+        status, err_msg = self._myControl.load_spice_scan_file(exp_no=None, scan_no=scan_no)
+        if status is False:
+            self.pop_one_button_dialog(err_msg)
+
+        return
+
+    def do_plot_pt_raw(self):
+        """ Plot the Pt.
+        """
+        # Get measurement pt and the file number
+        status, ret_obj = gutil.parse_integers_editors([self.ui.lineEdit_exp,
+                                                        self.ui.lineEdit_run,
+                                                        self.ui.lineEdit_rawDataPtNo])
+        if status is True:
+            exp_no = ret_obj[0]
+            scan_no = ret_obj[1]
+            pt_no = ret_obj[2]
+        else:
+            self.pop_one_button_dialog(ret_obj)
+            return
+
+        # Call to plot 2D
+        self._plot_raw_xml_2d(exp_no, scan_no, pt_no)
+
+        return
+
+    def do_plot_prev_pt_raw(self):
+        """ Plot the Pt.
+        """
+        # Get measurement pt and the file number
+        status, ret_obj = gutil.parse_integers_editors([self.ui.lineEdit_exp,
+                                                        self.ui.lineEdit_run,
+                                                        self.ui.lineEdit_rawDataPtNo])
+        if status is True:
+            exp_no = ret_obj[0]
+            scan_no = ret_obj[1]
+            pt_no = ret_obj[2]
+        else:
+            self.pop_one_button_dialog(ret_obj)
+            return
+
+        # Previous one
+        pt_no -= 1
+        if pt_no <= 0:
+            self.pop_one_button_dialog('Pt. = 1 is the first one.')
+            return
+        else:
+            self.ui.lineEdit_rawDataPtNo.setText('%d' % pt_no)
+
+        # Plot
+        self._plot_raw_xml_2d(exp_no, scan_no, pt_no)
+
+        return
+
+    def do_plot_next_pt_raw(self):
+        """ Plot the Pt.
+        """
+        # Get measurement pt and the file number
+        status, ret_obj = gutil.parse_integers_editors([self.ui.lineEdit_exp,
+                                                        self.ui.lineEdit_run,
+                                                        self.ui.lineEdit_rawDataPtNo])
+        if status is True:
+            exp_no = ret_obj[0]
+            scan_no = ret_obj[1]
+            pt_no = ret_obj[2]
+        else:
+            self.pop_one_button_dialog(ret_obj)
+            return
+
+        # Previous one
+        pt_no += 1
+        # get last Pt. number
+        status, last_pt_no = self._myControl.get_pt_numbers(exp_no, scan_no)
+        if status is False:
+            error_message = last_pt_no
+            self.pop_one_button_dialog('Unable to access Spice table for scan %d. Reason" %s.' % (
+                scan_no, error_message))
+        if pt_no > last_pt_no:
+            self.pop_one_button_dialog('Pt. = %d is the last one of scan %d.' % (pt_no, scan_no))
+            return
+        else:
+            self.ui.lineEdit_rawDataPtNo.setText('%d' % pt_no)
+
+        # Plot
+        self._plot_raw_xml_2d(exp_no, scan_no, pt_no)
+
+        return
+
+    def do_merge_scans(self):
+        """ Process data for slicing view
+        :return:
+        """
+        # Get UB matrix
+        ub_matrix = self.ui.tableWidget_ubSiceView.get_matrix()
+        self._myControl.set_ub_matrix(exp_number=None, ub_matrix=ub_matrix)
+
+        # Get list of scans
+        scan_list = gutil.parse_integer_list(str(self.ui.lineEdit_listScansSliceView.text()))
+        if len(scan_list) == 0:
+            self.pop_one_button_dialog('Scan list is empty.')
+
+        # Set table
+        self.ui.tableWidget_sliceViewProgress.append_scans(scans=scan_list)
+
+        # Warning
+        self.pop_one_button_dialog('Data processing is long. Be patient!')
+
+        # Process
+        base_name = str(self.ui.lineEdit_baseMergeMDName.text())
+        scan_list.sort()
+        frame = str(self.ui.comboBox_mergeScanFrame.currentText())
+        for scan_no in scan_list:
+            # Download/check SPICE file
+            self._myControl.download_spice_file(None, scan_no, over_write=False)
+
+            # Get some information
+            status, pt_list = self._myControl.get_pt_numbers(None, scan_no, load_spice_scan=True)
+            if status is False:
+                err_msg = pt_list
+                self.pop_one_button_dialog('Failed to get Pt. number: %s' % err_msg)
+                return
+            else:
+                # Set information to table
+                err_msg = self.ui.tableWidget_sliceViewProgress.set_scan_pt(scan_no, pt_list)
+                if len(err_msg) > 0:
+                    self.pop_one_button_dialog(err_msg)
+
+            out_ws_name = base_name + '%04d' % scan_no
+            self.ui.tableWidget_sliceViewProgress.set_scan_pt(scan_no, 'In Processing')
+            try:
+                ret_tup = self._myControl.merge_pts_in_scan(exp_no=None, scan_no=scan_no,
+                                                            target_ws_name=out_ws_name,
+                                                            target_frame=frame)
+                merge_status = 'Done'
+                merged_name = ret_tup[0]
+                group_name = ret_tup[1]
+            except RuntimeError as e:
+                merge_status = 'Failed. Reason: %s' % str(e)
+                merged_name = ''
+                group_name = ''
+            finally:
+                self.ui.tableWidget_sliceViewProgress.set_status(scan_no, merge_status)
+                self.ui.tableWidget_sliceViewProgress.set_ws_names(scan_no, merged_name, group_name)
+
+            # Sleep for a while
+            time.sleep(0.1)
+        # END-FOR
+
+        return
+
+    def do_reset_ub_peaks_hkl(self):
+        """
+        Reset user specified HKL value to peak table
+        :return:
+        """
+        num_rows = self.ui.tableWidget_peaksCalUB.rowCount()
+        for i_row in xrange(num_rows):
+            print '[DB] Update row %d' % (i_row)
+            scan, pt = self.ui.tableWidget_peaksCalUB.get_scan_pt(i_row)
+            status, peak_info = self._myControl.get_peak_info(None, scan, pt)
+            if status is False:
+                error_message = peak_info
+                raise RuntimeError(error_message)
+            h, k, l = peak_info.get_user_hkl()
+            self.ui.tableWidget_peaksCalUB.update_hkl(i_row, h, k, l)
+        # END-FOR
+
+        return
+
+    def do_set_experiment(self):
+        """ Set experiment
+        :return:
+        """
+        status, ret_obj = gutil.parse_integers_editors([self.ui.lineEdit_exp])
+        if status is True:
+            exp_number = ret_obj[0]
+            curr_exp_number = self._myControl.get_experiment()
+            if curr_exp_number is not None and exp_number != curr_exp_number:
+                self.pop_one_button_dialog('Changing experiment to %d.  Clean previous experiment %d\'s result'
+                                           ' in Mantid manually.' % (exp_number, curr_exp_number))
+            self._myControl.set_exp_number(exp_number)
+            self.ui.lineEdit_exp.setStyleSheet('color: black')
+        else:
+            err_msg = ret_obj
+            self.pop_one_button_dialog('Unable to set experiment as %s' % err_msg)
+            self.ui.lineEdit_exp.setStyleSheet('color: red')
+
+        self.ui.tabWidget.setCurrentIndex(0)
+
+        return
+
+    def do_set_ub_sv(self):
+        """ Set UB matrix in Slice view
+        :return:
+        """
+        if self.ui.radioButton_ubFromTab1.isChecked():
+            self.ui.tableWidget_ubSiceView.set_from_matrix(self.ui.tableWidget_ubMatrix.get_matrix())
+        elif self.ui.radioButton_ubFromTab3.isChecked():
+            self.ui.tableWidget_ubSiceView.set_from_matrix(self.ui.tableWidget_refinedUB.get_matrix())
+        elif self.ui.radioButton_ubFromList.isChecked():
+            status, ret_obj = gutil.parse_float_array(str(self.ui.plainTextEdit_ubInput.toPlainText()))
+            if status is False:
+                self.pop_one_button_dialog(ret_obj)
+            elif len(ret_obj) != 9:
+                self.pop_one_button_dialog('Requiring 9 floats for UB matrix.  Only %d are given.' % len(ret_obj))
+            else:
+                self.ui.tableWidget_ubSiceView.set_from_list(ret_obj)
+        else:
+            self.pop_one_button_dialog('None is selected to set UB matrix.')
+
+        return
+
+    def do_setup_dir_default(self):
+        """
+        Set up default directory for storing data and working
+        :return:
+        """
+        home_dir = os.path.expanduser('~')
+
+        # Data cache directory
+        data_cache_dir = os.path.join(home_dir, 'Temp/HB3ATest')
+        self.ui.lineEdit_localSpiceDir.setText(data_cache_dir)
+        self.ui.lineEdit_localSrcDir.setText(data_cache_dir)
+
+        work_dir = os.path.join(data_cache_dir, 'Workspace')
+        self.ui.lineEdit_workDir.setText(work_dir)
+
+        return
+
+    def do_apply_setup(self):
+        """
+        Apply set up ...
+        :return:
+        """
+        # Local data directory
+        local_data_dir = str(self.ui.lineEdit_localSpiceDir.text())
+        if os.path.exists(local_data_dir) is False:
+            try:
+                os.mkdir(local_data_dir)
+            except OSError as os_error:
+                self.pop_one_button_dialog('Unable to create local data directory %s due to %s.' % (
+                    local_data_dir, str(os_error)))
+                self.ui.lineEdit_localSpiceDir.setStyleSheet("color: red;")
+                return
+            else:
+                self.ui.lineEdit_localSpiceDir.setStyleSheet("color: black;")
+        # END-IF
+
+        # Working directory
+        working_dir = str(self.ui.lineEdit_workDir.text())
+        if os.path.exists(working_dir) is False:
+            try:
+                os.mkdir(working_dir)
+            except OSError as os_error:
+                self.pop_one_button_dialog('Unable to create working directory %s due to %s.' % (
+                    working_dir, str(os_error)))
+                self.ui.lineEdit_workDir.setStyleSheet("color: red;")
+                return
+            else:
+                self.ui.lineEdit_workDir.setStyleSheet("color: black;")
+        # END-IF
+
+        # Server URL
+        data_server = str(self.ui.lineEdit_url.text())
+        url_is_good = self.do_test_url()
+        if url_is_good is False:
+            self.ui.lineEdit_url.setStyleSheet("color: red;")
+            return
+        else:
+            self.ui.lineEdit_url.setStyleSheet("color: black;")
+
+        # Set to control
+        self._myControl.set_local_data_dir(local_data_dir)
+        self._myControl.set_working_directory(working_dir)
+        self._myControl.set_server_url(data_server)
+
+        return
+
+    def do_test_url(self):
+        """ Test whether the root URL provided specified is good
+        """
+        url = str(self.ui.lineEdit_url.text())
+
+        url_is_good, err_msg = fcutil.check_url(url)
+        if url_is_good is True:
+            self.pop_one_button_dialog("URL %s is valid." % url)
+        else:
+            self.pop_one_button_dialog(err_msg)
+
+        return url_is_good
+
+    def pop_one_button_dialog(self, message):
+        """ Pop up a one-button dialog
+        :param message:
+        :return:
+        """
+        assert isinstance(message, str)
+        QtGui.QMessageBox.information(self, '4-circle Data Reduction', message)
+
+        return
+
+    def save_current_session(self, filename=None):
+        """ Save current session/value setup to
+        :return:
+        """
+        # Set up dictionary
+        save_dict = dict()
+
+        # Setup
+        save_dict['lineEdit_localSpiceDir'] = str(self.ui.lineEdit_localSpiceDir.text())
+        save_dict['lineEdit_url'] = str(self.ui.lineEdit_url.text())
+        save_dict['lineEdit_workDir']= str(self.ui.lineEdit_workDir.text())
+
+        # Experiment
+        save_dict['lineEdit_exp'] = str(self.ui.lineEdit_exp.text())
+        save_dict['lineEdit_scanNumber'] = self.ui.lineEdit_scanNumber.text()
+        save_dict['lineEdit_ptNumber'] = str(self.ui.lineEdit_ptNumber.text())
+
+        # Lattice
+        save_dict['lineEdit_a'] = str(self.ui.lineEdit_a.text())
+        save_dict['lineEdit_b'] = str(self.ui.lineEdit_b.text())
+        save_dict['lineEdit_c'] = str(self.ui.lineEdit_c.text())
+        save_dict['lineEdit_alpha'] = str(self.ui.lineEdit_alpha.text())
+        save_dict['lineEdit_beta'] = str(self.ui.lineEdit_beta.text())
+        save_dict['lineEdit_gamma'] = str(self.ui.lineEdit_gamma.text())
+
+        # Merge scan
+        save_dict['plainTextEdit_ubInput'] = str(self.ui.plainTextEdit_ubInput.toPlainText())
+        save_dict['lineEdit_listScansSliceView'] = str(self.ui.lineEdit_listScansSliceView.text())
+        save_dict['lineEdit_baseMergeMDName'] = str(self.ui.lineEdit_baseMergeMDName.text())
+
+        # Save to csv file
+        if filename is None:
+            filename = 'session_backup.csv'
+        ofile = open(filename, 'w')
+        writer = csv.writer(ofile)
+        for key, value in save_dict.items():
+            writer.writerow([key, value])
+        ofile.close()
+
+        return
+
+    def load_session(self, filename=None):
+        """
+        To load a session, i.e., read it back:
+        :param filename:
+        :return:
+        """
+        if filename is None:
+            filename = 'session_backup.csv'
+
+        in_file = open(filename, 'r')
+        reader = csv.reader(in_file)
+        my_dict = dict(x for x in reader)
+
+        # ...
+        for key, value in my_dict.items():
+            if key.startswith('lineEdit') is True:
+                self.ui.__getattribute__(key).setText(value)
+            elif key.startswith('plainText') is True:
+                self.ui.__getattribute__(key).setPlainText(value)
+            elif key.startswith('comboBox') is True:
+                self.ui.__getattribute__(key).setCurrentIndex(int(value))
+            else:
+                self.pop_one_button_dialog('Error! Widget name %s is not supported' % key)
+        # END-FOR
+
+        # ...
+        self._myControl.set_local_data_dir(str(self.ui.lineEdit_localSpiceDir.text()))
+
+        return
+
+    def menu_quit(self):
+        """
+
+        :return:
+        """
+        self.close()
+
+    def show_scan_pt_list(self):
+        """ Show the range of Pt. in a scan
+        :return:
+        """
+        # Get parameters
+        status, inp_list = gutil.parse_integers_editors([self.ui.lineEdit_exp, self.ui.lineEdit_run])
+        if status is False:
+            self.pop_one_button_dialog(inp_list)
+            return
+        else:
+            exp_no = inp_list[0]
+            scan_no = inp_list[1]
+
+        status, ret_obj = self._myControl.get_pt_numbers(exp_no, scan_no)
+
+        # Form message
+        if status is False:
+            # Failed to get Pt. list
+            error_message = ret_obj
+            self.pop_one_button_dialog(error_message)
+        else:
+            # Form message
+            pt_list = sorted(ret_obj)
+            num_pts = len(pt_list)
+            info = 'Exp %d Scan %d has %d Pt. ranging from %d to %d.\n' % (exp_no, scan_no, num_pts,
+                                                                           pt_list[0], pt_list[-1])
+            num_miss_pt = pt_list[-1] - pt_list[0] + 1 - num_pts
+            if num_miss_pt > 0:
+                info += 'There are %d Pt. skipped.\n' % num_miss_pt
+
+            self.pop_one_button_dialog(info)
+
+        return
+
+    def set_ub_peak_table(self, peakinfo):
+        """
+        DOC
+        :param peak_info:
+        :return:
+        """
+        assert isinstance(peakinfo, r4c.PeakInfo)
+
+        # Get data
+        exp_number, scan_number, pt_number = peakinfo.getExpInfo()
+        h, k, l = peakinfo.get_user_hkl()
+        q_sample = peakinfo.getQSample()
+        m1 = self._myControl.get_sample_log_value(exp_number, scan_number, pt_number, '_m1')
+
+        # Set to table
+        status, err_msg = self.ui.tableWidget_peaksCalUB.append_row(
+            [scan_number, pt_number, h, k, l, q_sample[0], q_sample[1], q_sample[2], False, m1, ''])
+        if status is False:
+            self.pop_one_button_dialog(err_msg)
+
+        return
+
+    def _get_lattice_parameters(self):
+        """
+        Get lattice parameters from GUI
+        :return: (Boolean, Object).  True, 6-tuple as a, b, c, alpha, beta, gamm
+                                     False: error message
+        """
+        status, ret_list = gutil.parse_float_editors([self.ui.lineEdit_a,
+                                                      self.ui.lineEdit_b,
+                                                      self.ui.lineEdit_c,
+                                                      self.ui.lineEdit_alpha,
+                                                      self.ui.lineEdit_beta,
+                                                      self.ui.lineEdit_gamma])
+        if status is False:
+            err_msg = ret_list
+            err_msg = 'Unable to parse unit cell due to %s' % err_msg
+            return False, err_msg
+
+        a, b, c, alpha, beta, gamma = ret_list
+
+        return True, (a, b, c, alpha, beta, gamma)
+
+    def _plot_raw_xml_2d(self, exp_no, scan_no, pt_no):
+        """ Plot raw workspace from XML file for a measurement/pt.
+        """
+        # Check and load SPICE table file
+        does_exist = self._myControl.does_spice_loaded(exp_no, scan_no)
+        if does_exist is False:
+            # Download data
+            status, error_message = self._myControl.download_spice_file(exp_no, scan_no, over_write=False)
+            if status is True:
+                status, error_message = self._myControl.load_spice_scan_file(exp_no, scan_no)
+                if status is False and self._allowDownload is False:
+                    self.pop_one_button_dialog(error_message)
+                    return
+            else:
+                self.pop_one_button_dialog(error_message)
+                return
+        # END-IF(does_exist)
+
+        # Load Data for Pt's xml file
+        does_exist = self._myControl.does_raw_loaded(exp_no, scan_no, pt_no)
+
+        if does_exist is False:
+            # Check whether needs to download
+            status, error_message = self._myControl.download_spice_xml_file(scan_no, pt_no, exp_no=exp_no)
+            if status is False:
+                self.pop_one_button_dialog(error_message)
+                return
+            # Load SPICE xml file
+            status, error_message = self._myControl.load_spice_xml_file(exp_no, scan_no, pt_no)
+            if status is False:
+                self.pop_one_button_dialog(error_message)
+                return
+
+        # Convert a list of vector to 2D numpy array for imshow()
+        # Get data and plot
+        raw_det_data = self._myControl.get_raw_detector_counts(exp_no, scan_no, pt_no)
+        self.ui.graphicsView.clear_canvas()
+        self.ui.graphicsView.add_plot_2d(raw_det_data, x_min=0, x_max=256, y_min=0, y_max=256,
+                                         hold_prev_image=False)
+
+        return
+
+    def _show_ub_matrix(self, ubmatrix):
+        """ Show UB matrix
+        :param ubmatrix:
+        :return:
+        """
+        assert ubmatrix.shape == (3, 3)
+
+        self.ui.tableWidget_ubMatrix.set_from_matrix(ubmatrix)
+
+        return
diff --git a/scripts/Inelastic/Direct/DirectEnergyConversion.py b/scripts/Inelastic/Direct/DirectEnergyConversion.py
index 56043ad5aeed4096c76b402026bf270c95982230..74394d53c59d56718d782f4b99e3b56634f1a1f9 100644
--- a/scripts/Inelastic/Direct/DirectEnergyConversion.py
+++ b/scripts/Inelastic/Direct/DirectEnergyConversion.py
@@ -1,3 +1,4 @@
+#pylint: disable=too-many-lines
 #pylint: disable=invalid-name
 from mantid.simpleapi import *
 from mantid.kernel import funcreturns
diff --git a/scripts/Inelastic/Direct/ISISDirecInelasticConfig.py b/scripts/Inelastic/Direct/ISISDirecInelasticConfig.py
index 624f599ba04d0e2848de1d7eae90cd134bcf83b3..f3c816ecbac11ce60b67842eb3f6dfbf1c4caad9 100644
--- a/scripts/Inelastic/Direct/ISISDirecInelasticConfig.py
+++ b/scripts/Inelastic/Direct/ISISDirecInelasticConfig.py
@@ -484,12 +484,12 @@ class MantidConfigDirectInelastic(object):
     #
     def init_user(self,fedIDorUser,theUser=None):
         """Define settings, specific to a user
-           Supports two interfaces -- old and the new one 
+           Supports two interfaces -- old and the new one
            where
-           OldInterface: requested two input parameters 
+           OldInterface: requested two input parameters
            fedID   -- users federal id
            theUser -- class defining all other user property
-           NewInterface: requested single parameter: 
+           NewInterface: requested single parameter:
            theUser -- class defining all user's properties including fedID
         """
         if not theUser:
diff --git a/scripts/Inelastic/Direct/PropertiesDescriptors.py b/scripts/Inelastic/Direct/PropertiesDescriptors.py
index f05779e6e22cb3be785e93284470526939658be8..aec0169cd240da45e7d63e5218902c7578eb579e 100644
--- a/scripts/Inelastic/Direct/PropertiesDescriptors.py
+++ b/scripts/Inelastic/Direct/PropertiesDescriptors.py
@@ -1,3 +1,4 @@
+#pylint: disable=too-many-lines
 #pylint: disable=invalid-name
 """ File contains collection of Descriptors used to define complex
     properties in NonIDF_Properties and PropertyManager classes
diff --git a/scripts/Inelastic/Direct/RunDescriptor.py b/scripts/Inelastic/Direct/RunDescriptor.py
index 9fda6508d6224a370358ac200b8968be3aeca2c5..b5e959ff885084e6a088e0647532fa21445b65ca 100644
--- a/scripts/Inelastic/Direct/RunDescriptor.py
+++ b/scripts/Inelastic/Direct/RunDescriptor.py
@@ -1,3 +1,4 @@
+#pylint: disable=too-many-lines
 #pylint: disable=invalid-name
 """ File contains Descriptors used describe run for direct inelastic reduction """
 
@@ -995,8 +996,8 @@ class RunDescriptor(PropDescriptor):
             Load(Filename=data_file, OutputWorkspace=ws_name,LoadMonitors = '1',MonitorsAsEvents='0')
         #HACK >>> , necessary until #11565 is fixed
         if nxs_file :
-           instr_name = RunDescriptor._holder.instr_name
-           if instr_name == 'LET' and self._run_number>14151 and self._run_number<14382:
+            instr_name = RunDescriptor._holder.instr_name
+            if instr_name == 'LET' and self._run_number>14151 and self._run_number<14382:
                 FrameworkManager.clearInstruments()
                 idf_file = api.ExperimentInfo.getInstrumentFilename(instr_name)
                 idf_path,tile = os.path.split(idf_file)
diff --git a/scripts/Interface/reduction_gui/reduction/diffraction/diffraction_reduction_script.py b/scripts/Interface/reduction_gui/reduction/diffraction/diffraction_reduction_script.py
index 7140a4df5633e57ccaaca3b9719cc32474b3539f..abbd2f4eee91d7db012641d90db791d3ecdec1b6 100644
--- a/scripts/Interface/reduction_gui/reduction/diffraction/diffraction_reduction_script.py
+++ b/scripts/Interface/reduction_gui/reduction/diffraction/diffraction_reduction_script.py
@@ -84,7 +84,7 @@ class DiffractionReductionScripter(BaseReductionScripter):
                 file_name, autosavexmlfname)
         wbuf += script
         wbuf += "\n========== End of Script ==========="
-        print (wbuf)
+        print wbuf
 
         return script
 
diff --git a/scripts/Interface/reduction_gui/widgets/reflectometer/base_ref_reduction.py b/scripts/Interface/reduction_gui/widgets/reflectometer/base_ref_reduction.py
index ea324c63828a6e03190b8b2c5fc99b90bdf2fd80..72cfb428315fa574ee295ed307c2e1e696f1eb99 100644
--- a/scripts/Interface/reduction_gui/widgets/reflectometer/base_ref_reduction.py
+++ b/scripts/Interface/reduction_gui/widgets/reflectometer/base_ref_reduction.py
@@ -1,3 +1,4 @@
+#pylint: disable=too-many-lines
 #pylint: disable=invalid-name,unused-import
 from PyQt4 import QtGui, QtCore
 import reduction_gui.widgets.util as util
diff --git a/scripts/Interface/reduction_gui/widgets/reflectometer/refl_data_simple.py b/scripts/Interface/reduction_gui/widgets/reflectometer/refl_data_simple.py
index bfb043368ad53ccaeb13b243a916cea1f8f5e615..8816e2f91ded5277314a7b6e267a8a72f8c424ac 100644
--- a/scripts/Interface/reduction_gui/widgets/reflectometer/refl_data_simple.py
+++ b/scripts/Interface/reduction_gui/widgets/reflectometer/refl_data_simple.py
@@ -1,3 +1,4 @@
+#pylint: disable=too-many-lines
 #pylint: disable=invalid-name
 from PyQt4 import QtGui, uic, QtCore
 import reduction_gui.widgets.util as util
diff --git a/scripts/Interface/ui/reflectometer/refl_gui.py b/scripts/Interface/ui/reflectometer/refl_gui.py
index 3bb3aed9b003789fd1786e1f1ecfa46f82878888..8f1a384733c2e605fd61b22f192b30ccc26b3b90 100644
--- a/scripts/Interface/ui/reflectometer/refl_gui.py
+++ b/scripts/Interface/ui/reflectometer/refl_gui.py
@@ -1,3 +1,4 @@
+#pylint: disable=too-many-lines
 #pylint: disable=invalid-name
 import ui_refl_window
 import refl_save
diff --git a/scripts/Reflectometry/isis_reflectometry/procedures.py b/scripts/Reflectometry/isis_reflectometry/procedures.py
index 999dd0a65df4c3c69b2b8d82f085be1fa5d886ab..11d1a52448ec5749956eca3315db82a7a2537801 100644
--- a/scripts/Reflectometry/isis_reflectometry/procedures.py
+++ b/scripts/Reflectometry/isis_reflectometry/procedures.py
@@ -1,3 +1,4 @@
+#pylint: disable=too-many-lines
 #pylint: disable=invalid-name
 from math import *
 
diff --git a/scripts/SANS/ISISCommandInterface.py b/scripts/SANS/ISISCommandInterface.py
index 0ed8fd805b698e6a5c35ffdf68ae9425299ed478..3f06b3229bf67e2a871806a1a62459c5db70707b 100644
--- a/scripts/SANS/ISISCommandInterface.py
+++ b/scripts/SANS/ISISCommandInterface.py
@@ -1,3 +1,4 @@
+#pylint: disable=too-many-lines
 #pylint: disable=invalid-name
 """
     Enables the SANS commands (listed at http://www.mantidproject.org/SANS) to
@@ -574,7 +575,7 @@ def _fitRescaleAndShift(rAnds, frontData, rearData):
 
     # We need to make sure at this point that the workspaces are 1D. We
     # don't really know how to match the workspaces for the 2D case.
-    if (not su.is_1D_workspace(mtd[frontData]) or not su.is_1D_workspace(mtd[rearData])):
+    if not su.is_1D_workspace(mtd[frontData]) or not su.is_1D_workspace(mtd[rearData]):
         sanslog.warning("Request to perform a fit to find the shift and scale values for"
                         "a non-1D workspace is not possible. Default values are provided.")
         scale = rAnds.scale
diff --git a/scripts/SANS/SANSBatchMode.py b/scripts/SANS/SANSBatchMode.py
index 3419a9c6cd16d07aede08f6ca2a48e6918fb1d9b..38f01016a7b8b7744b9bdd942883cb8c133268b4 100644
--- a/scripts/SANS/SANSBatchMode.py
+++ b/scripts/SANS/SANSBatchMode.py
@@ -178,7 +178,8 @@ def BatchReduce(filename, format, plotresults=False, saveAlgs={'SaveRKH':'txt'},
                                                        original_settings = settings,
                                                        original_prop_man_settings = prop_man_settings)
         except (RunTimeError, ValueError) as e:
-            sanslog.warning("Error in Batchmode user files: Could not reset the specified user file %s. More info: %s" %(str(run['user_file']),str(e)))
+            sanslog.warning("Error in Batchmode user files: Could not reset the specified user file %s. More info: %s" %(
+                str(run['user_file']),str(e)))
 
         local_settings = copy.deepcopy(ReductionSingleton().reference())
         local_prop_man_settings = ReductionSingleton().settings.clone("TEMP_SETTINGS")
diff --git a/scripts/SANS/SANSUtility.py b/scripts/SANS/SANSUtility.py
index b22d9e8c19ad5d785f2d99beb9479be8769d5258..c594e7548e3d319888d9136a2b8c14c6831b8221 100644
--- a/scripts/SANS/SANSUtility.py
+++ b/scripts/SANS/SANSUtility.py
@@ -1,3 +1,4 @@
+#pylint: disable=too-many-lines
 #pylint: disable=invalid-name
 #########################################################
 # This module contains utility functions common to the
diff --git a/scripts/SANS/isis_instrument.py b/scripts/SANS/isis_instrument.py
index b4c0a9a507d3bbcb0a063ac2c540d05a12eeb1ce..821b956195403a29bfb2b308d0a83d29286235c9 100644
--- a/scripts/SANS/isis_instrument.py
+++ b/scripts/SANS/isis_instrument.py
@@ -1,3 +1,4 @@
+#pylint: disable=too-many-lines
 #pylint: disable=invalid-name
 import math
 import os
diff --git a/scripts/SANS/isis_reduction_steps.py b/scripts/SANS/isis_reduction_steps.py
index ebb89992488267b445b04ba4d1b5f16f99c55a98..f98175cf90062335d14d3cf0894e08d7e117e840 100644
--- a/scripts/SANS/isis_reduction_steps.py
+++ b/scripts/SANS/isis_reduction_steps.py
@@ -1,3 +1,4 @@
+#pylint: disable=too-many-lines
 #pylint: disable=invalid-name
 """
     This file defines what happens in each step in the data reduction, it's
diff --git a/scripts/reduction/instruments/reflectometer/wks_utility.py b/scripts/reduction/instruments/reflectometer/wks_utility.py
index b9dec721553ac63bdbeb835d613fe0b306a45bb4..7544a27a51147a23863c1579e17d2db0afac45d3 100644
--- a/scripts/reduction/instruments/reflectometer/wks_utility.py
+++ b/scripts/reduction/instruments/reflectometer/wks_utility.py
@@ -1,3 +1,4 @@
+#pylint: disable=too-many-lines
 #pylint: disable=invalid-name
 from numpy import zeros, arctan2, arange, shape, sqrt, fliplr, asfarray, mean, sum, NAN
 from mantid.simpleapi import *
diff --git a/tools/DOI/authors.py b/tools/DOI/authors.py
index aefa191509e7cae27eb14df35dfc91e564189b23..2d35b45b4aec8710fb2a8a7cff85ed3b137977e2 100644
--- a/tools/DOI/authors.py
+++ b/tools/DOI/authors.py
@@ -1,3 +1,4 @@
+#pylint: disable=invalid-name
 from itertools import chain, ifilterfalse
 import string, os, re
 
diff --git a/tools/DOI/doi.py b/tools/DOI/doi.py
index f27811292ed89caf678ee17b70bfcabae46b99a6..56c4a8782a92cef962d8e76cd0750eac47717d4d 100644
--- a/tools/DOI/doi.py
+++ b/tools/DOI/doi.py
@@ -1,3 +1,4 @@
+#pylint: disable=invalid-name
 """A script for generating DataCite DOI's for Mantid releases, to be called by
 a Jenkins job during the release process.  When given a major, minor and patch
 release number along with username and password credentials, it will build a
diff --git a/tools/DefaultConfigFiles/configToCpp.py b/tools/DefaultConfigFiles/configToCpp.py
index 6cd03a271650bc81ed2e03fcdc93110c0f563604..bb924e92af41df65efb48cf20fa26230099a49f7 100644
--- a/tools/DefaultConfigFiles/configToCpp.py
+++ b/tools/DefaultConfigFiles/configToCpp.py
@@ -7,8 +7,8 @@ import sys
 
 with open(sys.argv[2]) as f:
     for line in f:
-    line = line.rstrip('\n')
-    if line == "":
-        print sys.argv[1] + " << std::endl;"
-    else:
-        print sys.argv[1] + " << \"" + line + "\" << std::endl;"
+        line = line.rstrip('\n')
+        if line == "":
+            print sys.argv[1] + " << std::endl;"
+        else:
+            print sys.argv[1] + " << \"" + line + "\" << std::endl;"
diff --git a/tools/PeriodicTable/generate_atom_code.py b/tools/PeriodicTable/generate_atom_code.py
index 6827ab0b10015a849b672f72dbc5f1b0c5c79780..3e2be400a0091c7ae44503bf0c060233302194e2 100755
--- a/tools/PeriodicTable/generate_atom_code.py
+++ b/tools/PeriodicTable/generate_atom_code.py
@@ -1,3 +1,4 @@
+#pylint: disable=invalid-name
 #!/usr/bin/env python
 
 VERSION = "1.0"
diff --git a/tools/Pylint/fixPylint.py b/tools/Pylint/fixPylint.py
new file mode 100644
index 0000000000000000000000000000000000000000..5f3cf1d6990bde995780868418b7132eef3e4060
--- /dev/null
+++ b/tools/Pylint/fixPylint.py
@@ -0,0 +1,173 @@
+#pylint: disable=invalid-name,anomalous-backslash-in-string
+import os
+import re
+import argparse
+
+def fixBadIndent(toModify,indent):
+    err_string=indent.replace(' Bad indentation. Found ','').replace('(bad-indentation)','').split('spaces, expected')
+    bad=int(err_string[0])
+    good=int(err_string[1])
+    return toModify.replace(' '*bad,' '*good)
+
+def fixParens(fname,errorlist,errlines):
+    tofixf=open(fname,'r')
+    file_content=tofixf.readlines()
+    tofixf.close()
+    newcontent=file_content
+    for i,error in zip(errlines,errorlist):
+        if error.find('(superfluous-parens)')!=-1:
+            kwd=error.split("'")[1]
+            pattern=re.compile(kwd+'(?P<spaces>\ *)\((?P<file_content>.*)\)')
+            match=pattern.search(file_content[i])
+            d=match.groupdict()
+            newcontent[i]=file_content[i].replace(kwd+d['spaces']+'('+d['file_content']+')',kwd+' '+d['file_content'])
+    tofixf=open(fname,'w')
+    tofixf.write(''.join(newcontent))
+    tofixf.close()
+
+def fixSeveralErrors(fname,errorlist,errlines):
+    tofixf=open(fname,'r')
+    file_content=tofixf.readlines()
+    tofixf.close()
+    newcontent=file_content
+    for i,error in zip(errlines,errorlist):
+        if error.find('Bad indentation')!=-1:
+            newcontent[i]=fixBadIndent(file_content[i],error)
+        if error.find('missing-final-newline')!=-1:
+            newcontent[-1]+='\n'
+        if error.find('mixed-indentation')!=-1:
+            newcontent[i]=file_content[i].replace('\t', '    ')
+        if error.find('trailing-whitespace')!=-1:
+            newcontent[i]=file_content[i].rstrip()+'\n'
+        if error.find('Unnecessary semicolon')!=-1:
+            newcontent[i]=file_content[i].replace(';','')
+    tofixf=open(fname,'w')
+    tofixf.write(''.join(newcontent))
+    tofixf.close()
+
+def addIgnoreStatement(fname,errorlist):
+    tofixf=open(fname,'r')
+    file_content=tofixf.readlines()
+    tofixf.close()
+    ignore=[]
+    for error in errorlist:
+        if error.find('(invalid-name)')!=-1 and 'invalid-name' not in ignore:
+            ignore.append('invalid-name')
+        if error.find('(no-init)')!=-1 and 'no-init' not in ignore:
+            ignore.append('no-init')
+        if error.find('(too-many-lines)')!=-1 and 'too-many-lines' not in ignore:
+            ignore.append('too-many-lines')
+    if len(ignore)!=0:
+        tofixf=open(fname,'w')
+        tofixf.write("#pylint: disable="+','.join(ignore)+'\n')
+        tofixf.write(''.join(file_content))
+        tofixf.close()
+
+def generate_choices():
+    ch=['simple','parentheses','add_ignores']
+    ch_help=['simple - fixes the following warning: bad-indentation, missing-final-newline, '+\
+             'mixed_indentation, trailing-whitespace, unnecesary-semicolon',
+             'parentheses - fixes superfluous-parens warning',
+             'add_ignores - adds ignore statemets at the beginning of each file to ignore invalid-name, no-init, too-many-lines']
+    chhelp="The possible choices supported are:\n\t"+'\n\t'.join(ch_help)
+    return (ch,chhelp)
+
+if __name__=='__main__':
+    choices,choices_help=generate_choices()
+    parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter,
+                                     epilog=choices_help,
+                                     description='Fix some pylint warnings. It is STRONGLY RECOMMENDED to '+\
+                                                 'rerun the pylintcheck between fixes')
+    parser.add_argument('-fix','--fix', default='simple',
+                        choices=choices,
+                        help='Select things to fix (default: simple). \nSee the choices options below.')
+    parser.add_argument('Filename', type=file, help='The output from "make pylint"')
+    parser.add_argument('-v','--version', action='version', version='%(prog)s 1.0')
+
+    #read pylint.log
+    args = parser.parse_args()
+    oneline=args.Filename.read()
+    args.Filename.close()
+    #ignore everything up to the first error
+    oneline=oneline[oneline.find('****'):]
+    content=oneline.split('\n')
+
+    fileindex=content.index('Checks of the following modules FAILED:')
+    files=[f.strip() for f in content[fileindex+1:-1]]
+    filenumber=0
+    linenumber=0
+    prevFile=True
+
+
+    while linenumber<fileindex:
+        filename=files[filenumber]
+        line=content[linenumber]
+        #find a file
+        if line.find('****')==0 and line.find('PyChop')==-1:
+            modname=line.split('************* Module ')[1]
+            if prevFile:
+                if os.path.isfile(filename):
+                    correct_filename=filename
+                    filenumber+=1
+                    prevFile=True
+                else:
+                    prevFile=False
+                    modname=modname.replace('.','/')
+                    firstslash=modname.find('/')
+                    if firstslash==-1:
+                        correct_filename=filename+'/__init__.py'
+                    else:
+                        correct_filename=filename+modname[firstslash:]+'.py'
+            else:
+                lastmodulename=os.path.split(filename)[1]
+                modbase=modname.split('.')[0]
+                if lastmodulename==modbase: #still in the same module
+                    modname=modname.replace('.','/')
+                    firstslash=modname.find('/')
+                    if firstslash==-1:
+                        correct_filename=filename+'/__init__.py'
+                    else:
+                        correct_filename=filename+modname[firstslash:]+'.py'
+                else: #go to the next file or module
+                    filenumber+=1
+                    filename=files[filenumber]
+                    prevFile=True
+                    if os.path.isfile(filename):
+                        correct_filename=filename
+                        filenumber+=1
+                        prevFile=True
+                    else:
+                        prevFile=False
+                        modname=modname.replace('.','/')
+                        firstslash=modname.find('/')
+                        if firstslash==-1:
+                            correct_filename=filename+'/__init__.py'
+                        else:
+                            correct_filename=filename+modname[firstslash:]+'.py'
+            #process it
+            j=1
+            errors=[]
+            errorlines=[]
+            while linenumber+j<fileindex and content[linenumber+j].find('****')==-1:
+                err=content[linenumber+j]
+                if len(err)>0 and err[0] in ['C','W','E'] and err[1]==':':
+                    lineNumber=int(err.split(':')[1].split(',')[0])-1
+                    errors.append(err.split(':')[2])
+                    errorlines.append(lineNumber)
+                j+=1
+            if args.fix=='simple':
+                fixSeveralErrors(correct_filename,errors,errorlines)
+            elif args.fix=='add_ignores':
+                addIgnoreStatement(correct_filename,errors)
+            elif args.fix=='parentheses':
+                fixParens(correct_filename,errors,errorlines)
+            linenumber+=j-1
+        else:
+            linenumber+=1
+
+
+
+
+
+
+
diff --git a/tools/Pylint/pylint.cfg b/tools/Pylint/pylint.cfg
index eec53d4f7b22bdfd67bc5e8f1c30b956fa6be060..cbf3bb4a69987805eca098774a89baba10598196 100644
--- a/tools/Pylint/pylint.cfg
+++ b/tools/Pylint/pylint.cfg
@@ -57,7 +57,7 @@ disable=W0142,I0011,F0401,W0614,E0602,C0111,C0326,W0401,R0201,R0801
 output-format=colorized
 
 # Include message's id in output
-include-ids=yes
+#include-ids=yes
 
 # Put messages in a separate file for each module / package specified on the
 # command line instead of printing them on stdout. Reports (if any) will be
diff --git a/tools/Pylint/run_pylint.py b/tools/Pylint/run_pylint.py
index 2b51de4194665b59e36f43166812cdb728a1b6c4..8368854c1fcafe1db6c7f464b3fe0a61a6f7922b 100644
--- a/tools/Pylint/run_pylint.py
+++ b/tools/Pylint/run_pylint.py
@@ -57,7 +57,7 @@ class Results(object):
         """
         Return true if all files were clean
         """
-        return (len(self.failures) == 0)
+        return len(self.failures) == 0
 
     def add(self, modulename, status):
         """
@@ -172,8 +172,8 @@ def parse_arguments(argv):
                       help="If provided, store the output in the given file.")
     parser.add_option("-x", "--exclude", dest="exclude", metavar="EXCLUDES",
                       help="If provided, a space-separated list of "
-                            "files/directories to exclude. Relative paths are "
-                            "taken as relative to --basedir")
+                           "files/directories to exclude. Relative paths are "
+                           "taken as relative to --basedir")
 
     parser.set_defaults(format=DEFAULT_PYLINT_FORMAT, exe=DEFAULT_PYLINT_EXE, nofail=False,
                         basedir=os.getcwd(), rcfile=DEFAULT_RCFILE, exclude="")
@@ -242,6 +242,7 @@ def check_module_imports():
       str: String indicating success/failure
     """
     msg = ""
+    #pylint: disable=unused-variable
     try:
         import mantid
     except ImportError, exc:
@@ -292,7 +293,7 @@ def run_checks(targets, serializer, options):
         targetpath = os.path.join(options.basedir, target)
         pkg_init = os.path.join(targetpath, "__init__.py")
         if os.path.isfile(targetpath) or os.path.isfile(pkg_init):
-            overall_stats.add(target, exec_pylint_on_importable(targetpath, serializer, options))
+            overall_stats.add(targetpath, exec_pylint_on_importable(targetpath, serializer, options))
         else:
             overall_stats.update(exec_pylint_on_all(targetpath, serializer, options, excludes))
     ##
@@ -352,7 +353,7 @@ def find_importable_targets(dirpath):
             pkg_init = os.path.join(abspath, "__init__.py")
             if (os.path.isfile(abspath) and item.endswith(".py")) or \
                 os.path.isfile(pkg_init):
-                 importables.append(abspath)
+                importables.append(abspath)
             elif os.path.isdir(abspath):
                 importables.extend(package_walk(abspath))
         return importables
@@ -386,7 +387,7 @@ def exec_pylint_on_importable(srcpath, serializer, options):
     with temp_dir_change(os.path.dirname(srcpath)):
         status = subp.call(cmd, stdout=serializer)
 
-    return (status == 0)
+    return status == 0
 
 #------------------------------------------------------------------------------
 
diff --git a/tools/TestViewer/TestViewer.py b/tools/TestViewer/TestViewer.py
index 428762ca8577534af6bc5449a80c9e08df2360d4..987819601d5c954e4bb51b9a0ce43707c03fdf91 100755
--- a/tools/TestViewer/TestViewer.py
+++ b/tools/TestViewer/TestViewer.py
@@ -4,4 +4,4 @@
 """ Launch the GUI Test Viewer """
 import main_window
 
-main_window.start()
\ No newline at end of file
+main_window.start()
diff --git a/tools/TestViewer/main_window.py b/tools/TestViewer/main_window.py
index 4117295fdb6b377a07b42355098a97c15d4e2bf9..48975b55710a5871b9c86f8211cbe22a839e7ebc 100644
--- a/tools/TestViewer/main_window.py
+++ b/tools/TestViewer/main_window.py
@@ -1,3 +1,4 @@
+#pylint: disable=invalid-name
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
diff --git a/tools/TestViewer/test_info.py b/tools/TestViewer/test_info.py
index c43fb05c0cf7a6b8ba340dea515ec46d1c5643cf..e93f07021bebedf3cb17b4ab1e53fe6281c46a4f 100644
--- a/tools/TestViewer/test_info.py
+++ b/tools/TestViewer/test_info.py
@@ -1,3 +1,4 @@
+#pylint: disable=too-many-lines,invalid-name
 # -*- coding: utf-8 -*-
 """ Classes describing test projects,
 how they are run,
@@ -77,7 +78,7 @@ class TestResult:
     def __eq__(self, other):
         """ Equality comparison """
         if isinstance(other, TestResult):
-            return ((self.value == other.value) and (self.old == other.old))
+            return (self.value == other.value) and (self.old == other.old)
         else:
             return self.value == other
 
@@ -372,7 +373,7 @@ class TestSuite(object):
             self.contents_changed = True
         else:
             for i in xrange(len(self.tests)):
-                if (self.tests[i].name != other.tests[i].name):
+                if self.tests[i].name != other.tests[i].name:
                     self.contents_changed = True
                 self.tests[i].replace_contents( other.tests[i] )
         # Copy local values
@@ -402,7 +403,7 @@ class TestSuite(object):
         oldtime = self.source_file_mtime
         if os.path.exists(self.source_file):
             self.source_file_mtime = os.path.getmtime(self.source_file)
-        return (self.source_file_mtime != oldtime)
+        return self.source_file_mtime != oldtime
 
     def get_selected(self):
         return self.selected
@@ -587,7 +588,7 @@ class TestSuite(object):
             return
         elif len(suites) > 1:
             for xmlSuite in suites:
-                if (suites[0].getAttribute("name") == self.name):
+                if suites[0].getAttribute("name") == self.name:
                     break
         else:
             xmlSuite = suites[0]
@@ -596,7 +597,7 @@ class TestSuite(object):
         xmlCases = xmlSuite.getElementsByTagName("testcase")
         for case in xmlCases:
             classname = case.getAttribute("classname")
-            if (classname == self.classname):
+            if classname == self.classname:
                 # This is the single test name
                 test_name = case.getAttribute("name")
                 test = self.find_test(test_name)
@@ -752,7 +753,7 @@ class TestProject(object):
         # This will run while calling the stdout callback.
         (status, output) = run_command_with_callback(full_command, callback_func)
 
-        if (status != 0):
+        if status != 0:
             msg = "-------- BUILD FAILED! ---------"
             if not callback_func is None: callback_func("%s" % msg)
             self.build_succeeded = False
@@ -1055,7 +1056,7 @@ class MultipleProjects(object):
             word = val[1:]
             for pj in self.projects:
                 for suite in pj.suites:
-                    suite.selected = not (word in suite.name)
+                    suite.selected = not word in suite.name
                     if suite.selected: num += 1
         else:
             word = val
@@ -1486,14 +1487,14 @@ def test_results_compiling():
 
 def test_age():
     a = TestSingle("my_test_test", None)
-    assert (a.state == TestResult.NOT_RUN)
+    assert a.state == TestResult.NOT_RUN
     a.age()
-    assert (a.state == TestResult.NOT_RUN)
-    assert (a.state.old)
+    assert a.state == TestResult.NOT_RUN
+    assert a.state.old
     a = TestSingle("my_test_test", None)
     a.state = TestResult(TestResult.ALL_PASSED)
     a.age()
-    assert (a.state.old)
+    assert a.state.old
 
 test_results_compiling()
 test_age()
diff --git a/tools/TestViewer/test_tree.py b/tools/TestViewer/test_tree.py
index f373d29ff19abf5b7fb4b5d4189f39e3424d7fb6..9c233db03d27a2f1b4e6569cd9ba148cf84dbf37 100644
--- a/tools/TestViewer/test_tree.py
+++ b/tools/TestViewer/test_tree.py
@@ -1,3 +1,4 @@
+#pylint: disable=invalid-name,no-init
 """ An AbstractTreeItem implementation for a QTreeView
 that uses the results from test runners. """
 
@@ -295,7 +296,7 @@ class TestTreeModel(QtCore.QAbstractItemModel):
 
         # What background color?
         if role == Qt.BackgroundRole:
-            return item.background_color();
+            return item.background_color()
 
         #User role is used when directly querying the contents of the item
         if role == Qt.UserRole:
@@ -490,7 +491,7 @@ class TestTreeModel(QtCore.QAbstractItemModel):
                 for k in xrange(num_tests):
                     test_indx = self.index(k, 0, suite_indx)
                     # Sets it as checked.
-                    self.setData(test_indx, QtCore.Qt.Checked, QtCore.Qt.CheckStateRole);
+                    self.setData(test_indx, QtCore.Qt.Checked, QtCore.Qt.CheckStateRole)
 
     def mouseDoubleClickEvent(self):
         print "mouseDoubleClickEvent"
@@ -536,7 +537,7 @@ class TreeFilterProxyModel(QSortFilterProxyModel):
                 return False
             if self.selected_only:
                 if isinstance(item, TestProject) or  isinstance(item, TestSuite) :
-                    return (item.get_selected() > 0)
+                    return item.get_selected() > 0
                 else:
                     # Don't filter out TestSingles based on selection (since they're all selected)
                     return True
diff --git a/tools/TestViewer/ui_main_window.py b/tools/TestViewer/ui_main_window.py
index 415f4cf3f0b9fc2ffc51ce79f3bb345c6d99e958..d33d69c8a7d567dd0f6e2337f7b286e84a9f8ab6 100644
--- a/tools/TestViewer/ui_main_window.py
+++ b/tools/TestViewer/ui_main_window.py
@@ -1,3 +1,4 @@
+#pylint: disable=invalid-name
 # -*- coding: utf-8 -*-
 
 # Form implementation generated from reading ui file 'main_window.ui'
diff --git a/tools/VTKConverter/VTKConvert.py b/tools/VTKConverter/VTKConvert.py
index 5b84926cc4900576e1ecede9e9337d983153c9a1..3048c2c46f2f3071bb0b9f104c26f61ca1d7706f 100644
--- a/tools/VTKConverter/VTKConvert.py
+++ b/tools/VTKConverter/VTKConvert.py
@@ -1,3 +1,4 @@
+#pylint: disable=invalid-name
 #! /usr/bin/python
 # Convert an acor file into VTK format (specifically a vtp file)
 from xml.dom import minidom
diff --git a/tools/VTKConverter/processISISData.py b/tools/VTKConverter/processISISData.py
index 7d00849ca3f3d570c99e3dc54354b7cbac107ff3..7a988d0adbbaab4180538af8c941ed45a67dca34 100644
--- a/tools/VTKConverter/processISISData.py
+++ b/tools/VTKConverter/processISISData.py
@@ -1,24 +1,25 @@
+#pylint: disable=invalid-name
 #!/usr/bin/python
 import os
 import sys
 import VTKConvert
 
-if( len(sys.argv) == 1 ):
+if  len(sys.argv) == 1 :
     print "Usage: processISISData file-name1 file-name2 ...\n       processISISDATA dir-name"
     exit(1)
 
 names=[]
 is_dir = os.path.isdir(sys.argv[1])
-if( is_dir ):
+if  is_dir :
     names = os.listdir(sys.argv[1])
 else:
     for i in range(1,len(sys.argv)):
         names.append(sys.argv[i])
 
 prefix=""
-if( is_dir ):
+if  is_dir :
     prefix = sys.argv[1].split('/')[0] + "-VTU/"
-    if( os.path.isdir(prefix) ):
+    if  os.path.isdir(prefix) :
         print "Directory " + prefix + " already exists, please move\n"
         exit(1)
     else:
@@ -27,7 +28,7 @@ else:
     prefix = "./"
 
 for file in names:
-    if( is_dir ):
+    if  is_dir :
         filename = sys.argv[1] + file
     VTKConvert.convertToVTU(filename, prefix)
 
diff --git a/tools/reports/facility-code-changes.py b/tools/reports/facility-code-changes.py
index 2ea10c847d974cb144283e74900c2a675eb52a84..f8f1e906cde51814c8d5fd820b323dceb9f08b5a 100644
--- a/tools/reports/facility-code-changes.py
+++ b/tools/reports/facility-code-changes.py
@@ -1,3 +1,4 @@
+#pylint: disable=invalid-name
 from __future__ import (absolute_import, division, print_function, unicode_literals)
 
 __author__ = 'Stuart Campbell'
diff --git a/tools/reports/release-list.py b/tools/reports/release-list.py
index f6a48764d64dbeade4b1df4a4ed9dfb7e7a93045..a74995bfa317d57197b2f7726be302e138e8ff08 100644
--- a/tools/reports/release-list.py
+++ b/tools/reports/release-list.py
@@ -1,3 +1,4 @@
+#pylint: disable=invalid-name
 from __future__ import (absolute_import, division, print_function, unicode_literals)
 
 import csv
diff --git a/tools/scripts/ConvertBadAlgmLinks.py b/tools/scripts/ConvertBadAlgmLinks.py
index 4d7d71e86989bbaa469f1535c5510afdd5ce52ee..6759d9d23b3b5bdf2004bd2afeb048e9b6edd5c4 100644
--- a/tools/scripts/ConvertBadAlgmLinks.py
+++ b/tools/scripts/ConvertBadAlgmLinks.py
@@ -1,3 +1,4 @@
+#pylint: disable=invalid-name
 import re, glob, os
 
 def grep(patt,lines):
@@ -30,13 +31,13 @@ for filename in files:
 
     #print os.path.basename(filename)[:-4]
     with open(filename) as file:
-      lines = file.readlines()
-      for alg in algs:
-        expr = regexs[alg]
-        results = grep(expr, lines)
-        if results:
-          print filename
-          print results
+        lines = file.readlines()
+        for alg in algs:
+            expr = regexs[alg]
+            results = grep(expr, lines)
+            if results:
+                print filename
+                print results
 
 
 
diff --git a/tools/scripts/CorrectConceptLinksinAlgPages.py b/tools/scripts/CorrectConceptLinksinAlgPages.py
index 700472f0529451dd752ec48008bf364e34f51806..7dcd787a465a2a84151c64ec152e6b0f2ba720c7 100644
--- a/tools/scripts/CorrectConceptLinksinAlgPages.py
+++ b/tools/scripts/CorrectConceptLinksinAlgPages.py
@@ -1,51 +1,52 @@
+#pylint: disable=invalid-name
 import os,  re
 import urllib2
 
 concepts = ['Algorithm',
-'Analysis_Data_Service',
-'categories',
-'Create_an_IDF',
-'Data_Service',
-'Dynamic_Factory',
-'Error_Propagation',
-'EventWorkspace',
-'Facilities_File',
-'FitConstraint',
-'Framework_Manager',
-'Geometry',
-'Geometry_of_Position',
-'Geometry_of_Shape',
-'HowToDefineGeometricShape',
-'index',
-'Instrument',
-'InstrumentDefinitionFile',
-'InstrumentParameterFile',
-'Instrument_Data_Service',
-'Lattice',
-'LET_Sample_IDF',
-'MatrixWorkspace',
-'MDHistoWorkspace',
-'MDWorkspace',
-'Nexus_file',
-'Plugin',
-'Project',
-'Properties',
-'Properties_File',
-'RAW_File',
-'Run',
-'SANS2D_Sample_IDF',
-'Shared_Pointer',
-'Table_Workspaces',
-'Unit_Factory',
-'UserAlgorithms',
-'Workflow_Algorithm',
-'Workspace',
-'Workspace2D',
-'WorkspaceGroup']
+            'Analysis_Data_Service',
+            'categories',
+            'Create_an_IDF',
+            'Data_Service',
+            'Dynamic_Factory',
+            'Error_Propagation',
+            'EventWorkspace',
+            'Facilities_File',
+            'FitConstraint',
+            'Framework_Manager',
+            'Geometry',
+            'Geometry_of_Position',
+            'Geometry_of_Shape',
+            'HowToDefineGeometricShape',
+            'index',
+            'Instrument',
+            'InstrumentDefinitionFile',
+            'InstrumentParameterFile',
+            'Instrument_Data_Service',
+            'Lattice',
+            'LET_Sample_IDF',
+            'MatrixWorkspace',
+            'MDHistoWorkspace',
+            'MDWorkspace',
+            'Nexus_file',
+            'Plugin',
+            'Project',
+            'Properties',
+            'Properties_File',
+            'RAW_File',
+            'Run',
+            'SANS2D_Sample_IDF',
+            'Shared_Pointer',
+            'Table_Workspaces',
+            'Unit_Factory',
+            'UserAlgorithms',
+            'Workflow_Algorithm',
+            'Workspace',
+            'Workspace2D',
+            'WorkspaceGroup']
 
 
 def outputError(alg, algVersion, description, notes=""):
-  print "%s, %i, %s, %s" % (alg, algVersion, description, notes)
+    print "%s, %i, %s, %s" % (alg, algVersion, description, notes)
 
 rstdir = r"C:\Mantid\Code\Mantid\docs\source\algorithms"
 conceptsPattern = {}
@@ -61,17 +62,17 @@ for alg in algs:
     fileFound = False
     filename = os.path.join(rstdir,alg + "-v" + str(algVersion) + ".rst")
     if os.path.exists(filename):
-    algText = ""
-    with open (filename, "r") as algRst:
-        fileFound = True
-        algText = algRst.read()
-    for concept in concepts:
-    	regex = conceptsPattern[concept]
-    	while (regex.search(algText) != None):
-    	    outputError(alg, algVersion, "found", concept)
-    	    algText = regex.sub(r":ref:`\1 <\2>`",algText)
+        algText = ""
+        with open (filename, "r") as algRst:
+            fileFound = True
+            algText = algRst.read()
+        for concept in concepts:
+            regex = conceptsPattern[concept]
+            while regex.search(algText) != None:
+                outputError(alg, algVersion, "found", concept)
+                algText = regex.sub(r":ref:`\1 <\2>`",algText)
                 with open (filename, "w") as algRst:
-    		algRst.write(algText)
+                    algRst.write(algText)
 
     if fileFound==False:
         outputError(alg, algVersion, "File not found")
diff --git a/tools/scripts/FindIncompleteAlgRSTPages.py b/tools/scripts/FindIncompleteAlgRSTPages.py
index a7573c89ff2705bc520ead33fea9940b662a231f..f4d05d10629102eab5eb160a5ed24eb1b0ff7749 100644
--- a/tools/scripts/FindIncompleteAlgRSTPages.py
+++ b/tools/scripts/FindIncompleteAlgRSTPages.py
@@ -1,3 +1,4 @@
+#pylint: disable=invalid-name
 import os,  re
 import urllib2
 
@@ -6,7 +7,7 @@ def readWebPage(url):
     opener = urllib2.build_opener(proxy)
     urllib2.install_opener(opener)
     aResp =urllib2.urlopen(url)
-    web_pg = aResp.read();
+    web_pg = aResp.read()
     return web_pg
 
 def ticketExists(alg, ticketHash):
diff --git a/tools/scripts/TestWikiPython.py b/tools/scripts/TestWikiPython.py
index 09ca6e06bc757b869f1ba53f913dd6e33c0c4c7d..63d0e4b367106c17a36bebcbf2cdb8caec1f337b 100644
--- a/tools/scripts/TestWikiPython.py
+++ b/tools/scripts/TestWikiPython.py
@@ -1,3 +1,4 @@
+#pylint: disable=invalid-name
 ###########################################################################################
 # Extracts code blocks marked as python from mediawiki pages and checks they run
 # run with -h for command line arguments
@@ -133,7 +134,7 @@ parser.add_argument('-o', '--o',
                     help='Provide a path to output to an output directory')
 
 args = parser.parse_args()
-urlList = [];
+urlList = []
 baseUrl = "http://www.mantidproject.org/"
 if args.s is not None:
     baseUrl = args.s
diff --git a/tools/scripts/extractAlgorithmNames.py b/tools/scripts/extractAlgorithmNames.py
index 90c7a661aed65f9d78fc2fc2878c2f21f3f2b9ea..8945b898c9e698c5c3d261c1d0ba9d35ad42635e 100644
--- a/tools/scripts/extractAlgorithmNames.py
+++ b/tools/scripts/extractAlgorithmNames.py
@@ -1,3 +1,4 @@
+#pylint: disable=invalid-name
 # simply just print out all algorithm names in a directory which can be piped
 # to a file
 
diff --git a/tools/scripts/extractAuthorNamesFromGit.py b/tools/scripts/extractAuthorNamesFromGit.py
index ee6bf1e2eceb5ff853dc9c5baa93a86814ee91d0..728ac36dadd8f2cc94f81df3cf512a7f4f4b93bb 100644
--- a/tools/scripts/extractAuthorNamesFromGit.py
+++ b/tools/scripts/extractAuthorNamesFromGit.py
@@ -1,3 +1,4 @@
+#pylint: disable=invalid-name
 # This python script is run after running extractAlgorithmNames.py, where
 # the output of that script is saved to a *.txt
 #
@@ -18,7 +19,7 @@ allAlgs = [line.strip() for line in open(algorithmList)]
 os.chdir('PythonInterface/plugins/algorithms/WorkflowAlgorithms')
 for line in allAlgs:
     #print line
-    fullline = line    
+    fullline = line
     args = [
         'git', 'log',
         '--pretty=short',
@@ -30,11 +31,11 @@ for line in allAlgs:
     authors = subprocess.check_output(args).replace('"', '').split('\n')
     authors = set(authors)
     authors = authors - set([''])
-    
+
     for author in authors:
         #print author
         fullline = fullline + ", " + author
-	
+
     print fullline
 
 #line = 'GroupWorkspaces.cpp'
@@ -54,5 +55,5 @@ for line in allAlgs:
 #for author in authors:
     #print author
 #    fullline = fullline + ", " + author
-	
+
 #print fullline
diff --git a/tools/skipped_systemtests.py b/tools/skipped_systemtests.py
index c13d3e140d18102f3e4e847377f2ebcaacca1c8b..3ffdb9fb5837d1c055e93e8f019d11e31384d56e 100755
--- a/tools/skipped_systemtests.py
+++ b/tools/skipped_systemtests.py
@@ -1,3 +1,4 @@
+#pylint: disable=invalid-name
 #!/usr/bin/env python
 
 import ast
@@ -33,7 +34,7 @@ def addTestResult(results, case, label):
 
 
 def printResultCell(mark, length):
-    if (mark):
+    if mark:
         left = int(length/2)
         right = length-left-1
         print "%sx%s" % (' '*left, ' '*right),