Mantid
Loading...
Searching...
No Matches
BoxController.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
7#include <sstream>
8
11#include "MantidKernel/System.h"
13
14#include <Poco/DOM/Attr.h>
15#include <Poco/DOM/AutoPtr.h>
16#include <Poco/DOM/DOMParser.h>
17#include <Poco/DOM/DOMWriter.h>
18#include <Poco/DOM/Document.h>
19#include <Poco/DOM/Element.h>
20#include <Poco/DOM/NodeList.h>
21#include <Poco/DOM/Text.h>
22#include <boost/algorithm/string.hpp>
23#include <boost/format.hpp>
24#include <boost/optional.hpp>
25
26using namespace Mantid::Kernel;
29
30namespace Mantid::API {
31
32//-----------------------------------------------------------------------------------
36 // reset the clone file IO controller to avoid dublicated file based
37 // operations for different box controllers
38 return new BoxController(*this);
39}
40
41/*Private Copy constructor used in cloning */
43 : nd(other.nd), m_maxId(other.m_maxId), m_SplitThreshold(other.m_SplitThreshold),
44 m_significantEventsNumber(other.m_significantEventsNumber), m_maxDepth(other.m_maxDepth),
45 m_numEventsAtMax(other.m_numEventsAtMax), m_splitInto(other.m_splitInto), m_splitTopInto(other.m_splitTopInto),
46 m_numSplit(other.m_numSplit), m_numTopSplit(other.m_numTopSplit),
47 m_addingEvents_eventsPerTask(other.m_addingEvents_eventsPerTask),
48 m_addingEvents_numTasksPerBlock(other.m_addingEvents_numTasksPerBlock), m_numMDBoxes(other.m_numMDBoxes),
49 m_numMDGridBoxes(other.m_numMDGridBoxes), m_maxNumMDBoxes(other.m_maxNumMDBoxes),
50 m_fileIO(std::shared_ptr<API::IBoxControllerIO>()) {}
51
52bool BoxController::operator==(const BoxController &other) const {
53 if (nd != other.nd || m_maxId != other.m_maxId || m_SplitThreshold != other.m_SplitThreshold ||
54 m_maxDepth != other.m_maxDepth || m_numSplit != other.m_numSplit ||
55 m_splitInto.size() != other.m_splitInto.size() || m_numMDBoxes.size() != other.m_numMDBoxes.size() ||
56 m_numMDGridBoxes.size() != other.m_numMDGridBoxes.size() ||
57 m_maxNumMDBoxes.size() != other.m_maxNumMDBoxes.size())
58 return false;
59
60 for (size_t i = 0; i < m_splitInto.size(); i++) {
61 if (m_splitInto[i] != other.m_splitInto[i])
62 return false;
63 }
64
65 for (size_t i = 0; i < m_numMDBoxes.size(); i++) {
66 if (m_numMDBoxes[i] != other.m_numMDBoxes[i])
67 return false;
68 if (m_numMDGridBoxes[i] != other.m_numMDGridBoxes[i])
69 return false;
70 if (m_maxNumMDBoxes[i] != other.m_maxNumMDBoxes[i])
71 return false;
72 }
73
74 // Check top level splitting if they are set in both or not
75 if ((m_splitTopInto && !other.m_splitTopInto) || (!m_splitTopInto && other.m_splitTopInto)) {
76 return false;
77 }
78
79 if (m_splitTopInto && other.m_splitTopInto) {
80 if (m_splitTopInto.get().size() != other.m_splitTopInto.get().size()) {
81 return false;
82 } else {
83 for (size_t i = 0; i < m_splitTopInto.get().size(); i++) {
84 if (m_splitTopInto.get()[i] != other.m_splitTopInto.get()[i])
85 return false;
86 }
87 }
88 }
89
90 // There are number of variables which are
91 // 1) derived:
92 // Number of events sitting in the boxes which should be split but are already
93 // split up to the max depth: volatile size_t m_numEventsAtMax;
94 // 2) Dynamical and related to current processor and dynamical jobs
95 // allocation:
96 // For adding events tasks: size_t m_addingEvents_eventsPerTask;
97 // m_addingEvents_numTasksPerBlock;
98 // These variables are not compared here but may need to be compared in a
99 // future for some purposes.
100
101 return true;
102}
103
106 if (m_fileIO) {
107 m_fileIO->closeFile();
108 m_fileIO.reset();
109 }
110}
116size_t BoxController::claimIDRange(size_t range) {
117 std::lock_guard<std::mutex> lock(m_idMutex);
118 size_t tmp = m_maxId;
119 m_maxId += range;
120 return tmp;
121}
125std::string BoxController::toXMLString() const {
126 using namespace Poco::XML;
127
128 // Create the root element for this fragment.
129 AutoPtr<Document> pDoc = new Document;
130 AutoPtr<Element> pBoxElement = pDoc->createElement("BoxController");
131 pDoc->appendChild(pBoxElement);
132
133 AutoPtr<Element> element;
134 AutoPtr<Text> text;
135 std::string vecStr;
136
137 element = pDoc->createElement("NumDims");
138 text = pDoc->createTextNode(boost::str(boost::format("%d") % this->getNDims()));
139 element->appendChild(text);
140 pBoxElement->appendChild(element);
141
142 element = pDoc->createElement("MaxId");
143 text = pDoc->createTextNode(boost::str(boost::format("%d") % this->getMaxId()));
144 element->appendChild(text);
145 pBoxElement->appendChild(element);
146
147 element = pDoc->createElement("SplitThreshold");
148 text = pDoc->createTextNode(boost::str(boost::format("%d") % this->getSplitThreshold()));
149 element->appendChild(text);
150 pBoxElement->appendChild(element);
151
152 element = pDoc->createElement("MaxDepth");
153 text = pDoc->createTextNode(boost::str(boost::format("%d") % this->getMaxDepth()));
154 element->appendChild(text);
155 pBoxElement->appendChild(element);
156
157 element = pDoc->createElement("SplitInto");
158 vecStr = Kernel::Strings::join(this->m_splitInto.begin(), this->m_splitInto.end(), ",");
159 text = pDoc->createTextNode(vecStr);
160 element->appendChild(text);
161 pBoxElement->appendChild(element);
162
163 element = pDoc->createElement("SplitTopInto");
164 if (m_splitTopInto) {
165 vecStr = Kernel::Strings::join(this->m_splitTopInto.get().begin(), this->m_splitTopInto.get().end(), ",");
166 } else {
167 vecStr = "";
168 }
169 text = pDoc->createTextNode(vecStr);
170 element->appendChild(text);
171 pBoxElement->appendChild(element);
172
173 element = pDoc->createElement("NumMDBoxes");
174 vecStr = Kernel::Strings::join(this->m_numMDBoxes.begin(), this->m_numMDBoxes.end(), ",");
175 text = pDoc->createTextNode(vecStr);
176 element->appendChild(text);
177 pBoxElement->appendChild(element);
178
179 element = pDoc->createElement("NumMDGridBoxes");
180 vecStr = Kernel::Strings::join(this->m_numMDGridBoxes.begin(), this->m_numMDGridBoxes.end(), ",");
181 text = pDoc->createTextNode(vecStr);
182 element->appendChild(text);
183 pBoxElement->appendChild(element);
184
185 // Create a string representation of the DOM tree.
186 std::stringstream xmlstream;
187 DOMWriter writer;
188 writer.writeNode(xmlstream, pDoc);
189
190 return xmlstream.str();
191}
195std::string BoxController::getFilename() const {
196 if (m_fileIO)
197 return m_fileIO->getFileName();
198 else
199 return "";
200}
203bool BoxController::useWriteBuffer() const { return static_cast<bool>(m_fileIO); }
204
205//------------------------------------------------------------------------------------------------------
211void BoxController::fromXMLString(const std::string &xml) {
212 using namespace Poco::XML;
213 Poco::XML::DOMParser pParser;
214 Poco::AutoPtr<Poco::XML::Document> pDoc = pParser.parseString(xml);
215 Poco::XML::Element *pBoxElement = pDoc->documentElement();
216
217 std::string s;
218 s = pBoxElement->getChildElement("NumDims")->innerText();
220 if (nd == 0 || nd > 20)
221 throw std::runtime_error("BoxController::fromXMLString(): Bad number of dimensions found.");
222
223 size_t ival;
224 Strings::convert(pBoxElement->getChildElement("MaxId")->innerText(), ival);
225 this->setMaxId(ival);
226 Strings::convert(pBoxElement->getChildElement("SplitThreshold")->innerText(), ival);
227 this->setSplitThreshold(ival);
228 Strings::convert(pBoxElement->getChildElement("MaxDepth")->innerText(), ival);
229 this->setMaxDepth(ival);
230
231 s = pBoxElement->getChildElement("SplitInto")->innerText();
232 this->m_splitInto = splitStringIntoVector<size_t>(s);
233
234 // Need to make sure that we handle box controllers which did not have the
235 // SplitTopInto
236 // attribute
237 Poco::AutoPtr<NodeList> nodes = pBoxElement->getElementsByTagName("SplitTopInto");
238 if (nodes->length() > 0) {
239 s = pBoxElement->getChildElement("SplitTopInto")->innerText();
240 if (s.empty()) {
241 this->m_splitTopInto = boost::none;
242 } else {
243 this->m_splitTopInto = splitStringIntoVector<size_t>(s);
244 }
245 } else {
246 this->m_splitTopInto = boost::none;
247 }
248
249 s = pBoxElement->getChildElement("NumMDBoxes")->innerText();
250 this->m_numMDBoxes = splitStringIntoVector<size_t>(s);
251
252 s = pBoxElement->getChildElement("NumMDGridBoxes")->innerText();
253 this->m_numMDGridBoxes = splitStringIntoVector<size_t>(s);
254
255 this->calcNumSplit();
256
257 if (m_splitTopInto) {
258 this->calcNumTopSplit();
259 }
260}
263 if (m_fileIO) {
264 // flush DB cache
265 m_fileIO->flushCache();
266 // close underlying file
267 m_fileIO->closeFile();
268 // decrease the sp counter by one and nullify this instance of sp.
269 m_fileIO.reset(); // = std::shared_ptr<API::IBoxControllerIO>();
270 }
271}
278void BoxController::setFileBacked(const std::shared_ptr<IBoxControllerIO> &newFileIO, const std::string &fileName) {
279 if (!newFileIO->isOpened()) {
280 bool opened = newFileIO->openFile(fileName, "w");
281 if (!opened)
282 throw(Kernel::Exception::FileError("Can not open target file for filebased box controller ", fileName));
283 }
284
285 this->m_fileIO = newFileIO;
286}
287
288} // namespace Mantid::API
gsl_vector * tmp
This class is used by MDBox and MDGridBox in order to intelligently determine optimal behavior.
Definition: BoxController.h:33
void clearFileBacked()
function clears the file-backed status of the box controller
size_t claimIDRange(size_t range)
get range of id-s and increment box ID by this range;
boost::optional< std::vector< size_t > > m_splitTopInto
Splittin # for all dimensions in the top level.
virtual ~BoxController()
Destructor.
std::shared_ptr< IBoxControllerIO > m_fileIO
std::vector< size_t > m_splitInto
Splitting # for all dimensions.
virtual BoxController * clone() const
create new box controller from the existing one.
size_t m_numSplit
When you split a MDBox, it becomes this many sub-boxes.
size_t m_maxDepth
Maximum splitting depth: don't go further than this many levels of recursion.
size_t getNDims() const
Get # of dimensions.
Definition: BoxController.h:70
std::string getFilename() const
the function left for compartibility with the previous bc python interface.
std::vector< size_t > m_numMDGridBoxes
For tracking how many MDGridBoxes (not MDBoxes) are at each recursion level.
size_t nd
Number of dimensions.
std::vector< size_t > m_numMDBoxes
For tracking how many MDBoxes (not MDGridBoxes) are at each recursion level.
void setMaxDepth(size_t value)
Sets the max recursion depth allowed for grid box splitting.
bool operator==(const BoxController &other) const
Equality operator.
void fromXMLString(const std::string &xml)
De-serializing XML.
void calcNumTopSplit()
When you split an MDBox by force, it becomes this many sub boxes.
void setSplitThreshold(size_t threshold)
Set the splitting threshold.
void calcNumSplit()
When you split a MDBox, it becomes this many sub-boxes.
BoxController(size_t nd)
Constructor.
Definition: BoxController.h:41
void setMaxId(size_t newMaxId)
Set the new maximum ID number anywhere in the workspace.
Definition: BoxController.h:87
size_t m_SplitThreshold
Splitting threshold.
size_t getSplitThreshold() const
Return the splitting threshold, in # of events.
std::mutex m_idMutex
Mutex for getting IDs.
bool useWriteBuffer() const
the compartibility function – the write buffer is always used for file based workspaces
std::string toXMLString() const
Serialize.
void setFileBacked(const std::shared_ptr< IBoxControllerIO > &newFileIO, const std::string &fileName="")
makes box controller file based by providing class, responsible for fileIO.
std::vector< double > m_maxNumMDBoxes
This is the maximum number of MD boxes there could be at each recursion level (e.g.
size_t m_maxId
The maximum ID number of any boxes in the workspace (not inclusive, i.e.
The header describes interface to IO Operations perfomed by the box controller May be replaced by a b...
Records the filename and the description of failure.
Definition: Exception.h:98
DLLExport std::string join(ITERATOR_TYPE begin, ITERATOR_TYPE end, const std::string &separator, typename std::enable_if<!(std::is_same< typename std::iterator_traits< ITERATOR_TYPE >::iterator_category, std::random_access_iterator_tag >::value)>::type *=nullptr)
Join a set or vector of (something that turns into a string) together into one string,...
Definition: Strings.h:84
int convert(const std::string &A, T &out)
Convert a string into a number.
Definition: Strings.cpp:665
MANTID_KERNEL_DLL std::vector< NumT > splitStringIntoVector(std::string listString)
Take a string of comma or space-separated values, and splits it into a vector of doubles.
STL namespace.