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);
217 if (m_Saveable->wasSaved()) {
218 if (m_Saveable->isLoaded())
221 return m_Saveable->getFileSize() + data.size();
235 if (m_Saveable->wasSaved()) {
239 m_Saveable->setBusy(
true);
241 m_Saveable->setDataChanged();
245 this->m_BoxController->getFileIO()->toWrite(m_Saveable.get());
251TMDE(
const std::vector<MDE> &
MDBox)::getEvents() const { return getConstEvents(); }
257TMDE(
const std::vector<MDE> &
MDBox)::getConstEvents() const {
261 if (m_Saveable->wasSaved()) {
267 m_Saveable->setBusy(
true);
271 this->m_BoxController->getFileIO()->toWrite(m_Saveable.get());
285 m_Saveable->setBusy(
false);
296 double signal, errorSq;
297 MDE::eventsToData(this->data, coordTable, nColumns, signal, errorSq);
298 this->m_signal =
static_cast<signal_t>(signal);
299 this->m_errorSquared =
static_cast<signal_t>(errorSq);
301#ifdef MDBOX_TRACK_CENTROID
302 this->calculateCentroid(this->m_centroid);
311TMDE(
void MDBox)::setEventsData(const
std::vector<
coord_t> &coordTable) { MDE::dataToEvents(coordTable, this->data); }
319 auto out =
new std::vector<MDE>();
321 out->insert(out->begin(), data.begin(), data.end());
347 if (m_Saveable->wasSaved())
352 if (!m_Saveable->isLoaded())
357 signalSum = this->m_signal;
358 errorSum = this->m_errorSquared;
364 signalSum = std::accumulate(data.cbegin(), data.cend(), signalSum,
365 [](
const double &sum,
const MDE &event) { return sum + event.getSignal(); });
366 errorSum = std::accumulate(data.cbegin(), data.cend(), errorSum,
367 [](
const double &sum,
const MDE &event) { return sum + event.getErrorSquared(); });
369 this->m_signal =
signal_t(signalSum);
370 this->m_errorSquared =
signal_t(errorSum);
371#ifdef MDBOX_TRACK_CENTROID
372 this->calculateCentroid(this->m_centroid);
376 this->m_totalWeight =
static_cast<double>(this->getNPoints());
383 if (m_Saveable->isLoaded())
384 return data.size() != m_Saveable->getFileSize();
386 return (!data.empty());
394 std::fill_n(centroid, nd, 0.0f);
398 if (this->m_signal == 0)
401 for (
const MDE &Evnt : data) {
402 double signal = Evnt.getSignal();
403 for (
size_t d = 0;
d < nd;
d++) {
405 centroid[
d] += Evnt.getCenter(
d) *
static_cast<coord_t>(signal);
410 const coord_t reciprocal = 1.0f /
static_cast<coord_t>(this->m_signal);
411 for (
size_t d = 0;
d < nd; ++
d) {
412 centroid[
d] *= reciprocal;
423 std::fill_n(centroid, nd, 0.0f);
427 if (this->m_signal == 0)
430 for (
const MDE &Evnt : data) {
431 coord_t signal = Evnt.getSignal();
432 if (Evnt.getExpInfoIndex() == expInfoIndex) {
433 for (
size_t d = 0;
d < nd;
d++) {
435 centroid[
d] += Evnt.getCenter(
d) * signal;
441 const coord_t reciprocal = 1.0f /
static_cast<coord_t>(this->m_signal);
442 for (
size_t d = 0;
d < nd; ++
d) {
443 centroid[
d] *= reciprocal;
454 for (const MDE &Evnt : data) {
455 for (
size_t d = 0;
d < nd;
d++) {
456 stats[
d].addPoint(Evnt.getCenter(
d));
478 const bool useOnePercentBackgroundCorrection) const {
480 const
std::vector<MDE> &events = this->getConstEvents();
481 if (innerRadiusSquared == 0.0) {
483 for (
const auto &it : events) {
485 radiusTransform.apply(it.getCenter(), out);
486 if (out[0] < radiusSquared) {
487 integratedSignal +=
static_cast<signal_t>(it.getSignal());
488 errorSquared +=
static_cast<signal_t>(it.getErrorSquared());
493 using valAndErrorPair = std::pair<signal_t, signal_t>;
494 std::vector<valAndErrorPair> vals;
495 for (
const auto &it : events) {
497 radiusTransform.apply(it.getCenter(), out);
498 if (out[0] < radiusSquared && out[0] > innerRadiusSquared) {
499 const auto signal =
static_cast<signal_t>(it.getSignal());
500 const auto errSquared =
static_cast<signal_t>(it.getErrorSquared());
501 vals.emplace_back(signal, errSquared);
505 std::sort(vals.begin(), vals.end(),
506 [](
const valAndErrorPair &a,
const valAndErrorPair &b) { return a.first < b.first; });
509 const size_t endIndex =
510 useOnePercentBackgroundCorrection ?
static_cast<size_t>(0.99 *
static_cast<double>(vals.size())) : vals.size();
512 for (
size_t k = 0; k < endIndex; k++) {
513 integratedSignal += vals[k].first;
514 errorSquared += vals[k].second;
521 m_Saveable->setBusy(
false);
544 const
std::vector<MDE> &events = this->getConstEvents();
545 size_t numSteps = signal_fit.size();
546 double deltaQ = length /
static_cast<double>(numSteps - 1);
549 for (
const auto &evnt : events) {
551 radiusTransform.apply(evnt.getCenter(), out);
552 if (out[0] < radius && std::fabs(out[1]) < 0.5 * length + deltaQ) {
554 size_t xchannel =
static_cast<size_t>(std::floor(out[1] / deltaQ)) + numSteps / 2;
555 if (xchannel < numSteps)
556 signal_fit[xchannel] +=
static_cast<signal_t>(evnt.getSignal());
558 signal +=
static_cast<signal_t>(evnt.getSignal());
559 errorSquared +=
static_cast<signal_t>(evnt.getErrorSquared());
566 m_Saveable->setBusy(
false);
589 const
std::vector<MDE> &events = this->getConstEvents();
592 for (
const auto &evnt : events) {
594 radiusTransform.apply(evnt.getCenter(), out);
595 if (out[0] < radiusSquared) {
597 signal += eventSignal;
598 for (
size_t d = 0;
d < nd;
d++)
599 centroid[
d] += evnt.getCenter(
d) * eventSignal;
605 m_Saveable->setBusy(
false);
615TMDE(
void MDBox)::transformDimensions(
std::vector<double> &scaling,
std::vector<double> &offset) {
617 this->calculateCentroid(this->m_centroid);
618 std::vector<MDE> &events = this->getEvents();
619 for (
auto &evnt : events) {
620 coord_t *center = evnt.getCenterNonConst();
621 for (
size_t d = 0;
d < nd;
d++)
622 center[
d] = (center[
d] *
static_cast<coord_t>(scaling[
d])) +
static_cast<coord_t>(offset[
d]);
625 m_Saveable->setBusy(
false);
630 this->setSignal(API::MDMaskValue);
631 this->setErrorSquared(API::MDMaskValue);
644 const
std::vector<uint16_t> &expInfoIndex,
645 const
std::vector<uint16_t> &goniometerIndex,
646 const
std::vector<uint32_t> &detectorId) {
648 size_t nEvents = sigErrSq.size() / 2;
649 size_t nExisiting = data.size();
650 data.reserve(nExisiting + nEvents);
651 std::lock_guard<std::mutex> _lock(this->m_dataMutex);
652 IF<MDE, nd>::EXEC(this->data, sigErrSq, Coord, expInfoIndex, goniometerIndex, detectorId, nEvents);
667 uint16_t expInfoIndex, uint16_t goniometerIndex, uint32_t detectorId) {
668 std::lock_guard<std::mutex> _lock(this->m_dataMutex);
669 this->data.emplace_back(
687 const
std::vector<
coord_t> &point, uint16_t expInfoIndex,
688 uint16_t goniometerIndex, uint32_t detectorId) {
689 this->data.emplace_back(
699 std::lock_guard<std::mutex> _lock(this->m_dataMutex);
700 this->data.emplace_back(Evnt);
713 this->data.emplace_back(Evnt);
725 std::lock_guard<std::mutex> _lock(this->m_dataMutex);
727 this->data.insert(this->data.end(), events.cbegin(), events.cend());
739TMDE(
void MDBox)::setFileBacked(const uint64_t fileLocation, const size_t fileSize, const bool markSaved) {
741 m_Saveable = std::make_unique<MDBoxSaveable>(
this);
743 m_Saveable->setFilePosition(fileLocation, fileSize, markSaved);
749 this->setFileBacked(
UNDEF_UINT64, this->getDataInMemorySize(),
false);
764 throw(std::invalid_argument(
" Needs defined file saver to save data to it"));
765 if (!FileSaver->isOpened())
766 throw(std::invalid_argument(
" The data file has to be opened to use box SaveAt function"));
768 std::vector<coord_t> TabledData;
770 double totalSignal, totalErrSq;
772 MDE::eventsToData(this->data, TabledData, nDataColumns, totalSignal, totalErrSq);
774 this->m_signal =
static_cast<signal_t>(totalSignal);
775 this->m_errorSquared =
static_cast<signal_t>(totalErrSq);
776#ifdef MDBOX_TRACK_CENTROID
777 this->calculateCentroid(this->m_centroid);
780 FileSaver->saveBlock(TabledData,
position);
788TMDE(
void MDBox)::reserveMemoryForLoad(uint64_t size) { this->data.reserve(size); }
806 throw(std::invalid_argument(
" Needs defined file saver to load data using it"));
807 if (!FileSaver->isOpened())
808 throw(std::invalid_argument(
" The data file has to be opened to use box loadAndAddFrom function"));
810 std::lock_guard<std::mutex> _lock(this->m_dataMutex);
812 tableDataTemp.clear();
813 FileSaver->loadBlock(tableDataTemp, filePosition, nEvents);
816 MDE::dataToEvents(tableDataTemp, data,
false);
833 throw(std::invalid_argument(
" Needs defined file saver to load data using it"));
834 if (!FileSaver->isOpened())
835 throw(std::invalid_argument(
" The data file has to be opened to use box loadAndAddFrom function"));
837 std::lock_guard<std::mutex> _lock(this->m_dataMutex);
840 FileSaver->loadBlock(m_tableData, filePosition, nEvents);
843 MDE::dataToEvents(m_tableData, data,
false);
855TMDE(
void MDBox)::clearFileBacked(bool loadDiskBackedData) {
857 if (loadDiskBackedData)
860 this->m_BoxController->getFileIO()->objectDeleted(m_Saveable.get());
861 m_Saveable =
nullptr;
#define TMDE(decl)
Macro TMDE to make declaring template functions faster.
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...
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.