Newer
Older
#include "MantidDataObjects/MDBoxBase.h"
#include "MantidDataObjects/MDEvent.h"
#include "MantidKernel/System.h"
Janik Zikovsky
committed
#include "MantidKernel/VMD.h"
#include <boost/make_shared.hpp>
namespace DataObjects {
//-----------------------------------------------------------------------------------------------
/** Default constructor.
*/
TMDE(MDBoxBase)::MDBoxBase(Mantid::API::BoxController *const boxController,
const uint32_t depth, const size_t boxID)
: m_signal(0.0), m_errorSquared(0.0), m_totalWeight(0.0),
m_BoxController(boxController),
m_inverseVolume(std::numeric_limits<coord_t>::quiet_NaN()),
m_depth(depth), m_parent(NULL), m_fileID(boxID) {
if (boxController) {
// Give it a fresh ID from the controller.
if (boxID == std::numeric_limits<
size_t>::max()) // Give it a fresh ID from the controller.
this->m_fileID = boxController->getNextId();
}
//-----------------------------------------------------------------------------------------------
/** Constructor with extents
*/
TMDE(MDBoxBase)::MDBoxBase(
Mantid::API::BoxController *const boxController, const uint32_t depth,
const size_t boxID,
const std::vector<
Mantid::Geometry::MDDimensionExtents<coord_t>> &extentsVector)
: m_signal(0.0), m_errorSquared(0.0), m_totalWeight(0.0),
m_BoxController(boxController), m_inverseVolume(UNDEF_COORDT),
m_depth(depth), m_parent(NULL), m_fileID(boxID) {
if (boxController) {
// Give it a fresh ID from the controller.
if (boxID == UNDEF_SIZET) // Give it a fresh ID from the controller.
this->m_fileID = boxController->getNextId();
}
// Set the extents
if (extentsVector.size() != nd)
throw std::invalid_argument(
"MDBoxBase::ctor(): extentsVector.size() must be == nd.");
for (size_t d = 0; d < nd; d++)
this->extents[d] = extentsVector[d];
//-----------------------------------------------------------------------------------------------
/** Copy constructor. Copies the extents, depth, etc.
* and recalculates the boxes' volume.
* @param box :: incoming box to copy.
* @param otherBC :: if present, other (different from the current one) box
* controller pointer
*/
TMDE(MDBoxBase)::MDBoxBase(const MDBoxBase<MDE, nd> &box,
Mantid::API::BoxController *const otherBC)
: m_signal(box.m_signal), m_errorSquared(box.m_errorSquared),
m_totalWeight(box.m_totalWeight), m_BoxController(otherBC),
m_inverseVolume(box.m_inverseVolume), m_depth(box.m_depth),
m_parent(box.m_parent), m_fileID(box.m_fileID), m_dataMutex() {
// Copy the extents
for (size_t d = 0; d < nd; d++)
this->extents[d] = box.extents[d];
for (size_t d = 0; d < nd; d++)
this->m_centroid[d] = box.m_centroid[d];
}
//---------------------------------------------------------------------------------------------------
/** Transform the dimensions contained in this box
* x' = x*scaling + offset
*
* @param scaling :: multiply each coordinate by this value.
* @param offset :: after multiplying, add this offset.
*/
TMDE(void MDBoxBase)::transformDimensions(std::vector<double> &scaling,
std::vector<double> &offset) {
for (size_t d = 0; d < nd; d++) {
extents[d].scaleExtents(scaling[d], offset[d]);
// Re-calculate the volume of the box
this->calcVolume();
}
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
//-----------------------------------------------------------------------------------------------
/** Return the vertices of corners of the box
*
* @return a vector of VMD objects
*/
TMDE(std::vector<Mantid::Kernel::VMD> MDBoxBase)::getVertexes() const {
if (nd > 4)
throw std::runtime_error("MDBoxBase::getVertexes(): At this time, cannot "
"return vertexes for > 4 dimensions.");
std::vector<Mantid::Kernel::VMD> out;
// How many vertices does one box have? 2^nd, or bitwise shift left 1 by nd
// bits
size_t maxVertices = 1 << nd;
// For each vertex, increase an integeer
for (size_t i = 0; i < maxVertices; ++i) {
// Coordinates of the vertex
coord_t coords[nd];
for (size_t d = 0; d < nd; d++) {
// Use a bit mask to look at each bit of the integer we are iterating
// through.
size_t mask = 1 << d;
if ((i & mask) > 0) {
// Bit is 1, use the max of the dimension
coords[d] = extents[d].getMax();
} else {
// Bit is 0, use the min of the dimension
coords[d] = extents[d].getMin();
}
} // (for each dimension)
// Create the coordinate object and add it to the vector
out.push_back(Mantid::Kernel::VMD(nd, coords));
}
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
//-----------------------------------------------------------------------------------------------
/** Return the vertices of every corner of the box, but as
* a bare array of length numVertices * nd
*
* @param[out] numVertices :: returns the number of vertices in the array.
* @return the bare array. This should be deleted by the caller!
* */
TMDE(coord_t *MDBoxBase)::getVertexesArray(size_t &numVertices) const {
// How many vertices does one box have? 2^nd, or bitwise shift left 1 by nd
// bits
numVertices = 1 << nd;
// Allocate the array of the right size
coord_t *out = new coord_t[nd * numVertices];
// For each vertex, increase an integeer
for (size_t i = 0; i < numVertices; ++i) {
// Start point index in the output array;
size_t outIndex = i * nd;
// Coordinates of the vertex
for (size_t d = 0; d < nd; d++) {
// Use a bit mask to look at each bit of the integer we are iterating
// through.
size_t mask = 1 << d;
if ((i & mask) > 0) {
// Bit is 1, use the max of the dimension
out[outIndex + d] = extents[d].getMax();
} else {
// Bit is 0, use the min of the dimension
out[outIndex + d] = extents[d].getMin();
}
} // (for each dimension)
}
return out;
}
Janik Zikovsky
committed
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
//-----------------------------------------------------------------------------------------------
/** Return the vertices of every corner of the box, but to a reduced
* number of dimensions.
*
* Essentially, this is a projection of the vertexes from nd down to a lower
* (or equal) number of dimensions. Redundant vertexes are NOT included.
*
* @param[out] numVertices :: returns the number of vertices in the array.
* @param outDimensions :: the number of dimensions in the output array (must be
*> 0).
* @param maskDim :: nd-sized array of a mask, with TRUE for the dimensions to
*KEEP.
* The number of TRUEs in maskDim MUST be equal to outDimensions, and
*this is
* not checked for here (for performance).
* @return the bare array, size of outDimensions. This should be deleted by the
*caller!
* @throw if outDimensions == 0
* */
TMDE(coord_t *MDBoxBase)::getVertexesArray(size_t &numVertices,
const size_t outDimensions,
const bool *maskDim) const {
if (outDimensions == 0)
throw std::invalid_argument(
"MDBoxBase::getVertexesArray(): Must have > 0 output dimensions.");
// How many vertices does one box have? 2^numOutputDimensions
numVertices = (size_t)1 << outDimensions;
// Allocate the array of the right size
coord_t *out = new coord_t[outDimensions * numVertices];
// For each vertex, increase an integeer
for (size_t i = 0; i < numVertices; ++i) {
// Start point index in the output array;
size_t outIndex = i * outDimensions;
// The OUTPUT dimension index
size_t outd = 0;
// Coordinates of the vertex
for (size_t ind = 0; ind < nd; ind++) {
if (maskDim[ind]) {
// Use a bit mask to look at each bit of the integer we are iterating
// through.
size_t mask = (size_t)1 << outd;
if ((i & mask) > 0) {
Janik Zikovsky
committed
// Bit is 1, use the max of the dimension
out[outIndex + outd] = extents[ind].getMax();
} else {
Janik Zikovsky
committed
// Bit is 0, use the min of the dimension
out[outIndex + outd] = extents[ind].getMin();
Janik Zikovsky
committed
}
outd++;
} // the dimensions is used in the output.
} // (for each INPUT dimension)
Janik Zikovsky
committed
}
Janik Zikovsky
committed
//-----------------------------------------------------------------------------------------------
/** Add several events, starting and stopping at particular point in a vector.
* Bounds checking IS performed, and events outside the range are rejected.
*
* NOTE: You must call refreshCache() after you are done, to calculate the
* nPoints, signal and error.
*
* @param events :: vector of events to be copied.
* @return the number of events that were rejected (because of being out of
*bounds)
*/
TMDE(size_t MDBoxBase)::addEvents(const std::vector<MDE> &events) {
size_t numBad = 0;
// --- Go event by event and add them ----
typename std::vector<MDE>::const_iterator it = events.begin();
typename std::vector<MDE>::const_iterator it_end = events.end();
m_dataMutex.lock();
for (; it != it_end; ++it) {
// Check out-of-bounds-ness
bool badEvent = false;
for (size_t d = 0; d < nd; d++) {
coord_t x = it->getCenter(d);
if (extents[d].outside(x)) {
badEvent = true;
break;
if (badEvent)
// Event was out of bounds. Count it
++numBad;
else
// Event was in bounds; add it
addEventUnsafe(*it);
}
m_dataMutex.unlock();
return numBad;
}
//---------------------------------------------------------------------------------------------------
/** Add all of the events contained in a vector, with:
* - No bounds checking.
* - No thread-safety.
*
* @param events :: Vector of MDEvent
*/
TMDE(size_t MDBoxBase)::addEventsUnsafe(const std::vector<MDE> &events) {
// --- Go event by event and add them ----
typename std::vector<MDE>::const_iterator it = events.begin();
typename std::vector<MDE>::const_iterator it_end = events.end();
for (; it != it_end; ++it) {
// Check out-of-bounds-ness
// Event was in bounds; add it
addEventUnsafe(*it);
}
Janik Zikovsky
committed
Janik Zikovsky
committed
} // namespace Mantid
} // namespace DataObjects