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
12
13#include <Poco/DOM/Attr.h>
14#include <Poco/DOM/AutoPtr.h>
15#include <Poco/DOM/DOMParser.h>
16#include <Poco/DOM/DOMWriter.h>
17#include <Poco/DOM/Document.h>
18#include <Poco/DOM/Element.h>
19#include <Poco/DOM/NodeList.h>
20#include <Poco/DOM/Text.h>
21#include <boost/algorithm/string.hpp>
22#include <boost/format.hpp>
23#include <optional>
24
25using namespace Mantid::Kernel;
28
29namespace Mantid::API {
30
31//-----------------------------------------------------------------------------------
35 // reset the clone file IO controller to avoid dublicated file based
36 // operations for different box controllers
37 return new BoxController(*this);
38}
39
40/*Private Copy constructor used in cloning */
42 : nd(other.nd), m_maxId(other.m_maxId), m_SplitThreshold(other.m_SplitThreshold),
43 m_significantEventsNumber(other.m_significantEventsNumber), m_maxDepth(other.m_maxDepth),
44 m_numEventsAtMax(other.m_numEventsAtMax), m_splitInto(other.m_splitInto), m_splitTopInto(other.m_splitTopInto),
45 m_numSplit(other.m_numSplit), m_numTopSplit(other.m_numTopSplit),
46 m_addingEvents_eventsPerTask(other.m_addingEvents_eventsPerTask),
47 m_addingEvents_numTasksPerBlock(other.m_addingEvents_numTasksPerBlock), m_numMDBoxes(other.m_numMDBoxes),
48 m_numMDGridBoxes(other.m_numMDGridBoxes), m_maxNumMDBoxes(other.m_maxNumMDBoxes),
49 m_fileIO(std::shared_ptr<API::IBoxControllerIO>()) {}
50
51bool BoxController::operator==(const BoxController &other) const {
52 if (nd != other.nd || m_maxId != other.m_maxId || m_SplitThreshold != other.m_SplitThreshold ||
53 m_maxDepth != other.m_maxDepth || m_numSplit != other.m_numSplit ||
54 m_splitInto.size() != other.m_splitInto.size() || m_numMDBoxes.size() != other.m_numMDBoxes.size() ||
55 m_numMDGridBoxes.size() != other.m_numMDGridBoxes.size() ||
56 m_maxNumMDBoxes.size() != other.m_maxNumMDBoxes.size())
57 return false;
58
59 for (size_t i = 0; i < m_splitInto.size(); i++) {
60 if (m_splitInto[i] != other.m_splitInto[i])
61 return false;
62 }
63
64 for (size_t i = 0; i < m_numMDBoxes.size(); i++) {
65 if (m_numMDBoxes[i] != other.m_numMDBoxes[i])
66 return false;
67 if (m_numMDGridBoxes[i] != other.m_numMDGridBoxes[i])
68 return false;
69 if (m_maxNumMDBoxes[i] != other.m_maxNumMDBoxes[i])
70 return false;
71 }
72
73 // Check top level splitting if they are set in both or not
74 if ((m_splitTopInto && !other.m_splitTopInto) || (!m_splitTopInto && other.m_splitTopInto)) {
75 return false;
76 }
77
78 if (m_splitTopInto && other.m_splitTopInto) {
79 if (m_splitTopInto.value().size() != other.m_splitTopInto.value().size()) {
80 return false;
81 } else {
82 for (size_t i = 0; i < m_splitTopInto.value().size(); i++) {
83 if (m_splitTopInto.value()[i] != other.m_splitTopInto.value()[i])
84 return false;
85 }
86 }
87 }
88
89 // There are number of variables which are
90 // 1) derived:
91 // Number of events sitting in the boxes which should be split but are already
92 // split up to the max depth: volatile size_t m_numEventsAtMax;
93 // 2) Dynamical and related to current processor and dynamical jobs
94 // allocation:
95 // For adding events tasks: size_t m_addingEvents_eventsPerTask;
96 // m_addingEvents_numTasksPerBlock;
97 // These variables are not compared here but may need to be compared in a
98 // future for some purposes.
99
100 return true;
101}
102
105 if (m_fileIO) {
106 m_fileIO->closeFile();
107 m_fileIO.reset();
108 }
109}
115size_t BoxController::claimIDRange(size_t range) {
116 std::lock_guard<std::mutex> lock(m_idMutex);
117 size_t tmp = m_maxId;
118 m_maxId += range;
119 return tmp;
120}
124std::string BoxController::toXMLString() const {
125 using namespace Poco::XML;
126
127 // Create the root element for this fragment.
128 AutoPtr<Document> pDoc = new Document;
129 AutoPtr<Element> pBoxElement = pDoc->createElement("BoxController");
130 pDoc->appendChild(pBoxElement);
131
132 AutoPtr<Element> element;
133 AutoPtr<Text> text;
134 std::string vecStr;
135
136 element = pDoc->createElement("NumDims");
137 text = pDoc->createTextNode(boost::str(boost::format("%d") % this->getNDims()));
138 element->appendChild(text);
139 pBoxElement->appendChild(element);
140
141 element = pDoc->createElement("MaxId");
142 text = pDoc->createTextNode(boost::str(boost::format("%d") % this->getMaxId()));
143 element->appendChild(text);
144 pBoxElement->appendChild(element);
145
146 element = pDoc->createElement("SplitThreshold");
147 text = pDoc->createTextNode(boost::str(boost::format("%d") % this->getSplitThreshold()));
148 element->appendChild(text);
149 pBoxElement->appendChild(element);
150
151 element = pDoc->createElement("MaxDepth");
152 text = pDoc->createTextNode(boost::str(boost::format("%d") % this->getMaxDepth()));
153 element->appendChild(text);
154 pBoxElement->appendChild(element);
155
156 element = pDoc->createElement("SplitInto");
157 vecStr = Kernel::Strings::join(this->m_splitInto.begin(), this->m_splitInto.end(), ",");
158 text = pDoc->createTextNode(vecStr);
159 element->appendChild(text);
160 pBoxElement->appendChild(element);
161
162 element = pDoc->createElement("SplitTopInto");
163 if (m_splitTopInto) {
164 vecStr = Kernel::Strings::join(this->m_splitTopInto.value().begin(), this->m_splitTopInto.value().end(), ",");
165 } else {
166 vecStr = "";
167 }
168 text = pDoc->createTextNode(vecStr);
169 element->appendChild(text);
170 pBoxElement->appendChild(element);
171
172 element = pDoc->createElement("NumMDBoxes");
173 vecStr = Kernel::Strings::join(this->m_numMDBoxes.begin(), this->m_numMDBoxes.end(), ",");
174 text = pDoc->createTextNode(vecStr);
175 element->appendChild(text);
176 pBoxElement->appendChild(element);
177
178 element = pDoc->createElement("NumMDGridBoxes");
179 vecStr = Kernel::Strings::join(this->m_numMDGridBoxes.begin(), this->m_numMDGridBoxes.end(), ",");
180 text = pDoc->createTextNode(vecStr);
181 element->appendChild(text);
182 pBoxElement->appendChild(element);
183
184 // Create a string representation of the DOM tree.
185 std::stringstream xmlstream;
186 DOMWriter writer;
187 writer.writeNode(xmlstream, pDoc);
188
189 return xmlstream.str();
190}
194std::string BoxController::getFilename() const {
195 if (m_fileIO)
196 return m_fileIO->getFileName();
197 else
198 return "";
199}
202bool BoxController::useWriteBuffer() const { return static_cast<bool>(m_fileIO); }
203
204//------------------------------------------------------------------------------------------------------
210void BoxController::fromXMLString(const std::string &xml) {
211 using namespace Poco::XML;
212 Poco::XML::DOMParser pParser;
213 Poco::AutoPtr<Poco::XML::Document> pDoc = pParser.parseString(xml);
214 Poco::XML::Element *pBoxElement = pDoc->documentElement();
215
216 std::string s;
217 s = pBoxElement->getChildElement("NumDims")->innerText();
219 if (nd == 0 || nd > 20)
220 throw std::runtime_error("BoxController::fromXMLString(): Bad number of dimensions found.");
221
222 size_t ival;
223 Strings::convert(pBoxElement->getChildElement("MaxId")->innerText(), ival);
224 this->setMaxId(ival);
225 Strings::convert(pBoxElement->getChildElement("SplitThreshold")->innerText(), ival);
226 this->setSplitThreshold(ival);
227 Strings::convert(pBoxElement->getChildElement("MaxDepth")->innerText(), ival);
228 this->setMaxDepth(ival);
229
230 s = pBoxElement->getChildElement("SplitInto")->innerText();
231 this->m_splitInto = splitStringIntoVector<size_t>(s);
232
233 // Need to make sure that we handle box controllers which did not have the
234 // SplitTopInto
235 // attribute
236 Poco::AutoPtr<NodeList> nodes = pBoxElement->getElementsByTagName("SplitTopInto");
237 if (nodes->length() > 0) {
238 s = pBoxElement->getChildElement("SplitTopInto")->innerText();
239 if (s.empty()) {
240 this->m_splitTopInto = std::nullopt;
241 } else {
242 this->m_splitTopInto = splitStringIntoVector<size_t>(s);
243 }
244 } else {
245 this->m_splitTopInto = std::nullopt;
246 }
247
248 s = pBoxElement->getChildElement("NumMDBoxes")->innerText();
249 this->m_numMDBoxes = splitStringIntoVector<size_t>(s);
250
251 s = pBoxElement->getChildElement("NumMDGridBoxes")->innerText();
252 this->m_numMDGridBoxes = splitStringIntoVector<size_t>(s);
253
254 this->calcNumSplit();
255
256 if (m_splitTopInto) {
257 this->calcNumTopSplit();
258 }
259}
262 if (m_fileIO) {
263 // flush DB cache
264 m_fileIO->flushCache();
265 // close underlying file
266 m_fileIO->closeFile();
267 // decrease the sp counter by one and nullify this instance of sp.
268 m_fileIO.reset(); // = std::shared_ptr<API::IBoxControllerIO>();
269 }
270}
277void BoxController::setFileBacked(const std::shared_ptr<IBoxControllerIO> &newFileIO, const std::string &fileName) {
278 if (!newFileIO->isOpened()) {
279 bool opened = newFileIO->openFile(fileName, "w");
280 if (!opened)
281 throw(Kernel::Exception::FileError("Can not open target file for filebased box controller ", fileName));
282 }
283
284 this->m_fileIO = newFileIO;
285}
286
287} // namespace Mantid::API
gsl_vector * tmp
This class is used by MDBox and MDGridBox in order to intelligently determine optimal behavior.
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;
std::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.
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.
void setMaxId(size_t newMaxId)
Set the new maximum ID number anywhere in the workspace.
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:696
MANTID_KERNEL_DLL std::vector< NumT > splitStringIntoVector(std::string listString, const std::string &separators=", ")
Take a string of comma or space-separated values, and splits it into a vector of doubles.
STL namespace.