From 172f07be616d985451f3fe9ed47d878112e47bd7 Mon Sep 17 00:00:00 2001
From: Alex Buts <Alex.Buts@stfc.ac.uk>
Date: Tue, 26 Jun 2012 15:35:33 +0100
Subject: [PATCH] refs #5244 further modifications to allow ConvToMD running
 multithread

refs #5537 Renamed couple of classes responsible for event conversion
---
 .../API/inc/MantidAPI/BoxController.h         |  16 +-
 Code/Mantid/Framework/Kernel/CMakeLists.txt   |   3 +
 .../Kernel/inc/MantidKernel/FunctionTask.h    |   5 +-
 .../MantidMDAlgorithms/ConvertToMDEvents.h    |   8 +-
 .../MDAlgorithms/src/ConvertToMDEvents.cpp    |   3 -
 Code/Mantid/Framework/MDEvents/CMakeLists.txt |   8 +-
 .../{ConvToMDEventsBase.h => ConvToMDBase.h}  |   6 +-
 .../MantidMDEvents/ConvToMDEventsSelector.h   |   2 +-
 .../inc/MantidMDEvents/ConvToMDEventsWS.h     |  74 ++++++++
 .../inc/MantidMDEvents/ConvToMDPreprocDet.h   |   9 +-
 .../MantidMDEvents/UnitsConversionHelper.h    |   3 +-
 ...onvToMDEventsBase.cpp => ConvToMDBase.cpp} |  11 +-
 .../MDEvents/src/ConvToMDEventsEvents.cpp     |  93 ----------
 .../MDEvents/src/ConvToMDEventsHisto.cpp      |  10 +-
 .../MDEvents/src/ConvToMDEventsSelector.cpp   |  14 +-
 .../MDEvents/src/ConvToMDEventsWS.cpp         | 162 ++++++++++++++++++
 .../MDEvents/src/ConvToMDPreprocDet.cpp       |  30 ----
 .../src/ConvertToDiffractionMDWorkspace.cpp   |  10 +-
 .../MDEvents/src/MDEventWSWrapper.cpp         |   2 +-
 .../MDEvents/src/UnitsConversionHelper.cpp    |  20 ++-
 .../test/ConvertToMDEventsParamsTest.h        |  35 +---
 21 files changed, 309 insertions(+), 215 deletions(-)
 rename Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/{ConvToMDEventsBase.h => ConvToMDBase.h} (97%)
 create mode 100644 Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/ConvToMDEventsWS.h
 rename Code/Mantid/Framework/MDEvents/src/{ConvToMDEventsBase.cpp => ConvToMDBase.cpp} (77%)
 delete mode 100644 Code/Mantid/Framework/MDEvents/src/ConvToMDEventsEvents.cpp
 create mode 100644 Code/Mantid/Framework/MDEvents/src/ConvToMDEventsWS.cpp

diff --git a/Code/Mantid/Framework/API/inc/MantidAPI/BoxController.h b/Code/Mantid/Framework/API/inc/MantidAPI/BoxController.h
index 1636da8d049..be33cc72273 100644
--- a/Code/Mantid/Framework/API/inc/MantidAPI/BoxController.h
+++ b/Code/Mantid/Framework/API/inc/MantidAPI/BoxController.h
@@ -241,15 +241,25 @@ namespace API
      * would be a slow-down, but keeping the boxes split at an earlier stage
      * should help scalability for later adding, so there is a balance to get.
      *
-     * @param eventsAdded :: How many events were added since the last split?
-     * @param numMDBoxes :: How many un-split MDBoxes are there (total) in the workspace
+     * @param nEventsInOutput :: How many events are currently in workspace in memory;
+     * @param eventsAdded     :: How many events were added since the last split?
+     * @param numMDBoxes      :: How many un-split MDBoxes are there (total) in the workspace
      * @return true if the boxes should get split.
      */
-    bool shouldSplitBoxes(size_t eventsAdded, size_t numMDBoxes) const
+    bool shouldSplitBoxes(size_t nEventsInOutput,size_t eventsAdded, size_t numMDBoxes) const
     {
       // Avoid divide by zero
       if(numMDBoxes == 0)
         return false;
+     // Performance depends pretty strongly on WHEN you split the boxes.
+      // This is an empirically-determined way to optimize the splitting calls.
+      // Split when adding 1/16^th as many events as are already in the output,
+      //  (because when the workspace gets very large you should split less often)
+      // But no more often than every 10 million events.
+      size_t comparisonPoint = nEventsInOutput/16;
+      if (comparisonPoint < 10000000)
+          comparisonPoint = 10000000;
+      if (eventsAdded > (comparisonPoint))return true;
 
       // Return true if the average # of events per box is big enough to split.
       return ((eventsAdded / numMDBoxes) > m_SplitThreshold);
diff --git a/Code/Mantid/Framework/Kernel/CMakeLists.txt b/Code/Mantid/Framework/Kernel/CMakeLists.txt
index dc79c8038d2..b7ca873bb5e 100644
--- a/Code/Mantid/Framework/Kernel/CMakeLists.txt
+++ b/Code/Mantid/Framework/Kernel/CMakeLists.txt
@@ -185,10 +185,13 @@ set ( INC_FILES
 	inc/MantidKernel/Strings.h
 	inc/MantidKernel/System.h
 	inc/MantidKernel/TestChannel.h
+	inc/MantidKernel/ThreadPool.h	
 	inc/MantidKernel/ThreadPoolRunnable.h
 	inc/MantidKernel/ThreadSafeLogStream.h
 	inc/MantidKernel/ThreadScheduler.h
 	inc/MantidKernel/ThreadSchedulerMutexes.h
+	inc/MantidKernel/Task.h 
+	inc/MantidKernel/FunctionTask.h 
 	inc/MantidKernel/TimeSeriesProperty.h
 	inc/MantidKernel/TimeSplitter.h
 	inc/MantidKernel/Timer.h
diff --git a/Code/Mantid/Framework/Kernel/inc/MantidKernel/FunctionTask.h b/Code/Mantid/Framework/Kernel/inc/MantidKernel/FunctionTask.h
index 164eee61c18..62038dcac44 100644
--- a/Code/Mantid/Framework/Kernel/inc/MantidKernel/FunctionTask.h
+++ b/Code/Mantid/Framework/Kernel/inc/MantidKernel/FunctionTask.h
@@ -27,6 +27,8 @@ public:
 
   /// Typedef for a function with no arguments and no return
   typedef void(*voidFunction)();
+  /// Typedef for a function with no arguments and size_t return
+  typedef size_t(*sizetFunction)();
 
   //---------------------------------------------------------------------------------------------
   /** Constructor for a simple void function.
@@ -40,7 +42,7 @@ public:
    * @param cost :: computational cost
    */
   FunctionTask(voidFunction func, double cost=1.0)
-    : Task(cost), m_voidFunc(func)
+    : Task(cost), m_voidFunc(func),m_sizetFunc(NULL)
   {
   }
 
@@ -74,6 +76,7 @@ public:
 
 protected:
   boost::function<void ()> m_voidFunc;
+  boost::function<size_t ()> m_sizetFunc;
 };
 
 
diff --git a/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/ConvertToMDEvents.h b/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/ConvertToMDEvents.h
index 22b6f7b31fb..13269aac092 100644
--- a/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/ConvertToMDEvents.h
+++ b/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/ConvertToMDEvents.h
@@ -75,13 +75,7 @@ namespace MDAlgorithms
     /// logger -> to provide logging, for MD dataset file operations
    static Mantid::Kernel::Logger& convert_log;
    /// pointer to the class, which does the particular conversion
-   boost::shared_ptr<MDEvents::ConvToMDEventsBase> pConvertor;
-  
-   /// the class which knows about existing subalgorithms and generates alforithm ID as function of input parameters of this algorithm. 
-    ///ConvertToMD::ConvertToMDEventsParams ParamParser;   
-    /// The class which keeps map of all existing subalgorithms converting to MDEventWorkspace.
-    /// It returns the pointer to the subalgorithm receiving alogID from ParamParser. Shoud be re-implemented through a singleton if used not only here. 
-    //ConvertToMDEventsSubalgFactory  subAlgFactory;
+   boost::shared_ptr<MDEvents::ConvToMDEventsBase> pConvertor; 
   //------------------------------------------------------------------------------------------------------------------------------------------
     protected: //for testing
         static Mantid::Kernel::Logger & getLogger();
diff --git a/Code/Mantid/Framework/MDAlgorithms/src/ConvertToMDEvents.cpp b/Code/Mantid/Framework/MDAlgorithms/src/ConvertToMDEvents.cpp
index a653b676713..31bc521a83e 100644
--- a/Code/Mantid/Framework/MDAlgorithms/src/ConvertToMDEvents.cpp
+++ b/Code/Mantid/Framework/MDAlgorithms/src/ConvertToMDEvents.cpp
@@ -185,9 +185,6 @@ ConvertToMDEvents::init()
 /* Execute the algorithm.   */
 void ConvertToMDEvents::exec()
 {
-    // initiate all availible subalgorithms for further usage (it will do it only once, first time the algorithm is executed);
-   // this->subAlgFactory.init(ParamParser);
-
   // initiate class which would deal with any dimension workspaces, handling 
   if(!pWSWrapper.get()){
     pWSWrapper = boost::shared_ptr<MDEvents::MDEventWSWrapper>(new MDEvents::MDEventWSWrapper());
diff --git a/Code/Mantid/Framework/MDEvents/CMakeLists.txt b/Code/Mantid/Framework/MDEvents/CMakeLists.txt
index 4e76b3f2820..2d045ca8bd4 100644
--- a/Code/Mantid/Framework/MDEvents/CMakeLists.txt
+++ b/Code/Mantid/Framework/MDEvents/CMakeLists.txt
@@ -8,8 +8,8 @@ set ( SRC_FILES
 	src/BoxControllerSettingsAlgorithm.cpp
 	src/CentroidPeaksMD.cpp
 	src/CloneMDWorkspace.cpp
-	src/ConvToMDEventsBase.cpp
-	src/ConvToMDEventsEvents.cpp
+	src/ConvToMDBase.cpp
+	src/ConvToMDEventsWS.cpp
 	src/ConvToMDEventsHisto.cpp
 	src/ConvToMDEventsSelector.cpp
 	src/ConvToMDPreprocDet.cpp
@@ -78,8 +78,8 @@ set ( INC_FILES
 	inc/MantidMDEvents/BoxControllerSettingsAlgorithm.h
 	inc/MantidMDEvents/CentroidPeaksMD.h
 	inc/MantidMDEvents/CloneMDWorkspace.h
-	inc/MantidMDEvents/ConvToMDEventsBase.h
-	inc/MantidMDEvents/ConvToMDEventsEvents.h
+	inc/MantidMDEvents/ConvToMDBase.h
+	inc/MantidMDEvents/ConvToMDEventsWS.h
 	inc/MantidMDEvents/ConvToMDEventsHisto.h
 	inc/MantidMDEvents/ConvToMDEventsSelector.h
 	inc/MantidMDEvents/ConvToMDPreprocDet.h
diff --git a/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/ConvToMDEventsBase.h b/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/ConvToMDBase.h
similarity index 97%
rename from Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/ConvToMDEventsBase.h
rename to Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/ConvToMDBase.h
index 44875836109..cf597e375f0 100644
--- a/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/ConvToMDEventsBase.h
+++ b/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/ConvToMDBase.h
@@ -50,18 +50,18 @@ namespace MDEvents
         Code Documentation is available at: <http://doxygen.mantidproject.org>
 */
 
- class DLLExport ConvToMDEventsBase
+ class DLLExport ConvToMDBase
  {
  public:
      // constructor;
-     ConvToMDEventsBase();
+     ConvToMDBase();
  
     ///method which initates all main class variables 
     virtual size_t initialize(const MDWSDescription &WSD, boost::shared_ptr<MDEventWSWrapper> inWSWrapper);
     /// method which starts the conversion procedure
     virtual void runConversion(API::Progress *)=0;
     /// virtual destructor
-    virtual ~ConvToMDEventsBase(){};
+    virtual ~ConvToMDBase(){};
 
  
   protected:
diff --git a/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/ConvToMDEventsSelector.h b/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/ConvToMDEventsSelector.h
index f99b23c0f77..d940bf7b0d9 100644
--- a/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/ConvToMDEventsSelector.h
+++ b/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/ConvToMDEventsSelector.h
@@ -2,7 +2,7 @@
 #define H_CONV_TOMDEVENTS_SELECTOR
 
 
-#include "MantidMDEvents/ConvToMDEventsEvents.h"
+#include "MantidMDEvents/ConvToMDEventsWS.h"
 #include "MantidMDEvents/ConvToMDEventsHisto.h"
 
 namespace Mantid
diff --git a/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/ConvToMDEventsWS.h b/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/ConvToMDEventsWS.h
new file mode 100644
index 00000000000..19d9ab3e4bf
--- /dev/null
+++ b/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/ConvToMDEventsWS.h
@@ -0,0 +1,74 @@
+#ifndef H_CONVERT_TO_MD_EVENTWS
+#define H_CONVERT_TO_MD_EVENTWS
+//
+#include "MantidKernel/System.h"
+#include "MantidKernel/Exception.h"
+#include "MantidAPI/Algorithm.h" 
+#include <vector>
+
+#include "MantidDataObjects/EventWorkspace.h"
+
+#include "MantidAPI/NumericAxis.h"
+#include "MantidAPI/Progress.h"
+#include "MantidKernel/PhysicalConstants.h"
+
+#include "MantidMDEvents/MDEventWSWrapper.h"
+#include "MantidMDEvents/MDEvent.h"
+
+#include "MantidMDEvents/ConvToMDPreprocDet.h"
+#include "MantidMDEvents/ConvToMDBase.h"
+// coordinate transformation
+#include "MantidMDEvents/MDTransfFactory.h"
+
+namespace Mantid
+{
+namespace MDEvents
+{
+/** The class specializes ConvToMDEventsBase for the case when the conversion occurs from Events WS to the MD events WS
+   *
+   * @date 11-10-2011
+
+    Copyright &copy; 2010 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory
+
+        This file is part of Mantid.
+
+        Mantid is free software; you can redistribute it and/or modify
+        it under the terms of the GNU General Public License as published by
+        the Free Software Foundation; either version 3 of the License, or
+        (at your option) any later version.
+
+        Mantid is distributed in the hope that it will be useful,
+        but WITHOUT ANY WARRANTY; without even the implied warranty of
+        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+        GNU General Public License for more details.
+
+        You should have received a copy of the GNU General Public License
+        along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+        File/ change history is stored at: <https://svn.mantidproject.org/mantid/trunk/Code/Mantid>
+        Code Documentation is available at: <http://doxygen.mantidproject.org>
+*/
+
+// Class to process event workspace by direct conversion:
+
+class ConvToMDEventsWS: public ConvToMDBase
+{
+ public:
+    size_t  initialize(const MDEvents::MDWSDescription &WSD, boost::shared_ptr<MDEvents::MDEventWSWrapper> inWSWrapper);
+    void runConversion(API::Progress *pProg);
+
+private:
+   // function runs the conversion on 
+   virtual size_t conversionChunk(size_t workspaceIndex);
+   // the pointer to the source event workspace as event ws does not work through the public Matrix WS interface
+    DataObjects::EventWorkspace_const_sptr pEventWS;
+
+   /**function converts particular type of events into MD space and add these events to the workspace itself    */
+   template <class T>   size_t convertEventList(size_t workspaceIndex);
+
+};
+
+} // endNamespace MDEvents
+} // endNamespace Mantid
+
+#endif
diff --git a/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/ConvToMDPreprocDet.h b/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/ConvToMDPreprocDet.h
index 533a5098662..97cbe313697 100644
--- a/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/ConvToMDPreprocDet.h
+++ b/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/ConvToMDPreprocDet.h
@@ -115,14 +115,7 @@ private:
     // function allocates the class detectors memory 
     void allocDetMemory(size_t nSpectra);
 
-    //void setEi(const API::MatrixWorkspace_sptr inputWS);
-
-
-   // parameter which describes the conversion mode, used to convert uints using TOF and detector's positions
-  //    int emode;
-    // parameter wjocj describes the energy used to convert uints using TOF and detector's positions
-  //  double efix;
-    // source-sample distance  used to convert uints using TOF and detector's positions
+      // source-sample distance  used to convert uints using TOF and detector's positions
     double L1; 
     // minimal position for the detectors
     Kernel::V3D   minDetPosition;    
diff --git a/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/UnitsConversionHelper.h b/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/UnitsConversionHelper.h
index 0ed70fb10a5..aacd2877652 100644
--- a/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/UnitsConversionHelper.h
+++ b/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/UnitsConversionHelper.h
@@ -73,7 +73,8 @@ public:
     void initialize(const MDWSDescription &TWSD,const std::string &units_to);
     void updateConversion(size_t i);
     double convertUnits(double val);
-
+    // copy constructor
+    UnitsConversionHelper(const UnitsConversionHelper &another);
 protected: // for testing
     /// establish and initialize proper units conversion from input to output units;
     ConvertToMD::ConvertUnits analyzeUnitsConversion(const std::string &UnitsFrom,const std::string &UnitsTo);
diff --git a/Code/Mantid/Framework/MDEvents/src/ConvToMDEventsBase.cpp b/Code/Mantid/Framework/MDEvents/src/ConvToMDBase.cpp
similarity index 77%
rename from Code/Mantid/Framework/MDEvents/src/ConvToMDEventsBase.cpp
rename to Code/Mantid/Framework/MDEvents/src/ConvToMDBase.cpp
index a75bbcc55aa..dbb65ed051d 100644
--- a/Code/Mantid/Framework/MDEvents/src/ConvToMDEventsBase.cpp
+++ b/Code/Mantid/Framework/MDEvents/src/ConvToMDBase.cpp
@@ -1,4 +1,4 @@
-#include "MantidMDEvents/ConvToMDEventsBase.h"
+#include "MantidMDEvents/ConvToMDBase.h"
 
 
 namespace Mantid
@@ -7,18 +7,16 @@ namespace MDEvents
 {
 
 // logger for conversion  
-   Kernel::Logger& ConvToMDEventsBase::convert_log =Kernel::Logger::get("MD-Algorithms");
+   Kernel::Logger& ConvToMDBase::convert_log =Kernel::Logger::get("MD-Algorithms");
 
 
 /** method which initates all main class variables
-  * @param pWS2D      -- shared pointer to input matirx workspace to process
-  * @param detLoc     -- class with information about datecotrs, partially transformed for convenient Q calculations
   * @param WSD        -- class describing the target workspace. 
   *                      the algorithm uses target workspace limints, transformation matix from source to the target workspace and the parameters, needed for  
   *                      unit conversion (if any) 
   * @param pWSWrapper -- shared pointer to target MD Event workspace to add converted events to.
 */
-size_t  ConvToMDEventsBase::initialize(const MDEvents::MDWSDescription &WSD, boost::shared_ptr<MDEvents::MDEventWSWrapper> inWSWrapper)
+size_t  ConvToMDBase::initialize(const MDEvents::MDWSDescription &WSD, boost::shared_ptr<MDEvents::MDEventWSWrapper> inWSWrapper)
 {
         pDetLoc = WSD.getDetectors();
         inWS2D  = WSD.getInWS();
@@ -49,7 +47,8 @@ size_t  ConvToMDEventsBase::initialize(const MDEvents::MDWSDescription &WSD, boo
         return n_spectra;
 };  
 
-ConvToMDEventsBase::ConvToMDEventsBase()
+/** empty default constructor */
+ConvToMDBase::ConvToMDBase()
 {}
 
 
diff --git a/Code/Mantid/Framework/MDEvents/src/ConvToMDEventsEvents.cpp b/Code/Mantid/Framework/MDEvents/src/ConvToMDEventsEvents.cpp
deleted file mode 100644
index 537ed67a4dc..00000000000
--- a/Code/Mantid/Framework/MDEvents/src/ConvToMDEventsEvents.cpp
+++ /dev/null
@@ -1,93 +0,0 @@
-#include "MantidMDEvents/ConvToMDEventsEvents.h"
-//
-
-namespace Mantid
-{
-namespace MDEvents
-{
-
-
-size_t  ConvToMDEventsEvents::initialize(const MDEvents::MDWSDescription &WSD, boost::shared_ptr<MDEvents::MDEventWSWrapper> inWSWrapper)
-{
-    size_t numSpec=ConvToMDEventsBase::initialize(WSD,inWSWrapper);
-
-    
-    pEventWS  = boost::dynamic_pointer_cast<const DataObjects::EventWorkspace>(inWS2D);
-    if(!pEventWS.get()){
-           throw(std::logic_error(" ConvertToMDEvensEventWS should work with defined event workspace"));
-    }
- 
-    return numSpec;
-}
-
-void ConvToMDEventsEvents::runConversion(API::Progress *pProg)
-{
-       // Get the box controller
-        Mantid::API::BoxController_sptr bc = pWSWrapper->pWorkspace()->getBoxController();
-        size_t lastNumBoxes = bc->getTotalNumMDBoxes();
-        
-        // preprocessed detectors insure that each detector has its own spectra
-        size_t nValidSpectra  = this->pDetLoc->nDetectors();
-
-       // if any property dimension is outside of the data range requested, the job is done;
-        if(!pQConverter->calcGenericVariables(Coord,this->n_dims))return; 
-       
-        size_t eventsAdded  = 0;
-        for (size_t wi=0; wi <nValidSpectra; wi++)
-        {     
-           size_t iSpec         = this->pDetLoc->getDetSpectra(wi);       
-           UnitConversion.updateConversion(wi);
-
-           eventsAdded         += this->conversionChunk(iSpec);
-      // Give this task to the scheduler
-         //%double cost = double(el.getNumberEvents());
-         //ts->push( new FunctionTask( func, cost) );
-
-          // Keep a running total of how many events we've added
-           if (bc->shouldSplitBoxes(eventsAdded, lastNumBoxes)){
-            // Do all the adding tasks
-            //   tp.joinAll();    
-            // Now do all the splitting tasks
-              //ws->splitAllIfNeeded(ts);
-               pWSWrapper->pWorkspace()->splitAllIfNeeded(NULL);
-             //if (ts->size() > 0)       tp.joinAll();
-
-            // Count the new # of boxes.
-              lastNumBoxes = pWSWrapper->pWorkspace()->getBoxController()->getTotalNumMDBoxes();
-              pProg->report(wi);
-           }
-   
-       }
-    //tp.joinAll();
-    // Do a final splitting of everything
-    //ws->splitAllIfNeeded(ts);
-    //tp.joinAll();
-    pWSWrapper->pWorkspace()->splitAllIfNeeded(NULL);
-    // Recount totals at the end.
-    pWSWrapper->pWorkspace()->refreshCache(); 
-    pWSWrapper->refreshCentroid();
-    pProg->report();
-}
-
-//
-size_t ConvToMDEventsEvents::conversionChunk(size_t workspaceIndex)
-{       
-
-       switch (this->pEventWS->getEventList(workspaceIndex).getEventType())
-        {
-        case Mantid::API::TOF:
-            return this->convertEventList<Mantid::DataObjects::TofEvent>(workspaceIndex);
-         case Mantid::API::WEIGHTED:
-          return  this->convertEventList<Mantid::DataObjects::WeightedEvent>(workspaceIndex);
-        case Mantid::API::WEIGHTED_NOTIME:
-          return this->convertEventList<Mantid::DataObjects::WeightedEventNoTime>(workspaceIndex);
-        default:
-           throw std::runtime_error("EventList had an unexpected data type!");
-        }
-}
-  
-
-} // endNamespace MDEvents
-} // endNamespace Mantid
-
-
diff --git a/Code/Mantid/Framework/MDEvents/src/ConvToMDEventsHisto.cpp b/Code/Mantid/Framework/MDEvents/src/ConvToMDEventsHisto.cpp
index cfb1a8a1d79..a12e878ec82 100644
--- a/Code/Mantid/Framework/MDEvents/src/ConvToMDEventsHisto.cpp
+++ b/Code/Mantid/Framework/MDEvents/src/ConvToMDEventsHisto.cpp
@@ -13,11 +13,15 @@ inline bool isNaN(T val){
     return (val!=buf);
 }
 
+/** method sets up all internal variables necessary to convert from Matrix2D workspace to MDEvent workspace 
+ @parameter WSD         -- the class describing the target MD workspace, sorurce matrtix workspace and the transformations, necessary to perform on these workspaces
+ @parameter inWSWrapper -- the class wrapping the target MD workspace
+*/
 size_t  ConvToMDEventsHisto::initialize(const MDEvents::MDWSDescription &WSD, boost::shared_ptr<MDEvents::MDEventWSWrapper> inWSWrapper)
 {
                         
    size_t numSpec=ConvToMDEventsBase::initialize(WSD,inWSWrapper);
-
+   // check if we indeed have matrix workspace as input.
    DataObjects::Workspace2D_const_sptr pWS2D  = boost::dynamic_pointer_cast<const DataObjects::Workspace2D>(inWS2D);
    if(!pWS2D.get()){
            throw(std::logic_error("ConvToMDEventsHisto should work with defined histrohram workspace"));
@@ -33,6 +37,7 @@ void ConvToMDEventsHisto::runConversion(API::Progress *pProg)
         //
         Mantid::API::BoxController_sptr bc = pWSWrapper->pWorkspace()->getBoxController();
         size_t lastNumBoxes                = bc->getTotalNumMDBoxes();
+        size_t nEventsInWS                 = pWSWrapper->pWorkspace()->getNPoints();
         //
 
         const size_t specSize = this->inWS2D->blocksize();    
@@ -100,11 +105,12 @@ void ConvToMDEventsHisto::runConversion(API::Progress *pProg)
                 if(n_buf_events>=buf_size){
                    pWSWrapper->addMDData(sig_err,run_index,det_ids,allCoord,n_buf_events);
                    n_added_events+=n_buf_events;
+                   nEventsInWS   +=n_buf_events;
 
                    // reset buffer counts
                    n_coordinates= 0;
                    n_buf_events = 0;
-                   if (bc->shouldSplitBoxes(n_added_events, lastNumBoxes)){
+                   if (bc->shouldSplitBoxes(nEventsInWS,n_added_events, lastNumBoxes)){
                         // Do all the adding tasks
                         //   tp.joinAll();    
                         // Now do all the splitting tasks
diff --git a/Code/Mantid/Framework/MDEvents/src/ConvToMDEventsSelector.cpp b/Code/Mantid/Framework/MDEvents/src/ConvToMDEventsSelector.cpp
index 740fdc74733..305882fa9bf 100644
--- a/Code/Mantid/Framework/MDEvents/src/ConvToMDEventsSelector.cpp
+++ b/Code/Mantid/Framework/MDEvents/src/ConvToMDEventsSelector.cpp
@@ -22,8 +22,8 @@ enum wsType
  {
     // identify what kind of workspace we expect to process
     wsType inputWSType(Undefined);
-    if(dynamic_cast<DataObjects::EventWorkspace *>(inputWS.get()))    inputWSType = EventWS;   
-    if(dynamic_cast<DataObjects::Workspace2D *>(inputWS.get())   )    inputWSType = Matrix2DWS;
+    if(boost::dynamic_pointer_cast<DataObjects::EventWorkspace>(inputWS)) inputWSType = EventWS;   
+    if(boost::dynamic_pointer_cast<DataObjects::Workspace2D>(inputWS)) inputWSType = Matrix2DWS;
     
     if(inputWSType == Undefined)
     {
@@ -35,8 +35,8 @@ enum wsType
      ConvToMDEventsBase *pSolver = currentSolver.get();
      if(pSolver)
      {
-         if(dynamic_cast<ConvToMDEventsEvents *>(pSolver))    wsConvType = EventWS;
-         if(dynamic_cast<ConvToMDEventsHisto  *>(pSolver))    wsConvType = Matrix2DWS;          
+         if(dynamic_cast<ConvToMDEventsEvents *>(pSolver)) wsConvType = EventWS;
+         if(dynamic_cast<ConvToMDEventsHisto  *>(pSolver)) wsConvType = Matrix2DWS;          
      }
 
      // select a converter, which corresponds to the workspace type
@@ -44,9 +44,9 @@ enum wsType
      {
          switch(inputWSType)
          {
-            case(EventWS):       return boost::shared_ptr<ConvToMDEventsBase>(new ConvToMDEventsEvents());
-            case(Matrix2DWS):    return boost::shared_ptr<ConvToMDEventsBase>(new ConvToMDEventsHisto());
-            default:             throw(std::logic_error("ConvToMDEventsSelector: requested converter for unknown ws type"));
+            case(EventWS):   return boost::shared_ptr<ConvToMDEventsBase>(new ConvToMDEventsEvents());
+            case(Matrix2DWS): return boost::shared_ptr<ConvToMDEventsBase>(new ConvToMDEventsHisto());
+            default:  throw(std::logic_error("ConvToMDEventsSelector: requested converter for unknown ws type"));
          }
 
      }else{ // existing converter is suitable for the workspace
diff --git a/Code/Mantid/Framework/MDEvents/src/ConvToMDEventsWS.cpp b/Code/Mantid/Framework/MDEvents/src/ConvToMDEventsWS.cpp
new file mode 100644
index 00000000000..8fd92b0fb36
--- /dev/null
+++ b/Code/Mantid/Framework/MDEvents/src/ConvToMDEventsWS.cpp
@@ -0,0 +1,162 @@
+#include "MantidMDEvents/ConvToMDEventsEvents.h"
+//
+
+namespace Mantid
+{
+namespace MDEvents
+{
+/**function converts particular list of events type T into MD space and adds these events to the workspace itself   */
+template <class T>
+size_t ConvToMDEventsEvents::convertEventList(size_t workspaceIndex)
+{
+
+         const Mantid::DataObjects::EventList & el = this->pEventWS->getEventList(workspaceIndex);
+         size_t iSpec                              = this->pDetLoc->getDetSpectra(workspaceIndex);   
+         // create local unit conversion class
+         UnitConversionHelper localUnitConv(UnitConversion);
+
+         size_t numEvents     = el.getNumberEvents();    
+         size_t  detNum       = this->pDetLoc->getWSDet(workspaceIndex);
+         uint32_t detID       = this->pDetLoc->getDetID(detNum);
+         uint16_t runIndexLoc = this->runIndex;
+
+         std::vector<coord_t>locCoord(this->Coord);
+         // set up unit conversion and calculate up all coordinates, which depend on spectra index only
+        if(!pQConverter->calcYDepCoordinates(locCoord,detNum))return 0;   // skip if any y outsize of the range of interest;
+        localUnitConv.updateConversion(detNum);
+//
+        // allocate temporary buffers for MD Events data
+         // MD events coordinates buffer
+         std::vector<coord_t>  allCoord;
+         std::vector<float>    sig_err;       // array for signal and error. 
+         std::vector<uint16_t> run_index;       // Buffer run index for each event 
+         std::vector<uint32_t> det_ids;         // Buffer of det Id-s for each event
+
+         allCoord.reserve(this->n_dims*numEvents);     sig_err.reserve(2*numEvents);
+         run_index.reserve(numEvents);                 det_ids.reserve(numEvents);
+    
+      // This little dance makes the getting vector of events more general (since you can't overload by return type).
+        typename std::vector<T>const * events_ptr;
+        getEventsFrom(el, events_ptr);
+        const typename std::vector<T> & events = *events_ptr;
+
+
+
+        // Iterators to start/end
+       typename std::vector<T>::const_iterator it = events.begin();
+       typename std::vector<T>::const_iterator it_end = events.end();
+     
+    
+       it = events.begin();
+       for (; it != it_end; it++)
+       {
+         double val=localUnitConv.convertUnits(it->tof());         
+         if(!pQConverter->calcMatrixCoord(val,locCoord))continue; // skip ND outside the range
+
+
+         sig_err.push_back(float(it->weight()));
+         sig_err.push_back(float(it->errorSquared()));
+         run_index.push_back(runIndexLoc);
+         det_ids.push_back(detID);
+         allCoord.insert(allCoord.end(),locCoord.begin(),locCoord.end());
+       }
+
+      // Add them to the MDEW
+       size_t n_added_events = run_index.size();
+       pWSWrapper->addMDData(sig_err,run_index,det_ids,allCoord,n_added_events);
+       return n_added_events;
+}
+
+
+/** method sets up all internal variables necessary to convert from Event Workspace to MDEvent workspace 
+ @parameter WSD         -- the class describing the target MD workspace, sorurce Event workspace and the transformations, necessary to perform on these workspaces
+ @parameter inWSWrapper -- the class wrapping the target MD workspace
+*/
+size_t  ConvToMDEventsEvents::initialize(const MDEvents::MDWSDescription &WSD, boost::shared_ptr<MDEvents::MDEventWSWrapper> inWSWrapper)
+{
+    size_t numSpec=ConvToMDEventsBase::initialize(WSD,inWSWrapper);
+
+    
+    pEventWS  = boost::dynamic_pointer_cast<const DataObjects::EventWorkspace>(inWS2D);
+    if(!pEventWS.get()){
+           throw(std::logic_error(" ConvertToMDEvensEventWS should work with defined event workspace"));
+    }
+ 
+    return numSpec;
+}
+
+void ConvToMDEventsEvents::runConversion(API::Progress *pProg)
+{
+       // Get the box controller
+        Mantid::API::BoxController_sptr bc = pWSWrapper->pWorkspace()->getBoxController();
+        size_t lastNumBoxes = bc->getTotalNumMDBoxes();
+        size_t nEventsInWS  = pWSWrapper->pWorkspace()->getNPoints();
+         // Is the access to input events thread-safe?
+        bool MultiThreadedAdding = pEventWS->threadSafe();
+
+        
+        // preprocessed detectors insure that each detector has its own spectra
+        size_t nValidSpectra  = this->pDetLoc->nDetectors();
+
+       // if any property dimension is outside of the data range requested, the job is done;
+        if(!pQConverter->calcGenericVariables(Coord,this->n_dims))return; 
+       
+        size_t eventsAdded  = 0;
+        for (size_t wi=0; wi <nValidSpectra; wi++)
+        {     
+
+           size_t nConverted   =  this->conversionChunk(wi);
+           eventsAdded         += nConverted;
+           nEventsInWS         += nConverted;
+      // Give this task to the scheduler
+         //%double cost = double(el.getNumberEvents());
+         //ts->push( new FunctionTask( func, cost) );
+
+          // Keep a running total of how many events we've added
+           if (bc->shouldSplitBoxes(nEventsInWS,eventsAdded, lastNumBoxes)){
+            // Do all the adding tasks
+            //   tp.joinAll();    
+            // Now do all the splitting tasks
+              //ws->splitAllIfNeeded(ts);
+               pWSWrapper->pWorkspace()->splitAllIfNeeded(NULL);
+             //if (ts->size() > 0)       tp.joinAll();
+
+            // Count the new # of boxes.
+              lastNumBoxes = pWSWrapper->pWorkspace()->getBoxController()->getTotalNumMDBoxes();
+              pProg->report(wi);
+           }
+   
+       }
+    //tp.joinAll();
+    // Do a final splitting of everything
+    //ws->splitAllIfNeeded(ts);
+    //tp.joinAll();
+    pWSWrapper->pWorkspace()->splitAllIfNeeded(NULL);
+    // Recount totals at the end.
+    pWSWrapper->pWorkspace()->refreshCache(); 
+    pWSWrapper->refreshCentroid();
+    pProg->report();
+}
+
+//
+size_t ConvToMDEventsEvents::conversionChunk(size_t workspaceIndex)
+{       
+
+       switch (this->pEventWS->getEventList(workspaceIndex).getEventType())
+        {
+        case Mantid::API::TOF:
+            return this->convertEventList<Mantid::DataObjects::TofEvent>(workspaceIndex);
+         case Mantid::API::WEIGHTED:
+          return  this->convertEventList<Mantid::DataObjects::WeightedEvent>(workspaceIndex);
+        case Mantid::API::WEIGHTED_NOTIME:
+          return this->convertEventList<Mantid::DataObjects::WeightedEventNoTime>(workspaceIndex);
+        default:
+           throw std::runtime_error("EventList had an unexpected data type!");
+        }
+}
+  
+
+} // endNamespace MDEvents
+} // endNamespace Mantid
+
+
diff --git a/Code/Mantid/Framework/MDEvents/src/ConvToMDPreprocDet.cpp b/Code/Mantid/Framework/MDEvents/src/ConvToMDPreprocDet.cpp
index cf8ef985a38..a23e346f9ff 100644
--- a/Code/Mantid/Framework/MDEvents/src/ConvToMDPreprocDet.cpp
+++ b/Code/Mantid/Framework/MDEvents/src/ConvToMDPreprocDet.cpp
@@ -9,36 +9,6 @@ namespace Mantid
 {
 namespace MDEvents
 {
-///// function sets appropriate energy conversion mode to work with detectors and unit conversion
-//void ConvToMDPreprocDet::setEmode(int mode)
-//{   
-//    if(mode<-1||mode>2){
-//        std::string Err="Energy conversion mode has to be between -1 and 2 but trying to set: "+boost::lexical_cast<std::string>(mode);
-//        throw(std::invalid_argument(Err));
-//    }
-//    emode = mode;
-//}
-/// function sets appropriate energy  to work with detectors and unit conversion
-//void ConvToMDPreprocDet::setEfix(double Ei)
-//{
-//    if(Ei<=0){
-//        std::string Err="Input neutron's energy can not be negative but equal: "+boost::lexical_cast<std::string>(Ei);
-//        throw(std::invalid_argument(Err));
-//    }
-//    efix  = Ei;
-//}
-/** Function sets up energy of neurtorns used by number of conversion algorithms */
-//void ConvToMDPreprocDet::setEi(const API::MatrixWorkspace_sptr inputWS)
-//{
-//  try{
-//      Kernel::PropertyWithValue<double>  *pProp(NULL);
-//      pProp=dynamic_cast<Kernel::PropertyWithValue<double>  *>(inputWS->run().getProperty("Ei"));
-//      efix=(*pProp);
-//  }catch(...){
-//      efix= std::numeric_limits<double>::quiet_NaN();
-//  }
-//}
-
 /// function sets source-sample distance  to work with detectors and unit conversion
 void ConvToMDPreprocDet::setL1(double Dist)
 {
diff --git a/Code/Mantid/Framework/MDEvents/src/ConvertToDiffractionMDWorkspace.cpp b/Code/Mantid/Framework/MDEvents/src/ConvertToDiffractionMDWorkspace.cpp
index 6290a5e9e8f..b5b8a92d82c 100644
--- a/Code/Mantid/Framework/MDEvents/src/ConvertToDiffractionMDWorkspace.cpp
+++ b/Code/Mantid/Framework/MDEvents/src/ConvertToDiffractionMDWorkspace.cpp
@@ -558,15 +558,7 @@ namespace MDEvents
       eventsAdded += eventsAdding;
       approxEventsInOutput += eventsAdding;
 
-      // Performance depends pretty strongly on WHEN you split the boxes.
-      // This is an empirically-determined way to optimize the splitting calls.
-      // Split when adding 1/16^th as many events as are already in the output,
-      //  (because when the workspace gets very large you should split less often)
-      // But no more often than every 10 million events.
-      size_t comparisonPoint = approxEventsInOutput/16;
-      if (comparisonPoint < 10000000)
-        comparisonPoint = 10000000;
-      if (bc->shouldSplitBoxes(eventsAdded, lastNumBoxes) || (eventsAdded > (comparisonPoint)))
+      if (bc->shouldSplitBoxes(approxEventsInOutput,eventsAdded, lastNumBoxes))
       {
         if (DODEBUG) g_log.information() << cputim << ": Added tasks worth " << eventsAdded << " events. WorkspaceIndex " << wi << std::endl;
         // Do all the adding tasks
diff --git a/Code/Mantid/Framework/MDEvents/src/MDEventWSWrapper.cpp b/Code/Mantid/Framework/MDEvents/src/MDEventWSWrapper.cpp
index 9313f95fc9c..b5dd6a8fb33 100644
--- a/Code/Mantid/Framework/MDEvents/src/MDEventWSWrapper.cpp
+++ b/Code/Mantid/Framework/MDEvents/src/MDEventWSWrapper.cpp
@@ -57,7 +57,7 @@ void  MDEventWSWrapper::addMDData(std::vector<float> &sig_err,std::vector<uint16
   
 
 /** method should be called at the end of the algorithm, to let the workspace manager know that it has whole responsibility for the workspace
-   (As the algorithm is static, it will hold the pointer to the workspace otherwise, not allowing the WS manager to delete WS on request or when it find this usefull)*/
+   (As the algorithm is static, it will hold the pointer to the workspace otherwise, not allowing the WS manager to delete WS on request or when it finds this usefull)*/
 void MDEventWSWrapper::releaseWorkspace()
 {
     // decrease the sp count by one
diff --git a/Code/Mantid/Framework/MDEvents/src/UnitsConversionHelper.cpp b/Code/Mantid/Framework/MDEvents/src/UnitsConversionHelper.cpp
index b41786944ea..e04ce9bada3 100644
--- a/Code/Mantid/Framework/MDEvents/src/UnitsConversionHelper.cpp
+++ b/Code/Mantid/Framework/MDEvents/src/UnitsConversionHelper.cpp
@@ -150,8 +150,24 @@ double UnitsConversionHelper::convertUnits(double val)
            throw std::runtime_error("updateConversion: unknown type of conversion requested");
  
     }
-
-
+}
+// copy constructor;
+UnitsConversionHelper::UnitsConversionHelper(const UnitsConversionHelper &another)
+{
+      UnitCnvrsn = another.UnitCnvrsn;
+      factor     = another.factor;
+      power      = another.power;
+
+      emode      = another.emode;
+      L1         = another.L1;
+      efix       = another.efix;
+      twoTheta   = another.twoTheta;
+      L2         = another.L2;
+      pTwoTheta  = another.pTwoTheta;
+      pL2        = another.pL2;
+
+      if(pSourceWSUnit.get())pSourceWSUnit = Kernel::Unit_sptr(another.pSourceWSUnit->clone());      
+      if(pTargetUnit.get())  pTargetUnit   = Kernel::Unit_sptr(another.pSourceWSUnit->clone());
 }
 
 } // endNamespace MDEvents
diff --git a/Code/Mantid/Framework/MDEvents/test/ConvertToMDEventsParamsTest.h b/Code/Mantid/Framework/MDEvents/test/ConvertToMDEventsParamsTest.h
index 0585465221e..99ed0529947 100644
--- a/Code/Mantid/Framework/MDEvents/test/ConvertToMDEventsParamsTest.h
+++ b/Code/Mantid/Framework/MDEvents/test/ConvertToMDEventsParamsTest.h
@@ -69,40 +69,7 @@ void testGetWS4DimIDFine()
 
 
 }
-//void testGetWS3DimIDFine()
-//{
-//    Mantid::API::MatrixWorkspace_sptr ws2D =WorkspaceCreationHelper::createProcessedWorkspaceWithCylComplexInstrument(4,10,true);
-//    API::NumericAxis *pAx = new API::NumericAxis(3);
-//    pAx->title() = "Dim1";
-//    pAx->setUnit("dSpacing");
-//    ws2D->replaceAxis(0,pAx);
-//    MDEvents::MDWSDescription TWS;
-//
-// 
-//    std::vector<std::string> dim_units;
-//    std::string Alg_ID; 
-//    ConvertToMDEventsParams params;
-//    std::vector<std::string> other_dim_names;
-//
-//    TS_ASSERT_THROWS_NOTHING(Alg_ID=params.identifyMatrixAlg(ws2D,"Q3D","Elastic",dim_units, TWS));
-//
-//    TSM_ASSERT_EQUALS("Inelastic workspace will produce 3 dimensions",3,dim_units.size());
-//    TSM_ASSERT_EQUALS("Last dimension of Elastic transformation should be ","Momentum",dim_units[2]);
-//    TSM_ASSERT_EQUALS("Alg ID would be: ","WS2DHistoQ3DCrystElasticCnvByTOF",Alg_ID);
-//    TS_ASSERT(!TWS.detInfoLost);
-//
-//    TS_ASSERT_THROWS_NOTHING(params.buildMDDimDescription(ws2D,Alg_ID,other_dim_names,TWS));
-//    TSM_ASSERT_EQUALS("elastic workspace will produce 3 dimensions",3,TWS.nDims);
-//    TS_ASSERT_EQUALS(TWS.dimIDs.size(),TWS.dimNames.size());
-//
-//    std::vector<std::string> dimID= TWS.getDefaultDimIDQ3D(0);
-//    for(size_t i=0;i<TWS.dimNames.size();i++)
-//    {
-//        TS_ASSERT_EQUALS(dimID[i],TWS.dimIDs[i]);
-//        TS_ASSERT_EQUALS(dimID[i],TWS.dimNames[i]);
-//    }
-//
-//}
+
 //void testGetWSDimNames2AxisNoQ()
 //{
 //    Mantid::API::MatrixWorkspace_sptr ws2D =WorkspaceCreationHelper::Create2DWorkspace(4,10);
-- 
GitLab