From 8101afa8785668a30c6b9eddc54a43f8656304f5 Mon Sep 17 00:00:00 2001
From: Federico Montesino Pouzols <federico.montesino-pouzols@stfc.ac.uk>
Date: Thu, 29 Oct 2015 16:26:59 +0000
Subject: [PATCH] methods for rebinning added, documentation for new tab, re
 #13808

---
 .../EnggDiffractionPresWorker.h               |  31 ++-
 .../EnggDiffractionPresenter.h                |  27 ++
 .../EnggDiffractionQtTabPreproc.ui            | 260 ++++++++++--------
 .../EnggDiffractionViewQtGUI.h                |   4 +-
 .../EnggDiffraction/IEnggDiffractionView.h    |   9 +-
 .../EnggDiffractionPresenter.cpp              | 189 ++++++++++++-
 .../EnggDiffractionViewQtGUI.cpp              |  11 +-
 .../test/EnggDiffractionPresenterTest.h       |   5 +-
 .../test/EnggDiffractionViewMock.h            |   6 +-
 .../interfaces/Engineering_Diffraction.rst    |  51 +++-
 10 files changed, 448 insertions(+), 145 deletions(-)

diff --git a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/EnggDiffraction/EnggDiffractionPresWorker.h b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/EnggDiffraction/EnggDiffractionPresWorker.h
index 47bcff662e7..99245626a29 100644
--- a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/EnggDiffraction/EnggDiffractionPresWorker.h
+++ b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/EnggDiffraction/EnggDiffractionPresWorker.h
@@ -42,7 +42,8 @@ public:
   EnggDiffWorker(EnggDiffractionPresenter *pres, const std::string &outFilename,
                  const std::string &vanNo, const std::string &ceriaNo)
       : m_pres(pres), m_outFilenames(), m_outCalibFilename(outFilename),
-        m_vanNo(vanNo), m_ceriaNo(ceriaNo), m_banks() {}
+        m_vanNo(vanNo), m_ceriaNo(ceriaNo), m_banks(), m_bin(.0),
+        m_nperiods(0) {}
 
   /// for focusing
   EnggDiffWorker(EnggDiffractionPresenter *pres, const std::string &outDir,
@@ -51,7 +52,19 @@ public:
                  const std::string &specIDs, const std::string &dgFile)
       : m_pres(pres), m_outFilenames(outFilenames), m_outCalibFilename(),
         m_runNo(runNo), m_outDir(outDir), m_banks(banks), m_specIDs(specIDs),
-        m_dgFile(dgFile) {}
+        m_dgFile(dgFile), m_bin(.0), m_nperiods(0) {}
+
+  // for rebinning (ToF)
+  EnggDiffWorker(EnggDiffractionPresenter *pres, const std::string &runNo,
+                 double bin, const std::string &outWSName)
+      : m_pres(pres), m_runNo(runNo), m_bin(bin), m_nperiods(0),
+        m_outWSName(outWSName) {}
+
+  // for rebinning (by pulse times)
+  EnggDiffWorker(EnggDiffractionPresenter *pres, const std::string &runNo,
+                 size_t nperiods, double timeStep, const std::string &outWSName)
+      : m_pres(pres), m_runNo(runNo), m_bin(timeStep), m_nperiods(nperiods),
+        m_outWSName(outWSName) {}
 
 private slots:
 
@@ -74,6 +87,16 @@ private slots:
     emit finished();
   }
 
+  void rebinTime() {
+    m_pres->doRebinningTime(m_runNo, m_bin, m_outWSName);
+    emit finished();
+  }
+
+  void rebinPulses() {
+    m_pres->doRebinningPulses(m_runNo, m_nperiods, m_bin, m_outWSName);
+    emit finished();
+  }
+
 signals:
   void finished();
 
@@ -93,6 +116,10 @@ private:
   const std::string m_specIDs;
   // for focusing "texture"
   const std::string m_dgFile;
+  // parameters for pre-processing/rebinning
+  const double m_bin;
+  const size_t m_nperiods;
+  const std::string m_outWSName;
 };
 
 } // namespace CustomInterfaces
diff --git a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/EnggDiffraction/EnggDiffractionPresenter.h b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/EnggDiffraction/EnggDiffractionPresenter.h
index 89421a9cabb..ae84b508673 100644
--- a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/EnggDiffraction/EnggDiffractionPresenter.h
+++ b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/EnggDiffraction/EnggDiffractionPresenter.h
@@ -71,6 +71,13 @@ public:
                   const std::string &runNo, const std::vector<bool> &banks,
                   const std::string &specNos, const std::string &dgFile);
 
+  /// pre-processing re-binning with Rebin, for a worker/thread
+  void doRebinningTime(const std::string &runNo, double bin,
+                       const std::string &outWSName);
+
+  /// pre-processing re-binning with RebinByPulseTimes, for a worker/thread
+  void doRebinningPulses(const std::string &runNo, size_t nperiods, double bin,
+                         const std::string &outWSName);
 protected:
   void initialize();
 
@@ -94,6 +101,7 @@ protected:
 protected slots:
   void calibrationFinished();
   void focusingFinished();
+  void rebinningFinished();
 
 private:
   bool validateRBNumber(const std::string &rbn) const;
@@ -183,6 +191,23 @@ private:
                               Mantid::API::ITableWorkspace_sptr &vanIntegWS,
                               Mantid::API::MatrixWorkspace_sptr &vanCurvesWS);
 
+  /// @name Methods related to pre-processing / re-binning
+  //@{
+  void inputChecksBeforeRebin(const std::string &runNo);
+
+  void inputChecksBeforeRebinTime(const std::string &runNo, double bin);
+
+  void inputChecksBeforeRebinPulses(const std::string &runNo, size_t nperiods,
+                                    double timeStep);
+
+  void startAsyncRebinningTimeWorker(const std::string &runNo, double bin,
+                                     const std::string &outWSName);
+
+  void startAsyncRebinningPulsesWorker(const std::string &runNo,
+                                       size_t nperiods, double timeStep,
+                                       const std::string &outWSName);
+  //@}
+
   // plots workspace according to the user selection
   void plotFocusedWorkspace(std::string outWSName, std::string bank);
 
@@ -215,6 +240,8 @@ private:
   bool m_calibFinishedOK;
   /// true if the last focusing completed successfully
   bool m_focusFinishedOK;
+  /// true if the last pre-processing/re-binning completed successfully
+  bool m_rebinningFinishedOK;
 
   /// Counter for the cropped output files
   static int g_croppedCounter;
diff --git a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/EnggDiffraction/EnggDiffractionQtTabPreproc.ui b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/EnggDiffraction/EnggDiffractionQtTabPreproc.ui
index 5779d57c3ec..e7132c0cac4 100644
--- a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/EnggDiffraction/EnggDiffractionQtTabPreproc.ui
+++ b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/EnggDiffraction/EnggDiffractionQtTabPreproc.ui
@@ -15,113 +15,116 @@
   </property>
   <layout class="QVBoxLayout" name="verticalLayout">
    <item>
-    <layout class="QGridLayout" name="gridLayout_3">
-     <item row="0" column="0">
-      <layout class="QHBoxLayout" name="horizontalLayout_9">
-       <item>
-        <widget class="QLabel" name="label_cropped_run_num">
-         <property name="text">
-          <string/>
-         </property>
-        </widget>
-       </item>
-       <item>
-        <spacer name="horizontalSpacer_7">
-         <property name="orientation">
-          <enum>Qt::Horizontal</enum>
-         </property>
-         <property name="sizeHint" stdset="0">
-          <size>
-           <width>98</width>
-           <height>20</height>
-          </size>
-         </property>
-        </spacer>
-       </item>
-       <item>
-        <widget class="MantidQt::MantidWidgets::MWRunFiles" name="MWRunFiles_preproc_run_num" native="true">
-         <property name="text" stdset="0">
-          <string/>
-         </property>
-         <property name="readOnly" stdset="0">
-          <bool>false</bool>
-         </property>
-         <property name="label" stdset="0">
-          <string>Run #:</string>
-         </property>
-         <property name="multipleFiles" stdset="0">
-          <bool>true</bool>
-         </property>
-        </widget>
-       </item>
-      </layout>
-     </item>
-     <item row="1" column="0">
-      <widget class="QGroupBox" name="groupBox">
-       <property name="title">
-        <string>Regular time binning:</string>
+    <layout class="QHBoxLayout" name="horizontalLayout_9">
+     <item>
+      <widget class="QLabel" name="label_cropped_run_num">
+       <property name="text">
+        <string/>
        </property>
-       <layout class="QGridLayout" name="gridLayout">
-        <item row="0" column="0">
-         <spacer name="horizontalSpacer">
-          <property name="orientation">
-           <enum>Qt::Horizontal</enum>
-          </property>
-          <property name="sizeHint" stdset="0">
-           <size>
-            <width>408</width>
-            <height>20</height>
-           </size>
-          </property>
-         </spacer>
-        </item>
-        <item row="0" column="1">
-         <widget class="QLabel" name="label">
-          <property name="text">
-           <string>Time bin:</string>
-          </property>
-         </widget>
-        </item>
-        <item row="0" column="2">
-         <widget class="QDoubleSpinBox" name="doubleSpinBox_time_bin">
-          <property name="decimals">
-           <number>6</number>
-          </property>
-          <property name="singleStep">
-           <double>0.000001000000000</double>
-          </property>
-         </widget>
-        </item>
-        <item row="1" column="2">
-         <widget class="QPushButton" name="pushButton_rebin_time">
-          <property name="text">
-           <string>Rebin</string>
-          </property>
-         </widget>
-        </item>
-        <item row="1" column="0" colspan="2">
-         <spacer name="horizontalSpacer_2">
-          <property name="orientation">
-           <enum>Qt::Horizontal</enum>
-          </property>
-          <property name="sizeHint" stdset="0">
-           <size>
-            <width>470</width>
-            <height>21</height>
-           </size>
-          </property>
-         </spacer>
-        </item>
-       </layout>
       </widget>
      </item>
-     <item row="2" column="0">
-      <widget class="QGroupBox" name="groupBox_2">
-       <property name="title">
-        <string>Multi-period data:</string>
+     <item>
+      <spacer name="horizontalSpacer_7">
+       <property name="orientation">
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name="sizeHint" stdset="0">
+        <size>
+         <width>98</width>
+         <height>20</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+     <item>
+      <widget class="MantidQt::MantidWidgets::MWRunFiles" name="MWRunFiles_preproc_run_num" native="true">
+       <property name="text" stdset="0">
+        <string/>
+       </property>
+       <property name="readOnly" stdset="0">
+        <bool>false</bool>
+       </property>
+       <property name="label" stdset="0">
+        <string>Run #:</string>
+       </property>
+       <property name="multipleFiles" stdset="0">
+        <bool>true</bool>
        </property>
-       <layout class="QGridLayout" name="gridLayout_2">
-        <item row="0" column="0">
+      </widget>
+     </item>
+    </layout>
+   </item>
+   <item>
+    <widget class="QGroupBox" name="groupBox">
+     <property name="title">
+      <string>Regular time binning:</string>
+     </property>
+     <layout class="QGridLayout" name="gridLayout">
+      <item row="0" column="0">
+       <spacer name="horizontalSpacer">
+        <property name="orientation">
+         <enum>Qt::Horizontal</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>408</width>
+          <height>20</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+      <item row="0" column="1">
+       <widget class="QLabel" name="label">
+        <property name="text">
+         <string>Time bin:</string>
+        </property>
+       </widget>
+      </item>
+      <item row="0" column="2">
+       <widget class="QDoubleSpinBox" name="doubleSpinBox_time_bin">
+        <property name="suffix">
+         <string>s</string>
+        </property>
+        <property name="decimals">
+         <number>6</number>
+        </property>
+        <property name="singleStep">
+         <double>0.000001000000000</double>
+        </property>
+       </widget>
+      </item>
+      <item row="1" column="2">
+       <widget class="QPushButton" name="pushButton_rebin_time">
+        <property name="text">
+         <string>Rebin</string>
+        </property>
+       </widget>
+      </item>
+      <item row="1" column="0" colspan="2">
+       <spacer name="horizontalSpacer_2">
+        <property name="orientation">
+         <enum>Qt::Horizontal</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>470</width>
+          <height>21</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
+    <widget class="QGroupBox" name="groupBox_2">
+     <property name="title">
+      <string>Multi-period data (rebinning by pulse time):</string>
+     </property>
+     <layout class="QGridLayout" name="gridLayout_2">
+      <item row="0" column="0">
+       <layout class="QHBoxLayout" name="horizontalLayout_2">
+        <item>
          <spacer name="horizontalSpacer_4">
           <property name="orientation">
            <enum>Qt::Horizontal</enum>
@@ -134,17 +137,25 @@
           </property>
          </spacer>
         </item>
-        <item row="0" column="1">
+        <item>
          <widget class="QLabel" name="label_nperiods">
           <property name="text">
            <string>Number of periods:</string>
           </property>
          </widget>
         </item>
-        <item row="0" column="2" rowspan="2">
-         <widget class="QSpinBox" name="spinBox_nperiods"/>
+        <item>
+         <widget class="QSpinBox" name="spinBox_nperiods">
+          <property name="value">
+           <number>1</number>
+          </property>
+         </widget>
         </item>
-        <item row="1" column="0" rowspan="2">
+       </layout>
+      </item>
+      <item row="1" column="0">
+       <layout class="QHBoxLayout" name="horizontalLayout_3">
+        <item>
          <spacer name="horizontalSpacer_5">
           <property name="orientation">
            <enum>Qt::Horizontal</enum>
@@ -157,24 +168,37 @@
           </property>
          </spacer>
         </item>
-        <item row="2" column="1">
+        <item>
          <widget class="QLabel" name="label_pulses_period">
           <property name="text">
-           <string>Pulses per period:</string>
+           <string>Step on time axis:</string>
           </property>
          </widget>
         </item>
-        <item row="2" column="2">
-         <widget class="QSpinBox" name="spinBox_pulses_per_period">
+        <item>
+         <widget class="QDoubleSpinBox" name="doubleSpinBox_step_time">
+          <property name="suffix">
+           <string>s</string>
+          </property>
+          <property name="decimals">
+           <number>6</number>
+          </property>
           <property name="minimum">
-           <number>1</number>
+           <double>0.000001000000000</double>
           </property>
           <property name="maximum">
-           <number>999999999</number>
+           <double>999999999.000000000000000</double>
+          </property>
+          <property name="value">
+           <double>0.100000000000000</double>
           </property>
          </widget>
         </item>
-        <item row="3" column="0" colspan="2">
+       </layout>
+      </item>
+      <item row="2" column="0">
+       <layout class="QHBoxLayout" name="horizontalLayout">
+        <item>
          <spacer name="horizontalSpacer_3">
           <property name="orientation">
            <enum>Qt::Horizontal</enum>
@@ -187,7 +211,7 @@
           </property>
          </spacer>
         </item>
-        <item row="3" column="2">
+        <item>
          <widget class="QPushButton" name="pushButton_rebin_multiperiod">
           <property name="text">
            <string>Rebin</string>
@@ -195,9 +219,9 @@
          </widget>
         </item>
        </layout>
-      </widget>
-     </item>
-    </layout>
+      </item>
+     </layout>
+    </widget>
    </item>
    <item>
     <spacer name="verticalSpacer">
diff --git a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/EnggDiffraction/EnggDiffractionViewQtGUI.h b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/EnggDiffraction/EnggDiffractionViewQtGUI.h
index 8d5b5e1b0bb..1a1911eaf5c 100644
--- a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/EnggDiffraction/EnggDiffractionViewQtGUI.h
+++ b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/EnggDiffraction/EnggDiffractionViewQtGUI.h
@@ -126,9 +126,9 @@ public:
 
   virtual double rebinningTimeBin() const;
 
-  virtual size_t rebinningNumberPeriods() const;
+  virtual size_t rebinningPulsesNumberPeriods() const;
 
-  virtual size_t rebinningPulsesPerPeriod() const;
+  virtual double rebinningPulsesTime() const;
 
   virtual void plotFocusedSpectrum(const std::string &wsName);
 
diff --git a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/EnggDiffraction/IEnggDiffractionView.h b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/EnggDiffraction/IEnggDiffractionView.h
index 98df623e7e9..92fc7fbcc63 100644
--- a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/EnggDiffraction/IEnggDiffractionView.h
+++ b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/EnggDiffraction/IEnggDiffractionView.h
@@ -284,7 +284,8 @@ public:
 
   /**
    * For when pre-processing from event to histo data using a regular
-   * time bin.
+   * time bin. Here time refers to time units for rebinning in
+   * time-of-flight.
    *
    * @param time bin to re-bin in microseconds
    */
@@ -295,14 +296,14 @@ public:
    *
    * @param number of periods to use
    */
-  virtual size_t rebinningNumberPeriods() const = 0;
+  virtual size_t rebinningPulsesNumberPeriods() const = 0;
 
   /**
    * For when pre-processing from multiperiod event to histo data.
    *
-   * @param number of pulses per period
+   * @param the time parameter (bin width) when rebinning by pulses.
    */
-  virtual size_t rebinningPulsesPerPeriod() const = 0;
+  virtual double rebinningPulsesTime() const = 0;
   //@}
 
   /**
diff --git a/MantidQt/CustomInterfaces/src/EnggDiffraction/EnggDiffractionPresenter.cpp b/MantidQt/CustomInterfaces/src/EnggDiffraction/EnggDiffractionPresenter.cpp
index d2d7fd0903f..d0c72235164 100644
--- a/MantidQt/CustomInterfaces/src/EnggDiffraction/EnggDiffractionPresenter.cpp
+++ b/MantidQt/CustomInterfaces/src/EnggDiffraction/EnggDiffractionPresenter.cpp
@@ -35,6 +35,7 @@ int EnggDiffractionPresenter::g_croppedCounter = 0;
 
 EnggDiffractionPresenter::EnggDiffractionPresenter(IEnggDiffractionView *view)
     : m_workerThread(NULL), m_calibFinishedOK(false), m_focusFinishedOK(false),
+      m_rebinningFinishedOK(false),
       m_view(view) /*, m_model(new EnggDiffractionModel()), */ {
   if (!m_view) {
     throw std::runtime_error(
@@ -260,16 +261,52 @@ void EnggDiffractionPresenter::startFocusing(const std::string &runNo,
 void EnggDiffractionPresenter::processResetFocus() { m_view->resetFocus(); }
 
 void EnggDiffractionPresenter::processRebinTime() {
-  std::string runno= m_view->currentPreprocRunNo();
+  std::string runNo = m_view->currentPreprocRunNo();
   double bin = m_view->rebinningTimeBin();
-  // TODO: rebin, start worker
+
+  try {
+    inputChecksBeforeRebinTime(runNo, bin);
+  } catch (std::invalid_argument &ia) {
+    m_view->userWarning(
+        "Error in the inputs required to pre-process (rebin) a run", ia.what());
+    return;
+  }
+
+  const std::string outWSName = "engggui_preproc_time_ws";
+  g_log.notice() << "EnggDiffraction GUI: starting new pre-processing "
+                    "(re-binning) with a TOF bin. This"
+                    "may take some seconds... " << std::endl;
+
+  m_view->enableCalibrateAndFocusActions(false);
+  // GUI-blocking alternative:
+  // doRebinningTime(runNo, bin, outWSName)
+  // rebinningFinished()
+  startAsyncRebinningTimeWorker(runNo, bin, outWSName);
 }
 
 void EnggDiffractionPresenter::processRebinMultiperiod() {
-  std::string runno = m_view->currentPreprocRunNo();
-  size_t nperiods = m_view->rebinningNumberPeriods();
-  size_t ppp = m_view->rebinningPulsesPerPeriod();
-  // TODO: rebin, start worker
+  std::string runNo = m_view->currentPreprocRunNo();
+  size_t nperiods = m_view->rebinningPulsesNumberPeriods();
+  double timeStep = m_view->rebinningPulsesTime();
+
+  try {
+    inputChecksBeforeRebinPulses(runNo, nperiods, timeStep);
+  } catch (std::invalid_argument &ia) {
+    m_view->userWarning("Error in the inputs required to pre-process (rebin) a "
+                        "run by pulse times",
+                        ia.what());
+    return;
+  }
+  const std::string outWSName = "engggui_preproc_by_pulse_time_ws";
+  g_log.notice() << "EnggDiffraction GUI: starting new pre-processing "
+                    "(re-binning) by pulse times. This"
+                    "may take some seconds... " << std::endl;
+
+  m_view->enableCalibrateAndFocusActions(false);
+  // GUI-blocking alternative:
+  // doRebinningPulses(runNo, nperiods, timeStep, outWSName)
+  // rebinningFinished()
+  startAsyncRebinningPulsesWorker(runNo, nperiods, timeStep, outWSName);
 }
 
 void EnggDiffractionPresenter::processLogMsg() {
@@ -1381,6 +1418,146 @@ void EnggDiffractionPresenter::calcVanadiumWorkspaces(
   vanCurvesWS = ADS.retrieveWS<MatrixWorkspace>(curvesName);
 }
 
+void EnggDiffractionPresenter::doRebinningTime(const std::string &runNo,
+                                               double bin,
+                                               const std::string &outWSName) {
+  // TODO:
+  // Load() then Rebin()
+
+  // TOOD: set m_rebinningFinishedOK;
+}
+
+void EnggDiffractionPresenter::inputChecksBeforeRebin(
+    const std::string &runNo) {
+  if (runNo.empty()) {
+    throw std::invalid_argument("The run to pre-process cannot be empty");
+  }
+}
+
+void EnggDiffractionPresenter::inputChecksBeforeRebinTime(
+    const std::string &runNo, double bin) {
+  inputChecksBeforeRebin(runNo);
+
+  if (bin <= 0) {
+    throw std::invalid_argument("The bin width must be strictly positive");
+  }
+}
+
+/**
+ * Starts the Rebin algorithm(s) without blocking the GUI. This is
+ * based on Qt connect / signals-slots so that it goes in sync with
+ * the Qt event loop. For that reason this class needs to be a
+ * Q_OBJECT.
+ *
+ * @param runNo run number(s)
+ * @param bin bin width parameter for Rebin
+ * @param outWSName name for the output workspace produced here
+ */
+void EnggDiffractionPresenter::startAsyncRebinningTimeWorker(
+    const std::string &runNo, double bin, const std::string &outWSName) {
+
+  delete m_workerThread;
+  m_workerThread = new QThread(this);
+  EnggDiffWorker *worker = new EnggDiffWorker(this, runNo, bin, outWSName);
+  worker->moveToThread(m_workerThread);
+
+  connect(m_workerThread, SIGNAL(started()), worker, SLOT(rebinTime()));
+  connect(worker, SIGNAL(finished()), this, SLOT(rebinningFinished()));
+  // early delete of thread and worker
+  connect(m_workerThread, SIGNAL(finished()), m_workerThread,
+          SLOT(deleteLater()), Qt::DirectConnection);
+  connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
+  m_workerThread->start();
+}
+
+void EnggDiffractionPresenter::inputChecksBeforeRebinPulses(
+    const std::string &runNo, size_t nperiods, double timeStep) {
+  inputChecksBeforeRebin(runNo);
+
+  if (0 == nperiods) {
+    throw std::invalid_argument("The number of periods has been set to 0 so "
+                                "none of the periods will be processed");
+  }
+
+  if (timeStep <= 0) {
+    throw std::invalid_argument(
+        "The bin or step for the time axis must be strictly positive");
+  }
+}
+
+void EnggDiffractionPresenter::doRebinningPulses(const std::string &runNo,
+                                                 size_t nperiods, double bin,
+                                                 const std::string &outWSName) {
+  // TODO: rebin
+  // run a command similar to this:
+  // ws.isMultiPeriod()
+  // True
+  // ws = mtd['nxs_ENGINX00197019']
+  // ws1 = ws.getItem(0)
+  // start=wsrun.startTime()
+  // end=wsrun.endTime()
+  // get seconds from: end-start
+  //
+  // rbpt=RebinByPulseTimes(InputWorkspace='ws', Params=[0, step_on_time_axis,
+  // *end-start*])
+
+  // TOOD: set m_rebinningFinishedOK;
+}
+
+/**
+ * Starts the Rebin (by pulses) algorithm(s) without blocking the
+ * GUI. This is based on Qt connect / signals-slots so that it goes in
+ * sync with the Qt event loop. For that reason this class needs to be
+ * a Q_OBJECT.
+ *
+ * @param runNo run number(s)
+ * @param nperiods max number of periods to process
+ * @param timeStep bin width parameter for the x (time) axis
+ * @param outWSName name for the output workspace produced here
+ */
+void EnggDiffractionPresenter::startAsyncRebinningPulsesWorker(
+    const std::string &runNo, size_t nperiods, double timeStep,
+    const std::string &outWSName) {
+
+  delete m_workerThread;
+  m_workerThread = new QThread(this);
+  EnggDiffWorker *worker =
+      new EnggDiffWorker(this, runNo, nperiods, timeStep, outWSName);
+  worker->moveToThread(m_workerThread);
+
+  connect(m_workerThread, SIGNAL(started()), worker, SLOT(rebinPulses()));
+  connect(worker, SIGNAL(finished()), this, SLOT(rebinningFinished()));
+  // early delete of thread and worker
+  connect(m_workerThread, SIGNAL(finished()), m_workerThread,
+          SLOT(deleteLater()), Qt::DirectConnection);
+  connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
+  m_workerThread->start();
+}
+
+/**
+ * Method (Qt slot) to call when the rebin work has finished,
+ * possibly from a separate thread but sometimes not (as in this
+ * presenter class' test).
+ */
+void EnggDiffractionPresenter::rebinningFinished() {
+  if (!m_view)
+    return;
+
+  m_view->enableCalibrateAndFocusActions(true);
+  if (!m_focusFinishedOK) {
+    g_log.warning()
+        << "The pre-processing (re-binning) did not finished correctly."
+        << std::endl;
+  } else {
+    g_log.notice() << "Pre-processing (re-binning) finished - the output "
+                      "workspace is ready." << std::endl;
+  }
+  if (m_workerThread) {
+    delete m_workerThread;
+    m_workerThread = NULL;
+  }
+}
+
 /**
  * Checks the plot type selected and applies the appropriate
  * python function to apply during first bank and second bank
diff --git a/MantidQt/CustomInterfaces/src/EnggDiffraction/EnggDiffractionViewQtGUI.cpp b/MantidQt/CustomInterfaces/src/EnggDiffraction/EnggDiffractionViewQtGUI.cpp
index 2053252498d..040d8c1e001 100644
--- a/MantidQt/CustomInterfaces/src/EnggDiffraction/EnggDiffractionViewQtGUI.cpp
+++ b/MantidQt/CustomInterfaces/src/EnggDiffraction/EnggDiffractionViewQtGUI.cpp
@@ -451,6 +451,11 @@ void EnggDiffractionViewQtGUI::enableCalibrateAndFocusActions(bool enable) {
   m_uiTabFocus.pushButton_focus->setEnabled(enable);
   m_uiTabFocus.pushButton_focus_cropped->setEnabled(enable);
   m_uiTabFocus.pushButton_focus_texture->setEnabled(enable);
+
+  // pre-processing
+  m_uiTabPreproc.MWRunFiles_preproc_run_num->setEnabled(enable);
+  m_uiTabPreproc.pushButton_rebin_time->setEnabled(enable);
+  m_uiTabPreproc.pushButton_rebin_multiperiod->setEnabled(enable);
 }
 
 void EnggDiffractionViewQtGUI::enableTabs(bool enable) {
@@ -467,12 +472,12 @@ double EnggDiffractionViewQtGUI::rebinningTimeBin() const {
   return m_uiTabPreproc.doubleSpinBox_time_bin->value();
 }
 
-size_t EnggDiffractionViewQtGUI::rebinningNumberPeriods() const {
+size_t EnggDiffractionViewQtGUI::rebinningPulsesNumberPeriods() const {
   return m_uiTabPreproc.spinBox_nperiods->value();
 }
 
-size_t EnggDiffractionViewQtGUI::rebinningPulsesPerPeriod() const {
-  return m_uiTabPreproc.spinBox_pulses_per_period->value();
+double EnggDiffractionViewQtGUI::rebinningPulsesTime() const {
+  return m_uiTabPreproc.doubleSpinBox_step_time->value();
 }
 
 void EnggDiffractionViewQtGUI::plotFocusedSpectrum(const std::string &wsName) {
diff --git a/MantidQt/CustomInterfaces/test/EnggDiffractionPresenterTest.h b/MantidQt/CustomInterfaces/test/EnggDiffractionPresenterTest.h
index 34581c7d421..2911c1ce1b2 100644
--- a/MantidQt/CustomInterfaces/test/EnggDiffractionPresenterTest.h
+++ b/MantidQt/CustomInterfaces/test/EnggDiffractionPresenterTest.h
@@ -685,8 +685,8 @@ public:
 
     // inputs from user
     EXPECT_CALL(mockView, currentPreprocRunNo()).Times(1).WillOnce(Return(""));
-    EXPECT_CALL(mockView, rebinningNumberPeriods()).Times(1).WillOnce(Return(0));
-    EXPECT_CALL(mockView, rebinningPulsesPerPeriod()).Times(1).WillOnce(Return(0));
+    EXPECT_CALL(mockView, rebinningPulsesNumberPeriods()).Times(1).WillOnce(Return(0));
+    EXPECT_CALL(mockView, rebinningPulsesTime()).Times(1).WillOnce(Return(0));
 
     // No errors/warnings
     EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(0);
@@ -694,6 +694,7 @@ public:
 
     pres.notify(IEnggDiffractionPresenter::RebinMultiperiod);
   }
+
   void test_logMsg() {
     testing::NiceMock<MockEnggDiffractionView> mockView;
     MantidQt::CustomInterfaces::EnggDiffractionPresenter pres(&mockView);
diff --git a/MantidQt/CustomInterfaces/test/EnggDiffractionViewMock.h b/MantidQt/CustomInterfaces/test/EnggDiffractionViewMock.h
index 03fc97a7c8d..c83d0fc8d2d 100644
--- a/MantidQt/CustomInterfaces/test/EnggDiffractionViewMock.h
+++ b/MantidQt/CustomInterfaces/test/EnggDiffractionViewMock.h
@@ -111,10 +111,10 @@ public:
   MOCK_CONST_METHOD0(rebinningTimeBin, double());
 
   // virtual size_t rebinningNumberPeriods() const;
-  MOCK_CONST_METHOD0(rebinningNumberPeriods, size_t());
+  MOCK_CONST_METHOD0(rebinningPulsesNumberPeriods, size_t());
 
-  // virtual size_t rebinningPulsesPerPeriod() const;
-  MOCK_CONST_METHOD0(rebinningPulsesPerPeriod, size_t());
+  // virtual double rebinningPulsesPerPeriod() const;
+  MOCK_CONST_METHOD0(rebinningPulsesTime, double());
 
   // virtual bool focusedOutWorkspace() const;
   MOCK_CONST_METHOD0(focusedOutWorkspace, bool());
diff --git a/docs/source/interfaces/Engineering_Diffraction.rst b/docs/source/interfaces/Engineering_Diffraction.rst
index 10c7cd263bf..0e8aeedf843 100644
--- a/docs/source/interfaces/Engineering_Diffraction.rst
+++ b/docs/source/interfaces/Engineering_Diffraction.rst
@@ -8,9 +8,10 @@ Overview
 --------
 
 This custom interface integrates several tasks related to engineeering
-diffraction. It provides calibration and focusing functionality which
-can be expected to expand for next releases as it is under active
-development. The following sections describe the different tabs or
+diffraction. It provides functionality for calibration, focusing, and
+pre-processing of event mode data. Further extensions can be expected
+for next releases as it is under active development. Feedback is very
+much welcome. The following sections describe the different tabs or
 functionality areas of the interface.
 
 .. interface:: Engineering Diffraction
@@ -62,8 +63,8 @@ the details on how the input runs are focused.
 The interface will also create workspaces that can be inspected in the
 workspaces window:
 
-1. The *engg_focusing_input_ws workspace* for the data being focused
-2. The *engg_focusing_output_ws... workspace* for the corresponding
+1. The *engggui_focusing_input_ws workspace* for the data being focused
+2. The *engggui_focusing_output_ws... workspace* for the corresponding
    focused data (where the ... denotes a suffix explained below).
 
 Three focusing alternatives are provided:
@@ -117,6 +118,46 @@ in Mantid. These files can be found with appropriate name at location:
 C:\EnginX_Mantid\User\236516\Focus on Windows, the
 EnginX_Mantid folder can be found on Desktop/Home on other platforms.
 
+Pre-processing
+--------------
+
+.. warning:: This is a new capability that is currently in a very
+             early stage of definition and implementation. Not all
+             options may be supported and/or consistent at the moment.
+
+The focusing options can be applied directly to histogram data. For
+event mode experiments, the event data (which would be loaded as event
+workspaces in Mantid) need to be pre-processed.
+
+The simplest pre-processing option is "regular time binning" which
+will produce a histogram data workspace (as a :ref:`Workspace2D
+<Workspace2D>`). The only parameter required is the bin width. The
+workspace will be named with the following convention:
+
+- *engggui_preproc_time_ws*
+
+When the input run file contains multiple workspaces (it would be
+loaded by :ref:`Load <algm-Load>` as multiple :ref:`EventWorkspace
+<EventWorkspace>` workspaces) the output workspace will be a group
+with the corresponding number of histogram workspaces, binned
+separately. This is the case when the input run file comes from a
+multi-period experiment. Note that the time bin can be a multiple of
+the pulse time.
+
+A different way of pre-processing event data is by rebinning
+multi-period data by pulse times. In this case the input required is
+the time step for the binning (the x axis of the output will be time
+instead of time-of-flight). It is also possible to specify the number
+of periods that will be processed (starting from the first one). This
+type of pre-processing produces workspaces with the following naming
+convention:
+
+- *engggui_preproc_by_pulse_time_ws*
+
+This tab uses the algorithms :ref:`Rebin <algm-Rebin>` and :ref:`Rebin
+<algm-RebinByPulseTimes>` to bin the data in different ways when
+converting event data into histogram data.
+
 Settings
 --------
 
-- 
GitLab