diff --git a/Code/Mantid/Framework/API/inc/MantidAPI/IMDEventWorkspace.h b/Code/Mantid/Framework/API/inc/MantidAPI/IMDEventWorkspace.h index 883e6b6055e148109a2bb3085ca874361faf4abe..7254708527332f387d8df9feaacb0f098001c494 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 6d5da0779e72dda12a3994a5e71c249caa6c72d9..4c01db216daf44f3cc4c26b2b5d2fa5c99c2fa27 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 0b75b1792964a475d9effecff62bfc904248adaa..ef2d5186c75b7f757fcc347f59fb2e3d5951d4df 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 2e76714cfd0dad532bb6eb1441e09d798e938de9..abc1d7a1876e3d687778ddad1701cb185f5581d7 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