Mantid
Loading...
Searching...
No Matches
MDBox.hxx
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 +
13#include <algorithm>
14#include <boost/math/special_functions/round.hpp>
15#include <cmath>
16#include <numeric>
17
18namespace Mantid {
19namespace DataObjects {
20
23 if (m_Saveable) {
24 // tell disk buffer that there are no point of tracking this box any more.
25 // BAD!!! TODO: make correct destructors order.
26 if (this->m_BoxController) // it is destructor, in tests everything may fall
27 // apart, though it should not be issue for a
28 // workspace
29 {
30 if (this->m_BoxController->isFileBacked()) {
31 this->m_BoxController->getFileIO()->objectDeleted(m_Saveable.get());
32 }
33 }
34 }
35}
36//-----------------------------------------------------------------------------------------------
44TMDE(MDBox)::MDBox(API::BoxController_sptr &splitter, const uint32_t depth, const size_t nBoxEvents, const size_t boxID)
45 : MDBoxBase<MDE, nd>(splitter.get(), depth, boxID), m_Saveable(nullptr), m_bIsMasked(false) {
46 initMDBox(nBoxEvents);
48
49//-----------------------------------------------------------------------------------------------
56TMDE(MDBox)::MDBox(API::BoxController *const splitter, const uint32_t depth, const size_t nBoxEvents,
57 const size_t boxID)
58 : MDBoxBase<MDE, nd>(splitter, depth, boxID), m_Saveable(nullptr), m_bIsMasked(false) {
59 initMDBox(nBoxEvents);
60}
62//-----------------------------------------------------------------------------------------------
71TMDE(MDBox)::MDBox(API::BoxController_sptr &splitter, const uint32_t depth,
72 const std::vector<Mantid::Geometry::MDDimensionExtents<coord_t>> &extentsVector,
73 const size_t nBoxEvents, const size_t boxID)
74 : MDBoxBase<MDE, nd>(splitter.get(), depth, boxID, extentsVector), m_Saveable(nullptr), m_bIsMasked(false) {
75 initMDBox(nBoxEvents);
76}
77//-----------------------------------------------------------------------------------------------
86TMDE(MDBox)::MDBox(API::BoxController *const splitter, const uint32_t depth,
87 const std::vector<Mantid::Geometry::MDDimensionExtents<coord_t>> &extentsVector,
88 const size_t nBoxEvents, const size_t boxID)
89 : MDBoxBase<MDE, nd>(splitter, depth, boxID, extentsVector), m_Saveable(nullptr), m_bIsMasked(false) {
90 initMDBox(nBoxEvents);
92
102template <typename MDE, size_t nd>
103MDBox<MDE, nd>::MDBox(Mantid::API::BoxController *const bc, const uint32_t depth,
104 const std::vector<Mantid::Geometry::MDDimensionExtents<coord_t>> &extentsVector,
105 EventIterator begin, EventIterator end)
106 : MDBoxBase<MDE, nd>(bc, depth, 0, extentsVector), m_Saveable(nullptr), data(std::vector<MDE>(begin, end)),
107 m_bIsMasked(false) {
109 if (this->m_BoxController->isFileBacked())
111}
112
114TMDE(void MDBox)::initMDBox(const size_t nBoxEvents) {
115 if (this->m_BoxController->getNDims() != nd)
116 throw std::invalid_argument("MDBox::ctor(): controller passed has the wrong number of dimensions.");
117
118 if (nBoxEvents != UNDEF_SIZET)
119 data.reserve(nBoxEvents);
120
121 if (this->m_BoxController->isFileBacked())
122 this->setFileBacked();
123}
124
125//-----------------------------------------------------------------------------------------------
131TMDE(MDBox)::MDBox(const MDBox<MDE, nd> &other, Mantid::API::BoxController *const otherBC)
132 : MDBoxBase<MDE, nd>(other, otherBC), m_Saveable(nullptr), data(other.data), m_bIsMasked(other.m_bIsMasked) {
133 if (otherBC) // may be absent in some tests but generally have to be present
134 {
135 if (otherBC->isFileBacked())
136 this->setFileBacked();
137 }
138}
139// unhide MDBoxBase method
140TMDE(size_t MDBox)::addEventsUnsafe(const std::vector<MDE> &events) {
143
144//-----------------------------------------------------------------------------------------------
146TMDE(void MDBox)::clear() {
147 // Make sure the object is not in any of the disk MRUs, and mark any space it
148 // used as free
149 // if (this->m_BoxController->useWriteBuffer())
150 if (m_Saveable)
151 this->m_BoxController->getFileIO()->objectDeleted(m_Saveable.get());
152
153 // Clear all contents
154 this->m_signal = 0.0;
155 this->m_errorSquared = 0.0;
156
157 this->clearDataFromMemory();
158}
159
160TMDE(Kernel::ISaveable *MDBox)::getISaveable() { return m_Saveable.get(); }
161TMDE(Kernel::ISaveable *MDBox)::getISaveable() const { return m_Saveable.get(); }
163//-----------------------------------------------------------------------------------------------
167TMDE(void MDBox)::clearDataFromMemory() {
168 data.clear();
169 vec_t().swap(data); // Linux trick to really free the memory
170 // mark data unchanged
171 if (m_Saveable) {
172 m_Saveable->setLoaded(false);
173 m_Saveable->setBusy(false);
174 m_Saveable->clearDataChanged();
175 }
178//-----------------------------------------------------------------------------------------------
180TMDE(size_t MDBox)::getNumDims() const { return nd; }
182//-----------------------------------------------------------------------------------------------
185TMDE(size_t MDBox)::getNumMDBoxes() const { return 1; }
187//-----------------------------------------------------------------------------------------------
189TMDE(void MDBox)::getBoxes(std::vector<MDBoxBase<MDE, nd> *> &boxes, size_t /*maxDepth*/, bool /*leafOnly*/) {
190 boxes.emplace_back(this);
191}
192TMDE(void MDBox)::getBoxes(std::vector<API::IMDNode *> &boxes, size_t /*maxDepth*/, bool /*leafOnly*/) {
193 boxes.emplace_back(this);
195
196//-----------------------------------------------------------------------------------------------
198TMDE(void MDBox)::getBoxes(std::vector<MDBoxBase<MDE, nd> *> &boxes, size_t /*maxDepth*/, bool /*leafOnly*/,
199 Mantid::Geometry::MDImplicitFunction * /*function*/) {
200 boxes.emplace_back(this);
201}
202TMDE(void MDBox)::getBoxes(std::vector<API::IMDNode *> &boxes, size_t /*maxDepth*/, bool /*leafOnly*/,
203 Mantid::Geometry::MDImplicitFunction * /*function*/) {
204 boxes.emplace_back(this);
205}
206
207//-----------------------------------------------------------------------------------------------
214TMDE(void MDBox)::getBoxes(std::vector<API::IMDNode *> &outBoxes, const std::function<bool(API::IMDNode *)> &cond) {
215 if (cond(this))
216 outBoxes.emplace_back(this);
217}
218
219//-----------------------------------------------------------------------------------------------
225TMDE(uint64_t MDBox)::getNPoints() const {
226 if (!m_Saveable)
227 return data.size();
228
229 if (m_Saveable->wasSaved()) {
230 if (m_Saveable->isLoaded())
231 return data.size();
232 else // m_fileNumEvents
233 return m_Saveable->getFileSize() + data.size();
234 } else
235 return data.size();
236}
237
238//-----------------------------------------------------------------------------------------------
243TMDE(std::vector<MDE> &MDBox)::getEvents() {
244 if (!m_Saveable)
245 return data;
246 else {
247 if (m_Saveable->wasSaved()) { // Load and concatenate the events if needed
248 m_Saveable->load(); // this will set isLoaded to true if not already loaded;
249 }
250 // The data vector is busy - can't release the memory yet
251 m_Saveable->setBusy(true);
252 // the non-const access to events assumes that the data will be modified;
253 m_Saveable->setDataChanged();
254
255 // Tell the to-write buffer to discard the object (when no longer busy) as
256 // it has not been modified
257 this->m_BoxController->getFileIO()->toWrite(m_Saveable.get());
258 // else: do nothing if the events are already in memory.
259 return data;
260 }
261}
262
263TMDE(const std::vector<MDE> &MDBox)::getEvents() const { return getConstEvents(); }
264//-----------------------------------------------------------------------------------------------
269TMDE(const std::vector<MDE> &MDBox)::getConstEvents() const {
270 if (!m_Saveable)
271 return data;
272 else {
273 if (m_Saveable->wasSaved()) {
274 // Load and concatenate the events if needed
275 m_Saveable->load(); // this will set isLoaded to true if not already loaded;
276 // This access to data was const. Don't change the m_dataModified flag.
277 }
278 // The data vector is busy - can't release the memory yet
279 m_Saveable->setBusy(true);
280
281 // Tell the to-write buffer to discard the object (when no longer busy) as
282 // it has not been modified
283 this->m_BoxController->getFileIO()->toWrite(m_Saveable.get());
284 // else: do nothing if the events are already in memory.
285 return data;
286 }
287}
288
289//-----------------------------------------------------------------------------------------------
294TMDE(void MDBox)::releaseEvents() {
295 // Data vector is no longer busy.
296 if (m_Saveable)
297 m_Saveable->setBusy(false);
298}
299
307TMDE(void MDBox)::getEventsData(std::vector<coord_t> &coordTable, size_t &nColumns) const {
308 double signal, errorSq;
309 MDE::eventsToData(this->data, coordTable, nColumns, signal, errorSq);
310 this->m_signal = static_cast<signal_t>(signal);
311 this->m_errorSquared = static_cast<signal_t>(errorSq);
312
313#ifdef MDBOX_TRACK_CENTROID
314 this->calculateCentroid(this->m_centroid);
315#endif
316}
323TMDE(void MDBox)::setEventsData(const std::vector<coord_t> &coordTable) { MDE::dataToEvents(coordTable, this->data); }
324
325//-----------------------------------------------------------------------------------------------
328TMDE(std::vector<MDE> *MDBox)::getEventsCopy() {
329 if (m_Saveable) {
330 }
331 auto out = new std::vector<MDE>();
332 // Make the copy
333 out->insert(out->begin(), data.begin(), data.end());
334 return out;
335}
336
337//-----------------------------------------------------------------------------------------------
350TMDE(void MDBox)::refreshCache(Kernel::ThreadScheduler * /*ts*/) {
351
352 // Use the cached value if it is on disk
353
354 // Convert floats to doubles to preserve precision when adding them.
355 double signalSum{0};
356 double errorSum{0};
357
358 if (m_Saveable) {
359 if (m_Saveable->wasSaved()) // There are possible problems with disk
360 // buffered events, as saving calculates
361 // averages and these averages has to be added
362 // to memory contents
363 {
364 if (!m_Saveable->isLoaded()) // events were saved, averages calculated
365 // and stored
366 {
367 // the partial data were not loaded from HDD but their averages should
368 // be calculated when loaded. Add them
369 signalSum = this->m_signal;
370 errorSum = this->m_errorSquared;
371 }
372 }
373 }
374
375 // calculate all averages from memory
376 signalSum = std::accumulate(data.cbegin(), data.cend(), signalSum,
377 [](const double &sum, const MDE &event) { return sum + event.getSignal(); });
378 errorSum = std::accumulate(data.cbegin(), data.cend(), errorSum,
379 [](const double &sum, const MDE &event) { return sum + event.getErrorSquared(); });
380
381 this->m_signal = signal_t(signalSum);
382 this->m_errorSquared = signal_t(errorSum);
383#ifdef MDBOX_TRACK_CENTROID
384 this->calculateCentroid(this->m_centroid);
385#endif
386
388 this->m_totalWeight = static_cast<double>(this->getNPoints());
389}
390
393TMDE(bool MDBox)::isDataAdded() const {
394 if (m_Saveable) {
395 if (m_Saveable->isLoaded())
396 return data.size() != m_Saveable->getFileSize();
397 }
398 return (!data.empty());
399}
400
401//-----------------------------------------------------------------------------------------------
405TMDE(void MDBox)::calculateCentroid(coord_t *centroid) const {
406 std::fill_n(centroid, nd, 0.0f);
407
408 // Signal was calculated before (when adding)
409 // Keep 0.0 if the signal is null. This avoids dividing by 0.0
410 if (this->m_signal == 0)
411 return;
412
413 for (const MDE &Evnt : data) {
414 double signal = Evnt.getSignal();
415 for (size_t d = 0; d < nd; d++) {
416 // Total up the coordinate weighted by the signal.
417 centroid[d] += Evnt.getCenter(d) * static_cast<coord_t>(signal);
418 }
419 }
420
421 // Normalize by the total signal
422 const coord_t reciprocal = 1.0f / static_cast<coord_t>(this->m_signal);
423 for (size_t d = 0; d < nd; ++d) {
424 centroid[d] *= reciprocal;
425 }
426}
427
428//-----------------------------------------------------------------------------------------------
433TMDE(void MDBox)::calculateCentroid(coord_t *centroid, const int expInfoIndex) const {
434
435 std::fill_n(centroid, nd, 0.0f);
436
437 // Signal was calculated before (when adding)
438 // Keep 0.0 if the signal is null. This avoids dividing by 0.0
439 if (this->m_signal == 0)
440 return;
441
442 for (const MDE &Evnt : data) {
443 coord_t signal = Evnt.getSignal();
444 if (Evnt.getExpInfoIndex() == expInfoIndex) {
445 for (size_t d = 0; d < nd; d++) {
446 // Total up the coordinate weighted by the signal.
447 centroid[d] += Evnt.getCenter(d) * signal;
448 }
449 }
450 }
451
452 // Normalize by the total signal
453 const coord_t reciprocal = 1.0f / static_cast<coord_t>(this->m_signal);
454 for (size_t d = 0; d < nd; ++d) {
455 centroid[d] *= reciprocal;
456 }
457}
458
459//-----------------------------------------------------------------------------------------------
465TMDE(void MDBox)::calculateDimensionStats(MDDimensionStats *stats) const {
466 for (const MDE &Evnt : data) {
467 for (size_t d = 0; d < nd; d++) {
468 stats[d].addPoint(Evnt.getCenter(d));
469 }
470 }
471}
472
473//-----------------------------------------------------------------------------------------------
479TMDE(void MDBox)::centerpointBin(MDBin<MDE, nd> &bin, bool *fullyContained) const {
480 if (fullyContained) {
481 // For MDSplitBox, check if we've already found that all dimensions are
482 // fully contained
483 size_t d;
484 for (d = 0; d < nd; ++d) {
485 if (!fullyContained[d])
486 break;
487 }
488 if (d == nd) {
489 // All dimensions are fully contained, so just return the cached total
490 // signal instead of counting.
491 bin.m_signal += static_cast<signal_t>(this->m_signal);
492 bin.m_errorSquared += static_cast<signal_t>(this->m_errorSquared);
493 return;
494 }
495 }
496
497 // If the box is cached to disk, you need to retrieve it
498 const std::vector<MDE> &events = this->getConstEvents();
499 // For each MDLeanEvent
500 for (const auto &evnt : events) {
501 size_t d;
502 // Go through each dimension
503 for (d = 0; d < nd; ++d) {
504 // Check that the value is within the bounds given. (Rotation is for
505 // later)
506 coord_t x = evnt.getCenter(d);
507 if (x < bin.m_min[d] || x >= bin.m_max[d])
508 break;
509 }
510 // If the loop reached the end, then it was all within bounds.
511 if (d == nd) {
512 // Accumulate error and signal (as doubles, to preserve precision)
513 bin.m_signal += static_cast<signal_t>(evnt.getSignal());
514 bin.m_errorSquared += static_cast<signal_t>(evnt.getErrorSquared());
515 }
516 }
517 // it is constant access, so no saving or fiddling with the buffer is needed.
518 // Events just can be dropped if necessary
519 // releaseEvents
520 if (m_Saveable)
521 m_Saveable->setBusy(false);
522}
523
524//-----------------------------------------------------------------------------------------------
535TMDE(void MDBox)::generalBin(MDBin<MDE, nd> &bin, Mantid::Geometry::MDImplicitFunction &function) const {
536 UNUSED_ARG(bin);
537
538 // For each MDLeanEvent
539 for (const auto &event : data) {
540 if (function.isPointContained(event.getCenter())) // HACK
541 {
542 // Accumulate error and signal
543 bin.m_signal += static_cast<signal_t>(event.getSignal());
544 bin.m_errorSquared += static_cast<signal_t>(event.getErrorSquared());
545 }
546 }
547}
548
564TMDE(void MDBox)::integrateSphere(Mantid::API::CoordTransform &radiusTransform, const coord_t radiusSquared,
565 signal_t &integratedSignal, signal_t &errorSquared, const coord_t innerRadiusSquared,
566 const bool useOnePercentBackgroundCorrection) const {
567 // If the box is cached to disk, you need to retrieve it
568 const std::vector<MDE> &events = this->getConstEvents();
569 if (innerRadiusSquared == 0.0) {
570 // For each MDLeanEvent
571 for (const auto &it : events) {
572 coord_t out[nd];
573 radiusTransform.apply(it.getCenter(), out);
574 if (out[0] < radiusSquared) {
575 integratedSignal += static_cast<signal_t>(it.getSignal());
576 errorSquared += static_cast<signal_t>(it.getErrorSquared());
577 }
578 }
579 } else {
580 // For each MDLeanEvent
581 using valAndErrorPair = std::pair<signal_t, signal_t>;
582 std::vector<valAndErrorPair> vals;
583 for (const auto &it : events) {
584 coord_t out[nd];
585 radiusTransform.apply(it.getCenter(), out);
586 if (out[0] < radiusSquared && out[0] > innerRadiusSquared) {
587 const auto signal = static_cast<signal_t>(it.getSignal());
588 const auto errSquared = static_cast<signal_t>(it.getErrorSquared());
589 vals.emplace_back(signal, errSquared);
590 }
591 }
592 // Sort based on signal values
593 std::sort(vals.begin(), vals.end(),
594 [](const valAndErrorPair &a, const valAndErrorPair &b) { return a.first < b.first; });
595
596 // Remove top 1% of background
597 const size_t endIndex =
598 useOnePercentBackgroundCorrection ? static_cast<size_t>(0.99 * static_cast<double>(vals.size())) : vals.size();
599
600 for (size_t k = 0; k < endIndex; k++) {
601 integratedSignal += vals[k].first;
602 errorSquared += vals[k].second;
603 }
604 }
605 // it is constant access, so no saving or fiddling with the buffer is needed.
606 // Events just can be dropped if necessary
607 // m_Saveable->releaseEvents();
608 if (m_Saveable) {
609 m_Saveable->setBusy(false);
610 }
611}
612
628TMDE(void MDBox)::integrateCylinder(Mantid::API::CoordTransform &radiusTransform, const coord_t radius,
629 const coord_t length, signal_t &signal, signal_t &errorSquared,
630 std::vector<signal_t> &signal_fit) const {
631 // If the box is cached to disk, you need to retrieve it
632 const std::vector<MDE> &events = this->getConstEvents();
633 size_t numSteps = signal_fit.size();
634 double deltaQ = length / static_cast<double>(numSteps - 1);
635
636 // For each MDLeanEvent
637 for (const auto &evnt : events) {
638 coord_t out[2]; // radius and length of cylinder
639 radiusTransform.apply(evnt.getCenter(), out);
640 if (out[0] < radius && std::fabs(out[1]) < 0.5 * length + deltaQ) {
641 // add event to appropriate y channel
642 size_t xchannel = static_cast<size_t>(std::floor(out[1] / deltaQ)) + numSteps / 2;
643 if (xchannel < numSteps)
644 signal_fit[xchannel] += static_cast<signal_t>(evnt.getSignal());
645
646 signal += static_cast<signal_t>(evnt.getSignal());
647 errorSquared += static_cast<signal_t>(evnt.getErrorSquared());
648 }
649 }
650 // it is constant access, so no saving or fiddling with the buffer is needed.
651 // Events just can be dropped if necessary
652 // m_Saveable->releaseEvents();
653 if (m_Saveable) {
654 m_Saveable->setBusy(false);
655 }
656}
657
658//-----------------------------------------------------------------------------------------------
661TMDE(coord_t *MDBox)::getCentroid() const { return this->m_centroid; }
662
663//-----------------------------------------------------------------------------------------------
674TMDE(void MDBox)::centroidSphere(Mantid::API::CoordTransform &radiusTransform, const coord_t radiusSquared,
675 coord_t *centroid, signal_t &signal) const {
676 // If the box is cached to disk, you need to retrieve it
677 const std::vector<MDE> &events = this->getConstEvents();
678
679 // For each MDLeanEvent
680 for (const auto &evnt : events) {
681 coord_t out[nd];
682 radiusTransform.apply(evnt.getCenter(), out);
683 if (out[0] < radiusSquared) {
684 coord_t eventSignal = static_cast<coord_t>(evnt.getSignal());
685 signal += eventSignal;
686 for (size_t d = 0; d < nd; d++)
687 centroid[d] += evnt.getCenter(d) * eventSignal;
688 }
689 }
690 // it is constant access, so no saving or fiddling with the buffer is needed.
691 // Events just can be dropped if necessary
692 if (m_Saveable)
693 m_Saveable->setBusy(false);
694}
695
696//-----------------------------------------------------------------------------------------------
703TMDE(void MDBox)::transformDimensions(std::vector<double> &scaling, std::vector<double> &offset) {
705 this->calculateCentroid(this->m_centroid);
706 std::vector<MDE> &events = this->getEvents();
707 for (auto &evnt : events) {
708 coord_t *center = evnt.getCenterNonConst();
709 for (size_t d = 0; d < nd; d++)
710 center[d] = (center[d] * static_cast<coord_t>(scaling[d])) + static_cast<coord_t>(offset[d]);
711 }
712 if (m_Saveable)
713 m_Saveable->setBusy(false);
714}
715
717TMDE(void MDBox)::mask() {
718 this->setSignal(API::MDMaskValue);
719 this->setErrorSquared(API::MDMaskValue);
720 m_bIsMasked = true;
721}
722
724TMDE(void MDBox)::unmask() { m_bIsMasked = false; }
725//------------------------------------------------------------------------------------------------------------------------------------------------------------
726
731TMDE(size_t MDBox)::buildAndAddEvents(const std::vector<signal_t> &sigErrSq, const std::vector<coord_t> &Coord,
732 const std::vector<uint16_t> &expInfoIndex,
733 const std::vector<uint16_t> &goniometerIndex,
734 const std::vector<uint32_t> &detectorId) {
735
736 size_t nEvents = sigErrSq.size() / 2;
737 size_t nExisiting = data.size();
738 data.reserve(nExisiting + nEvents);
739 std::lock_guard<std::mutex> _lock(this->m_dataMutex);
740 IF<MDE, nd>::EXEC(this->data, sigErrSq, Coord, expInfoIndex, goniometerIndex, detectorId, nEvents);
741
742 return 0;
743}
744
754TMDE(void MDBox)::buildAndAddEvent(const signal_t Signal, const signal_t errorSq, const std::vector<coord_t> &point,
755 uint16_t expInfoIndex, uint16_t goniometerIndex, uint32_t detectorId) {
756 std::lock_guard<std::mutex> _lock(this->m_dataMutex);
757 this->data.emplace_back(
758 IF<MDE, nd>::BUILD_EVENT(Signal, errorSq, &point[0], expInfoIndex, goniometerIndex, detectorId));
759}
760
761//-----------------------------------------------------------------------------------------------
774TMDE(void MDBox)::buildAndAddEventUnsafe(const signal_t Signal, const signal_t errorSq,
775 const std::vector<coord_t> &point, uint16_t expInfoIndex,
776 uint16_t goniometerIndex, uint32_t detectorId) {
777 this->data.emplace_back(
778 IF<MDE, nd>::BUILD_EVENT(Signal, errorSq, &point[0], expInfoIndex, goniometerIndex, detectorId));
779}
780
781//-----------------------------------------------------------------------------------------------
786TMDE(size_t MDBox)::addEvent(const MDE &Evnt) {
787 std::lock_guard<std::mutex> _lock(this->m_dataMutex);
788 this->data.emplace_back(Evnt);
789 return 1;
790}
791
792//-----------------------------------------------------------------------------------------------
800TMDE(size_t MDBox)::addEventUnsafe(const MDE &Evnt) {
801 this->data.emplace_back(Evnt);
802 return 1;
803}
804
805//-----------------------------------------------------------------------------------------------
812TMDE(size_t MDBox)::addEvents(const std::vector<MDE> &events) {
813 std::lock_guard<std::mutex> _lock(this->m_dataMutex);
814 // Copy all the events
815 this->data.insert(this->data.end(), events.cbegin(), events.cend());
816 return 0;
817}
818
827TMDE(void MDBox)::setFileBacked(const uint64_t fileLocation, const size_t fileSize, const bool markSaved) {
828 if (!m_Saveable)
829 m_Saveable = std::make_unique<MDBoxSaveable>(this);
830
831 m_Saveable->setFilePosition(fileLocation, fileSize, markSaved);
832}
835TMDE(void MDBox)::setFileBacked() {
836 if (!m_Saveable)
837 this->setFileBacked(UNDEF_UINT64, this->getDataInMemorySize(), false);
838}
839
847TMDE(void MDBox)::saveAt(API::IBoxControllerIO *const FileSaver, uint64_t position) const {
848 if (data.empty())
849 return;
850
851 if (!FileSaver)
852 throw(std::invalid_argument(" Needs defined file saver to save data to it"));
853 if (!FileSaver->isOpened())
854 throw(std::invalid_argument(" The data file has to be opened to use box SaveAt function"));
855
856 std::vector<coord_t> TabledData;
857 size_t nDataColumns;
858 double totalSignal, totalErrSq;
859
860 MDE::eventsToData(this->data, TabledData, nDataColumns, totalSignal, totalErrSq);
861
862 this->m_signal = static_cast<signal_t>(totalSignal);
863 this->m_errorSquared = static_cast<signal_t>(totalErrSq);
864#ifdef MDBOX_TRACK_CENTROID
865 this->calculateCentroid(this->m_centroid);
866#endif
867
868 FileSaver->saveBlock(TabledData, position);
869}
870
876TMDE(void MDBox)::reserveMemoryForLoad(uint64_t size) { this->data.reserve(size); }
877
888TMDE(void MDBox)::loadAndAddFrom(API::IBoxControllerIO *const FileSaver, uint64_t filePosition, size_t nEvents,
889 std::vector<coord_t> &tableDataTemp) {
890 if (nEvents == 0)
891 return;
892
893 if (!FileSaver)
894 throw(std::invalid_argument(" Needs defined file saver to load data using it"));
895 if (!FileSaver->isOpened())
896 throw(std::invalid_argument(" The data file has to be opened to use box loadAndAddFrom function"));
897
898 std::lock_guard<std::mutex> _lock(this->m_dataMutex);
899
900 tableDataTemp.clear();
901 FileSaver->loadBlock(tableDataTemp, filePosition, nEvents);
902
903 // convert data to events appending new events to existing
904 MDE::dataToEvents(tableDataTemp, data, false);
905}
906
916TMDE(void MDBox)::loadAndAddFrom(API::IBoxControllerIO *const FileSaver, uint64_t filePosition, size_t nEvents) {
917 if (nEvents == 0)
918 return;
919
920 if (!FileSaver)
921 throw(std::invalid_argument(" Needs defined file saver to load data using it"));
922 if (!FileSaver->isOpened())
923 throw(std::invalid_argument(" The data file has to be opened to use box loadAndAddFrom function"));
924
925 std::lock_guard<std::mutex> _lock(this->m_dataMutex);
926
927 m_tableData.clear();
928 FileSaver->loadBlock(m_tableData, filePosition, nEvents);
929
930 // convert data to events appending new events to existing
931 MDE::dataToEvents(m_tableData, data, false);
932}
943TMDE(void MDBox)::clearFileBacked(bool loadDiskBackedData) {
944 if (m_Saveable) {
945 if (loadDiskBackedData)
946 m_Saveable->load();
947 // tell disk buffer that there are no point of tracking this box any more.
948 this->m_BoxController->getFileIO()->objectDeleted(m_Saveable.get());
949 m_Saveable = nullptr;
950 }
951}
952
953} // namespace DataObjects
954
955} // namespace Mantid
double position
Definition GetAllEi.cpp:154
#define UNDEF_UINT64
Definition MDTypes.h:63
#define UNDEF_SIZET
Definition MDTypes.h:61
#define TMDE(decl)
Macro TMDE to make declaring template functions faster.
Definition MDTypes.h:52
#define UNUSED_ARG(x)
Function arguments are sometimes unused in certain implmentations but are required for documentation ...
Definition System.h:48
This class is used by MDBox and MDGridBox in order to intelligently determine optimal behavior.
bool isFileBacked() const
Returns if current box controller is file backed.
Unique SingleValueParameter Declaration for InputNDimensions.
The header describes interface to IO Operations perfomed by the box controller May be replaced by a b...
MDBin : Class describing a single bin in a dense, Multidimensional histogram.
Definition MDBin.h:32
Templated super-class of a multi-dimensional event "box".
Definition MDBoxBase.h:50
void calcCaches(const EventIterator &begin, const EventIterator &end)
Calculates caches if the events are known.
Definition MDBoxBase.h:368
virtual size_t addEventsUnsafe(const std::vector< MDE > &events)
Add all of the events contained in a vector, with:
Mantid::API::BoxController *const m_BoxController
The box splitting controller, shared with all boxes in the hierarchy.
Definition MDBoxBase.h:336
Templated class for a multi-dimensional event "box".
Definition MDBox.h:45
std::vector< MDE > vec_t
Typedef for a vector of the conatined events.
Definition MDBox.h:220
MDBox(Mantid::API::BoxController_sptr &splitter, const uint32_t depth=0, const size_t nBoxEvents=UNDEF_SIZET, const size_t boxID=UNDEF_SIZET)
Convenience Constructor/default constructor for accepting shared pointer.
Definition MDBox.hxx:44
std::vector< MDE > data
Vector of MDEvent's, in no particular order.
Definition MDBox.h:201
typename std::vector< MDE >::const_iterator EventIterator
Definition MDBox.h:60
void setFileBacked() override
Make this box file-backed but its place on the file is not identified yet.
Definition MDBox.hxx:835
A simple class holding some statistics on the distribution of events in a particular dimension.
Simple class that holds the extents (min/max) of a given dimension in a MD workspace or MDBox.
An "ImplicitFunction" defining a hyper-cuboid-shaped region in N dimensions.
An interface for objects that can be cached or saved to disk.
Definition ISaveable.h:28
The ThreadScheduler object defines how tasks are allocated to threads and in what order.
std::shared_ptr< BoxController > BoxController_sptr
Shared ptr to BoxController.
Helper class which provides the Collimation Length for SANS instruments.
float coord_t
Typedef for the data type to use for coordinate axes in MD objects such as MDBox, MDEventWorkspace,...
Definition MDTypes.h:27
double signal_t
Typedef for the signal recorded in a MDBox, etc.
Definition MDTypes.h:36
STL namespace.