From 94f57f7c7ae3fe10f5a9ba4d22ed57ff0a7c2223 Mon Sep 17 00:00:00 2001
From: Janik Zikovsky <zikovskyjl@ornl.gov>
Date: Thu, 19 Jan 2012 11:05:20 -0500
Subject: [PATCH] Refs #4562: reusable method for MinRecursionDepth in
 MDWorkspaces

---
 .../API/inc/MantidAPI/IMDEventWorkspace.h     |  4 ++
 .../inc/MantidMDEvents/MDEventWorkspace.h     |  6 ++-
 .../MDEvents/src/CreateMDWorkspace.cpp        | 31 +----------
 .../MDEvents/src/MDEventWorkspace.cpp         | 51 +++++++++++++++++++
 4 files changed, 61 insertions(+), 31 deletions(-)

diff --git a/Code/Mantid/Framework/API/inc/MantidAPI/IMDEventWorkspace.h b/Code/Mantid/Framework/API/inc/MantidAPI/IMDEventWorkspace.h
index 883e6b6055e..72547085273 100644
--- a/Code/Mantid/Framework/API/inc/MantidAPI/IMDEventWorkspace.h
+++ b/Code/Mantid/Framework/API/inc/MantidAPI/IMDEventWorkspace.h
@@ -63,6 +63,9 @@ namespace API
     /// Refresh the cache (integrated signal of each box)
     virtual void refreshCache() = 0;
 
+    /// Recurse down to a minimum depth
+    virtual void setMinRecursionDepth(size_t depth) = 0;
+
     /// Return the type of event contained, as a string. MDEvent or MDLeanEvent
     virtual std::string getEventTypeName() const = 0;
 
@@ -73,6 +76,7 @@ namespace API
 
     void setFileNeedsUpdating(bool value);
 
+
   protected:
     /// Marker set to true when a file-backed workspace needs its back-end file updated (by calling SaveMD(UpdateFileBackEnd=1) )
     bool m_fileNeedsUpdating;
diff --git a/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/MDEventWorkspace.h b/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/MDEventWorkspace.h
index 6d5da0779e7..4c01db216da 100644
--- a/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/MDEventWorkspace.h
+++ b/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/MDEventWorkspace.h
@@ -86,12 +86,14 @@ namespace MDEvents
 
     virtual void splitAllIfNeeded(Kernel::ThreadScheduler * ts);
 
-    virtual  void splitBox();
+    virtual void splitBox();
 
-    virtual  void refreshCache();
+    virtual void refreshCache();
 
     std::string getEventTypeName() const;
 
+    virtual void setMinRecursionDepth(size_t minDepth);
+
     //------------------------ (END) IMDEventWorkspace Methods -----------------------------------------
 
     Mantid::API::ITableWorkspace_sptr makeBoxTable(size_t start, size_t num);
diff --git a/Code/Mantid/Framework/MDEvents/src/CreateMDWorkspace.cpp b/Code/Mantid/Framework/MDEvents/src/CreateMDWorkspace.cpp
index 0b75b179296..ef2d5186c75 100644
--- a/Code/Mantid/Framework/MDEvents/src/CreateMDWorkspace.cpp
+++ b/Code/Mantid/Framework/MDEvents/src/CreateMDWorkspace.cpp
@@ -126,35 +126,8 @@ namespace MDEvents
 
     // Do we split more due to MinRecursionDepth?
     int minDepth = this->getProperty("MinRecursionDepth");
-    double numBoxes = pow(double(bc->getNumSplit()), double(minDepth));
-    double memoryToUse = numBoxes * double(sizeof(MDBox<MDE,nd>)) / 1024.0;
-    MemoryStats stats;
-    if (double(stats.availMem()) < memoryToUse)
-    {
-      g_log.error() << "MinRecursionDepth is set to " << minDepth << ", which would create " << numBoxes << " boxes using " <<  memoryToUse << " kB of memory."
-          << " You have " << stats.availMem() << " kB available." << std::endl;
-      throw std::runtime_error("Not enough memory available for the given MinRecursionDepth!");
-    }
-
-    for (int depth = 1; depth < minDepth; depth++)
-    {
-      // Get all the MDGridBoxes in the workspace
-      std::vector<IMDBox<MDE,nd>*> boxes;
-      boxes.clear();
-      ws->getBox()->getBoxes(boxes, depth-1, false);
-      for (size_t i=0; i<boxes.size(); i++)
-      {
-        IMDBox<MDE,nd> * box = boxes[i];
-        MDGridBox<MDE,nd>* gbox = dynamic_cast<MDGridBox<MDE,nd>*>(box);
-        if (gbox)
-        {
-          // Split ALL the contents.
-          for (size_t j=0; j<gbox->getNumChildren(); j++)
-            gbox->splitContents(j, NULL);
-        }
-      }
-    }
-
+    if (minDepth<0) throw std::invalid_argument("MinRecursionDepth must be >= 0.");
+    ws->setMinRecursionDepth(size_t(minDepth));
   }
 
 
diff --git a/Code/Mantid/Framework/MDEvents/src/MDEventWorkspace.cpp b/Code/Mantid/Framework/MDEvents/src/MDEventWorkspace.cpp
index 2e76714cfd0..abc1d7a1876 100644
--- a/Code/Mantid/Framework/MDEvents/src/MDEventWorkspace.cpp
+++ b/Code/Mantid/Framework/MDEvents/src/MDEventWorkspace.cpp
@@ -18,6 +18,7 @@
 #include <iomanip>
 #include <functional>
 #include "MantidMDEvents/MDBoxIterator.h"
+#include "MantidKernel/Memory.h"
 
 using namespace Mantid;
 using namespace Mantid::Kernel;
@@ -123,6 +124,56 @@ namespace MDEvents
     return data->getNPoints();
   }
 
+  //-----------------------------------------------------------------------------------------------
+  /** Recurse box structure down to a minimum depth.
+   *
+   * This will split all boxes so that all MDBoxes are at the depth indicated.
+   * 0 = no splitting, 1 = one level of splitting, etc.
+   *
+   * WARNING! This should ONLY be called before adding any events to a workspace.
+   *
+   * WARNING! Be careful using this since it can quickly create a huge
+   * number of boxes = (SplitInto ^ (MinRercursionDepth * NumDimensions))
+   *
+   * @param minDepth :: minimum recursion depth.
+   * @throw std::runtime_error if there is not enough memory for the boxes.
+   */
+  TMDE(
+  void MDEventWorkspace)::setMinRecursionDepth(size_t minDepth)
+  {
+    BoxController_sptr bc = this->getBoxController();
+    double numBoxes = pow(double(bc->getNumSplit()), double(minDepth));
+    double memoryToUse = numBoxes * double(sizeof(MDBox<MDE,nd>)) / 1024.0;
+    MemoryStats stats;
+    if (double(stats.availMem()) < memoryToUse)
+    {
+      std::ostringstream mess;
+      mess << "Not enough memory available for the given MinRecursionDepth! "
+           << "MinRecursionDepth is set to " << minDepth << ", which would create " << numBoxes << " boxes using " <<  memoryToUse << " kB of memory."
+           << " You have " << stats.availMem() << " kB available." << std::endl;
+      throw std::runtime_error(mess.str());
+    }
+
+    for (size_t depth = 1; depth < minDepth; depth++)
+    {
+      // Get all the MDGridBoxes in the workspace
+      std::vector<IMDBox<MDE,nd>*> boxes;
+      boxes.clear();
+      this->getBox()->getBoxes(boxes, depth-1, false);
+      for (size_t i=0; i<boxes.size(); i++)
+      {
+        IMDBox<MDE,nd> * box = boxes[i];
+        MDGridBox<MDE,nd>* gbox = dynamic_cast<MDGridBox<MDE,nd>*>(box);
+        if (gbox)
+        {
+          // Split ALL the contents.
+          for (size_t j=0; j<gbox->getNumChildren(); j++)
+            gbox->splitContents(j, NULL);
+        }
+      }
+    }
+  }
+
 
   //-----------------------------------------------------------------------------------------------
   /// Set the number of bins in each dimension to something corresponding to the estimated resolution of the finest binning
-- 
GitLab