14#include <boost/math/special_functions/round.hpp>
19namespace DataObjects {
26 if (this->m_BoxController)
30 if (this->m_BoxController->isFileBacked()) {
31 this->m_BoxController->getFileIO()->objectDeleted(m_Saveable.get());
45 :
MDBoxBase<MDE, nd>(splitter.get(), depth, boxID), m_Saveable(nullptr), m_bIsMasked(false) {
46 initMDBox(nBoxEvents);
58 :
MDBoxBase<MDE, nd>(splitter, depth, boxID), m_Saveable(nullptr), m_bIsMasked(false) {
59 initMDBox(nBoxEvents);
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);
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);
102template <
typename MDE,
size_t nd>
106 :
MDBoxBase<MDE, nd>(bc, depth, 0, extentsVector), m_Saveable(nullptr), data(
std::vector<MDE>(begin, end)),
115 if (this->m_BoxController->getNDims() != nd)
116 throw std::invalid_argument(
"MDBox::ctor(): controller passed has the wrong number of dimensions.");
119 data.reserve(nBoxEvents);
121 if (this->m_BoxController->isFileBacked())
122 this->setFileBacked();
132 :
MDBoxBase<MDE, nd>(other, otherBC), m_Saveable(nullptr), data(other.data), m_bIsMasked(other.m_bIsMasked) {
135 if (otherBC->isFileBacked())
136 this->setFileBacked();
151 this->m_BoxController->getFileIO()->objectDeleted(m_Saveable.get());
154 this->m_signal = 0.0;
155 this->m_errorSquared = 0.0;
157 this->clearDataFromMemory();
172 m_Saveable->setLoaded(
false);
173 m_Saveable->setBusy(
false);
174 m_Saveable->clearDataChanged();
190 boxes.emplace_back(
this);
193 boxes.emplace_back(
this);
200 boxes.emplace_back(
this);
204 boxes.emplace_back(
this);
216 outBoxes.emplace_back(
this);
229 if (m_Saveable->wasSaved()) {
230 if (m_Saveable->isLoaded())
233 return m_Saveable->getFileSize() + data.size();
247 if (m_Saveable->wasSaved()) {
251 m_Saveable->setBusy(
true);
253 m_Saveable->setDataChanged();
257 this->m_BoxController->getFileIO()->toWrite(m_Saveable.get());
263TMDE(
const std::vector<MDE> &
MDBox)::getEvents() const { return getConstEvents(); }
269TMDE(
const std::vector<MDE> &
MDBox)::getConstEvents() const {
273 if (m_Saveable->wasSaved()) {
279 m_Saveable->setBusy(
true);
283 this->m_BoxController->getFileIO()->toWrite(m_Saveable.get());
297 m_Saveable->setBusy(
false);
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);
313#ifdef MDBOX_TRACK_CENTROID
314 this->calculateCentroid(this->m_centroid);
323TMDE(
void MDBox)::setEventsData(const
std::vector<
coord_t> &coordTable) { MDE::dataToEvents(coordTable, this->data); }
331 auto out =
new std::vector<MDE>();
333 out->insert(out->begin(), data.begin(), data.end());
359 if (m_Saveable->wasSaved())
364 if (!m_Saveable->isLoaded())
369 signalSum = this->m_signal;
370 errorSum = this->m_errorSquared;
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(); });
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);
388 this->m_totalWeight =
static_cast<double>(this->getNPoints());
395 if (m_Saveable->isLoaded())
396 return data.size() != m_Saveable->getFileSize();
398 return (!data.empty());
406 std::fill_n(centroid, nd, 0.0f);
410 if (this->m_signal == 0)
413 for (
const MDE &Evnt : data) {
414 double signal = Evnt.getSignal();
415 for (
size_t d = 0;
d < nd;
d++) {
417 centroid[
d] += Evnt.getCenter(
d) *
static_cast<coord_t>(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;
435 std::fill_n(centroid, nd, 0.0f);
439 if (this->m_signal == 0)
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++) {
447 centroid[
d] += Evnt.getCenter(
d) * 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;
466 for (const MDE &Evnt : data) {
467 for (
size_t d = 0;
d < nd;
d++) {
468 stats[
d].addPoint(Evnt.getCenter(
d));
479TMDE(
void MDBox)::centerpointBin(
MDBin<MDE, nd> &bin, bool *fullyContained) const {
480 if (fullyContained) {
484 for (
d = 0;
d < nd; ++
d) {
485 if (!fullyContained[
d])
491 bin.m_signal +=
static_cast<signal_t>(this->m_signal);
492 bin.m_errorSquared +=
static_cast<signal_t>(this->m_errorSquared);
498 const std::vector<MDE> &events = this->getConstEvents();
500 for (
const auto &evnt : events) {
503 for (d = 0;
d < nd; ++
d) {
507 if (x < bin.m_min[d] || x >= bin.m_max[d])
513 bin.m_signal +=
static_cast<signal_t>(evnt.getSignal());
514 bin.m_errorSquared +=
static_cast<signal_t>(evnt.getErrorSquared());
521 m_Saveable->setBusy(
false);
539 for (
const auto &event : data) {
540 if (function.isPointContained(event.getCenter()))
543 bin.m_signal +=
static_cast<signal_t>(
event.getSignal());
544 bin.m_errorSquared +=
static_cast<signal_t>(
event.getErrorSquared());
566 const bool useOnePercentBackgroundCorrection) const {
568 const
std::vector<MDE> &events = this->getConstEvents();
569 if (innerRadiusSquared == 0.0) {
571 for (
const auto &it : events) {
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());
581 using valAndErrorPair = std::pair<signal_t, signal_t>;
582 std::vector<valAndErrorPair> vals;
583 for (
const auto &it : events) {
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);
593 std::sort(vals.begin(), vals.end(),
594 [](
const valAndErrorPair &a,
const valAndErrorPair &b) { return a.first < b.first; });
597 const size_t endIndex =
598 useOnePercentBackgroundCorrection ?
static_cast<size_t>(0.99 *
static_cast<double>(vals.size())) : vals.size();
600 for (
size_t k = 0; k < endIndex; k++) {
601 integratedSignal += vals[k].first;
602 errorSquared += vals[k].second;
609 m_Saveable->setBusy(
false);
632 const
std::vector<MDE> &events = this->getConstEvents();
633 size_t numSteps = signal_fit.size();
634 double deltaQ = length /
static_cast<double>(numSteps - 1);
637 for (
const auto &evnt : events) {
639 radiusTransform.apply(evnt.getCenter(), out);
640 if (out[0] < radius && std::fabs(out[1]) < 0.5 * length + deltaQ) {
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());
646 signal +=
static_cast<signal_t>(evnt.getSignal());
647 errorSquared +=
static_cast<signal_t>(evnt.getErrorSquared());
654 m_Saveable->setBusy(
false);
677 const
std::vector<MDE> &events = this->getConstEvents();
680 for (
const auto &evnt : events) {
682 radiusTransform.apply(evnt.getCenter(), out);
683 if (out[0] < radiusSquared) {
685 signal += eventSignal;
686 for (
size_t d = 0;
d < nd;
d++)
687 centroid[
d] += evnt.getCenter(
d) * eventSignal;
693 m_Saveable->setBusy(
false);
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]);
713 m_Saveable->setBusy(
false);
718 this->setSignal(API::MDMaskValue);
719 this->setErrorSquared(API::MDMaskValue);
732 const
std::vector<uint16_t> &expInfoIndex,
733 const
std::vector<uint16_t> &goniometerIndex,
734 const
std::vector<uint32_t> &detectorId) {
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);
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(
775 const
std::vector<
coord_t> &point, uint16_t expInfoIndex,
776 uint16_t goniometerIndex, uint32_t detectorId) {
777 this->data.emplace_back(
787 std::lock_guard<std::mutex> _lock(this->m_dataMutex);
788 this->data.emplace_back(Evnt);
801 this->data.emplace_back(Evnt);
813 std::lock_guard<std::mutex> _lock(this->m_dataMutex);
815 this->data.insert(this->data.end(), events.cbegin(), events.cend());
827TMDE(
void MDBox)::setFileBacked(const uint64_t fileLocation, const size_t fileSize, const bool markSaved) {
829 m_Saveable = std::make_unique<MDBoxSaveable>(
this);
831 m_Saveable->setFilePosition(fileLocation, fileSize, markSaved);
837 this->setFileBacked(
UNDEF_UINT64, this->getDataInMemorySize(),
false);
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"));
856 std::vector<coord_t> TabledData;
858 double totalSignal, totalErrSq;
860 MDE::eventsToData(this->data, TabledData, nDataColumns, totalSignal, totalErrSq);
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);
868 FileSaver->saveBlock(TabledData,
position);
876TMDE(
void MDBox)::reserveMemoryForLoad(uint64_t size) { this->data.reserve(size); }
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"));
898 std::lock_guard<std::mutex> _lock(this->m_dataMutex);
900 tableDataTemp.clear();
901 FileSaver->loadBlock(tableDataTemp, filePosition, nEvents);
904 MDE::dataToEvents(tableDataTemp, data,
false);
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"));
925 std::lock_guard<std::mutex> _lock(this->m_dataMutex);
928 FileSaver->loadBlock(m_tableData, filePosition, nEvents);
931 MDE::dataToEvents(m_tableData, data,
false);
943TMDE(
void MDBox)::clearFileBacked(bool loadDiskBackedData) {
945 if (loadDiskBackedData)
948 this->m_BoxController->getFileIO()->objectDeleted(m_Saveable.get());
949 m_Saveable =
nullptr;
#define TMDE(decl)
Macro TMDE to make declaring template functions faster.
#define UNUSED_ARG(x)
Function arguments are sometimes unused in certain implmentations but are required for documentation ...
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.
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.
Templated super-class of a multi-dimensional event "box".
void calcCaches(const EventIterator &begin, const EventIterator &end)
Calculates caches if the events are known.
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.
Templated class for a multi-dimensional event "box".
std::vector< MDE > vec_t
Typedef for a vector of the conatined events.
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.
std::vector< MDE > data
Vector of MDEvent's, in no particular order.
typename std::vector< MDE >::const_iterator EventIterator
void setFileBacked() override
Make this box file-backed but its place on the file is not identified yet.
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.
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,...
double signal_t
Typedef for the signal recorded in a MDBox, etc.