Newer
Older
Janik Zikovsky
committed
#include "MantidAPI/ITableWorkspace.h"
#include "MantidDataObjects/TableWorkspace.h"
Janik Zikovsky
committed
#include "MantidGeometry/MDGeometry/MDHistoDimension.h"
#include "MantidKernel/CPUTimer.h"
Janik Zikovsky
committed
#include "MantidKernel/FunctionTask.h"
#include "MantidKernel/ProgressBase.h"
#include "MantidKernel/Task.h"
Janik Zikovsky
committed
#include "MantidKernel/ThreadPool.h"
#include "MantidKernel/ThreadScheduler.h"
#include "MantidKernel/Timer.h"
#include "MantidKernel/Utils.h"
#include "MantidKernel/WarningSuppressions.h"
#include "MantidDataObjects/MDBoxBase.h"
#include "MantidDataObjects/MDBox.h"
#include "MantidDataObjects/MDEventWorkspace.h"
#include "MantidDataObjects/MDFramesToSpecialCoordinateSystem.h"
#include "MantidDataObjects/MDGridBox.h"
#include "MantidDataObjects/MDLeanEvent.h"
#include <iomanip>
Janik Zikovsky
committed
#include <functional>
#include "MantidDataObjects/MDBoxIterator.h"
#include "MantidKernel/Memory.h"
#include "MantidKernel/Exception.h"
Janik Zikovsky
committed
// Test for gcc 4.4
#if __GNUC__ > 4 || \
(__GNUC__ == 4 && (__GNUC_MINOR__ > 4 || \
(__GNUC_MINOR__ == 4 && \
__GNUC_PATCHLEVEL__ > 0)))
GCC_DIAG_OFF(strict-aliasing)
#endif
Janik Zikovsky
committed
using namespace Mantid;
using namespace Mantid::Kernel;
using namespace Mantid::API;
Janik Zikovsky
committed
using namespace Mantid::Geometry;
Janik Zikovsky
committed
using namespace Mantid::DataObjects;
namespace DataObjects {
//-----------------------------------------------------------------------------------------------
TMDE(MDEventWorkspace)::MDEventWorkspace(
Mantid::API::MDNormalization preferredNormalization,
Mantid::API::MDNormalization preferredNormalizationHisto)
: API::IMDEventWorkspace(), data(NULL),
m_BoxController(new BoxController(nd)),
m_displayNormalization(preferredNormalization),
m_displayNormalizationHisto(preferredNormalizationHisto),
m_coordSystem(None) {
// First box is at depth 0, and has this default boxController
data = new MDBox<MDE, nd>(m_BoxController.get(), 0);
}
//-----------------------------------------------------------------------------------------------
/** Copy constructor
*/
TMDE(MDEventWorkspace)::MDEventWorkspace(const MDEventWorkspace<MDE, nd> &other)
: IMDEventWorkspace(other), data(NULL),
m_BoxController(other.m_BoxController->clone()),
m_displayNormalization(other.m_displayNormalization),
m_displayNormalizationHisto(other.m_displayNormalizationHisto),
m_coordSystem(other.m_coordSystem) {
const MDBox<MDE, nd> *mdbox =
dynamic_cast<const MDBox<MDE, nd> *>(other.data);
const MDGridBox<MDE, nd> *mdgridbox =
dynamic_cast<const MDGridBox<MDE, nd> *>(other.data);
if (mdbox) {
data = new MDBox<MDE, nd>(*mdbox, m_BoxController.get());
} else if (mdgridbox) {
data = new MDGridBox<MDE, nd>(*mdgridbox, m_BoxController.get());
} else {
throw std::runtime_error(
"MDEventWorkspace::copy_ctor(): unexpected data box type found.");
}
//-----------------------------------------------------------------------------------------------
/** Destructor
*/
TMDE(MDEventWorkspace)::~MDEventWorkspace() { delete data; }
/**Make workspace file backed if it has not been already file backed
* @param fileName -- short or full file name of the file, which should be used
* as the file back end
*/
TMDE(void MDEventWorkspace)::setFileBacked(const std::string & /*fileName*/) {
throw Kernel::Exception::NotImplementedError(" Not yet implemented");
}
/** If the workspace was filebacked, this would clear file-backed information
*from the workspace nodes and close the files responsible for file backing
*
*@param LoadFileBackedData -- if true, load all data initially backed to hdd
*when breaking connection between the file and the workspace.
* if false, data on hdd are lost if not previously
*loaded in memory and the workspace is generally corrupted
* (used in destructor)
*/
TMDE(void MDEventWorkspace)::clearFileBacked(bool LoadFileBackedData) {
if (m_BoxController->isFileBacked()) {
data->clearFileBacked(LoadFileBackedData);
m_BoxController->clearFileBacked();
}
//-----------------------------------------------------------------------------------------------
/** Perform initialization after m_dimensions (and others) have been set.
* This sets the size of the box.
*/
TMDE(void MDEventWorkspace)::initialize() {
if (m_dimensions.size() != nd)
throw std::runtime_error("MDEventWorkspace::initialize() called with an "
"incorrect number of m_dimensions set. Use "
"addDimension() first to add the right number of "
"dimension info objects.");
if (isGridBox())
throw std::runtime_error("MDEventWorkspace::initialize() called on a "
"MDEventWorkspace containing a MDGridBox. You "
"should call initialize() before adding any "
"events!");
double minSize[nd], maxSize[nd];
for (size_t d = 0; d < nd; d++) {
minSize[d] = m_dimensions[d]->getMinimum();
maxSize[d] = m_dimensions[d]->getMaximum();
129
130
131
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
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
data->setExtents(minSize, maxSize);
}
//-----------------------------------------------------------------------------------------------
/** Get the data type (id) of the workspace */
TMDE(const std::string MDEventWorkspace)::id() const {
std::ostringstream out;
out << "MDEventWorkspace<" << MDE::getTypeName() << "," << getNumDims()
<< ">";
return out.str();
}
//-----------------------------------------------------------------------------------------------
/** Get the data type (id) of the events in the workspace.
* @return a string, either "MDEvent" or "MDLeanEvent"
*/
TMDE(std::string MDEventWorkspace)::getEventTypeName() const {
return MDE::getTypeName();
}
//-----------------------------------------------------------------------------------------------
/** Returns the number of dimensions in this workspace */
TMDE(size_t MDEventWorkspace)::getNumDims() const { return nd; }
//-----------------------------------------------------------------------------------------------
/** Returns the total number of points (events) in this workspace */
TMDE(uint64_t MDEventWorkspace)::getNPoints() const {
return data->getNPoints();
}
//-----------------------------------------------------------------------------------------------
/** Recurse box structure down to a minimum depth.
*
* This will split all boxes so that all MDBoxes are at the depth indicated.
* 0 = no splitting, 1 = one level of splitting, etc.
*
* WARNING! This should ONLY be called before adding any events to a workspace.
*
* WARNING! Be careful using this since it can quickly create a huge
* number of boxes = (SplitInto ^ (MinRercursionDepth * NumDimensions))
*
* @param minDepth :: minimum recursion depth.
* @throw std::runtime_error if there is not enough memory for the boxes.
*/
TMDE(void MDEventWorkspace)::setMinRecursionDepth(size_t minDepth) {
BoxController_sptr bc = this->getBoxController();
double numBoxes = pow(double(bc->getNumSplit()), double(minDepth));
double memoryToUse = numBoxes * double(sizeof(MDBox<MDE, nd>)) / 1024.0;
MemoryStats stats;
if (double(stats.availMem()) < memoryToUse) {
std::ostringstream mess;
mess << "Not enough memory available for the given MinRecursionDepth! "
<< "MinRecursionDepth is set to " << minDepth
<< ", which would create " << numBoxes << " boxes using "
<< memoryToUse << " kB of memory."
<< " You have " << stats.availMem() << " kB available." << std::endl;
throw std::runtime_error(mess.str());
for (size_t depth = 1; depth < minDepth; depth++) {
// Get all the MDGridBoxes in the workspace
std::vector<API::IMDNode *> boxes;
boxes.clear();
this->getBox()->getBoxes(boxes, depth - 1, false);
for (size_t i = 0; i < boxes.size(); i++) {
MDGridBox<MDE, nd> *gbox = dynamic_cast<MDGridBox<MDE, nd> *>(boxes[i]);
if (gbox) {
// Split ALL the contents.
for (size_t j = 0; j < gbox->getNumChildren(); j++)
gbox->splitContents(j, NULL);
}
}
}
}
//-----------------------------------------------------------------------------------------------
/** @return a vector with the size of the smallest bin in each dimension */
TMDE(std::vector<coord_t> MDEventWorkspace)::estimateResolution() const {
size_t realDepth = 0;
std::vector<size_t> numMD = m_BoxController->getNumMDBoxes();
for (size_t i = 0; i < numMD.size(); i++)
if (numMD[i] > 0)
realDepth = i;
std::vector<coord_t> out;
for (size_t d = 0; d < nd; d++) {
size_t finestSplit = 1;
for (size_t i = 0; i < realDepth; i++)
finestSplit *= m_BoxController->getSplitInto(d);
IMDDimension_const_sptr dim = this->getDimension(d);
// Calculate the bin size at the smallest split amount
out.push_back((dim->getMaximum() - dim->getMinimum()) /
static_cast<coord_t>(finestSplit));
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
return out;
}
//-----------------------------------------------------------------------------------------------
/** Creates a new iterator pointing to the first cell (box) in the workspace
*
* @param suggestedNumCores :: split iterator over this many cores.
* @param function :: Optional MDImplicitFunction limiting the iterator
*/
TMDE(std::vector<Mantid::API::IMDIterator *> MDEventWorkspace)::createIterators(
size_t suggestedNumCores,
Mantid::Geometry::MDImplicitFunction *function) const {
// Get all the boxes in this workspaces
std::vector<IMDNode *> boxes;
// TODO: Should this be leaf only? Depends on most common use case
if (function)
this->data->getBoxes(boxes, 10000, true, function);
else
this->data->getBoxes(boxes, 10000, true);
// Calculate the right number of cores
size_t numCores = suggestedNumCores;
if (!this->threadSafe())
numCores = 1;
size_t numElements = boxes.size();
if (numCores > numElements)
numCores = numElements;
if (numCores < 1)
numCores = 1;
// Create one iterator per core, splitting evenly amongst spectra
std::vector<IMDIterator *> out;
for (size_t i = 0; i < numCores; i++) {
size_t begin = (i * numElements) / numCores;
size_t end = ((i + 1) * numElements) / numCores;
if (end > numElements)
end = numElements;
out.push_back(new MDBoxIterator<MDE, nd>(boxes, begin, end));
Janik Zikovsky
committed
}
return out;
}
//-----------------------------------------------------------------------------------------------
/** Returns the (normalized) signal at a given coordinates
*
* @param coords :: nd-sized array of coordinates
* @param normalization :: how to normalize the signal.
* @return the normalized signal of the box at the given coordinates. NaN if out
*of bounds
*/
TMDE(signal_t MDEventWorkspace)::getSignalAtCoord(
const coord_t *coords,
const Mantid::API::MDNormalization &normalization) const {
// Do an initial bounds check
for (size_t d = 0; d < nd; d++) {
coord_t x = coords[d];
if (data->getExtents(d).outside(x))
return std::numeric_limits<signal_t>::quiet_NaN();
}
// If you got here, then the point is in the workspace.
const API::IMDNode *box = data->getBoxAtCoord(coords);
if (box) {
// What is our normalization factor?
switch (normalization) {
case NoNormalization:
return box->getSignal();
case VolumeNormalization:
return box->getSignal() * box->getInverseVolume();
case NumEventsNormalization:
return box->getSignal() / double(box->getNPoints());
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
// Should not reach here
return box->getSignal();
} else
return std::numeric_limits<signal_t>::quiet_NaN();
}
//-----------------------------------------------------------------------------------------------
/** Get a vector of the minimum extents that still contain all the events in the
*workspace.
*
* @param depth :: recursion depth to which to search. This will determine the
*resolution
* to which the extents will be found.
* @return a vector of the minimum extents that still contain all the events in
*the workspace.
* If the workspace is empty, then this will be the size of the overall
*workspace
*/
TMDE(std::vector<Mantid::Geometry::MDDimensionExtents<coord_t>>
MDEventWorkspace)::getMinimumExtents(size_t depth) {
std::vector<Mantid::Geometry::MDDimensionExtents<coord_t>> out(nd);
std::vector<API::IMDNode *> boxes;
// Get all the end (leaf) boxes
this->data->getBoxes(boxes, depth, true);
auto it = boxes.begin();
auto it_end = boxes.end();
for (; it != it_end; ++it) {
API::IMDNode *box = *it;
if (box->getNPoints() > 0) {
for (size_t d = 0; d < nd; d++)
box->getExtents(d).expand(out[d]);
Janik Zikovsky
committed
}
// Fix any missing dimensions (for empty workspaces)
for (size_t d = 0; d < nd; d++) {
if (out[d].isUndefined())
out[d].setExtents(this->getDimension(d)->getMinimum(),
this->getDimension(d)->getMaximum());
Janik Zikovsky
committed
}
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
return out;
}
//-----------------------------------------------------------------------------------------------
/// Returns some information about the box controller, to be displayed in the
/// GUI, for example
TMDE(std::vector<std::string> MDEventWorkspace)::getBoxControllerStats() const {
std::vector<std::string> out;
std::ostringstream mess;
size_t mem;
mem = (this->m_BoxController->getTotalNumMDBoxes() * sizeof(MDBox<MDE, nd>)) /
1024;
mess << m_BoxController->getTotalNumMDBoxes() << " MDBoxes (" << mem
<< " kB)";
out.push_back(mess.str());
mess.str("");
mem = (this->m_BoxController->getTotalNumMDGridBoxes() *
sizeof(MDGridBox<MDE, nd>)) /
1024;
mess << m_BoxController->getTotalNumMDGridBoxes() << " MDGridBoxes (" << mem
<< " kB)";
out.push_back(mess.str());
mess.str("");
// mess << "Avg recursion depth: " << m_BoxController->getAverageDepth();
// out.push_back(mess.str()); mess.str("");
//
// mess << "Recursion Coverage %: ";
// const std::vector<size_t> & num = m_BoxController->getNumMDBoxes();
// const std::vector<double> & max = m_BoxController->getMaxNumMDBoxes();
// for (size_t i=0; i<num.size(); i++)
// {
// if (i > 0) mess << ", ";
// double pct = (double(num[i]) / double(max[i] * 100));
// if (pct > 0 && pct < 1e-2) mess << std::scientific; else mess <<
// std::fixed;
// mess << std::setprecision(2) << pct;
// }
// out.push_back(mess.str()); mess.str("");
if (m_BoxController->isFileBacked()) {
mess << "File backed: ";
double avail = double(m_BoxController->getFileIO()->getWriteBufferSize() *
sizeof(MDE)) /
(1024 * 1024);
double used = double(m_BoxController->getFileIO()->getWriteBufferUsed() *
sizeof(MDE)) /
(1024 * 1024);
mess << "Write buffer: " << used << " of " << avail << " MB. ";
out.push_back(mess.str());
mess.str("");
mess << "File";
if (this->fileNeedsUpdating())
mess << " (needs updating)";
mess << ": " << this->m_BoxController->getFileIO()->getFileName();
out.push_back(mess.str());
mess.str("");
} else {
mess << "Not file backed.";
out.push_back(mess.str());
mess.str("");
Janik Zikovsky
committed
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
return out;
}
//-----------------------------------------------------------------------------------------------
/** Comparator for sorting MDBoxBase'es by ID */
template <typename BOXTYPE>
bool SortBoxesByID(const BOXTYPE &a, const BOXTYPE &b) {
return a->getID() < b->getID();
}
//-----------------------------------------------------------------------------------------------
/** Create a table of data about the boxes contained */
TMDE(Mantid::API::ITableWorkspace_sptr MDEventWorkspace)::makeBoxTable(
size_t start, size_t num) {
CPUTimer tim;
UNUSED_ARG(start);
UNUSED_ARG(num);
// Boxes to show
std::vector<API::IMDNode *> boxes;
std::vector<MDBoxBase<MDE, nd> *> boxes_filtered;
this->getBox()->getBoxes(boxes, 1000, false);
boxes_filtered.reserve(boxes.size());
for (size_t i = 0; i < boxes.size(); i++) {
MDBoxBase<MDE, nd> *box = dynamic_cast<MDBoxBase<MDE, nd> *>(boxes[i]);
boxes_filtered.push_back(box);
Janik Zikovsky
committed
}
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
// Now sort by ID
typedef MDBoxBase<MDE, nd> *ibox_t;
std::sort(boxes_filtered.begin(), boxes_filtered.end(),
SortBoxesByID<ibox_t>);
// Create the table
int numRows = int(boxes_filtered.size());
TableWorkspace_sptr ws(new TableWorkspace(numRows));
ws->addColumn("int", "ID");
ws->addColumn("int", "Depth");
ws->addColumn("int", "# children");
ws->addColumn("int", "File Pos.");
ws->addColumn("int", "File Size");
ws->addColumn("int", "EventVec Size");
ws->addColumn("str", "OnDisk?");
ws->addColumn("str", "InMemory?");
ws->addColumn("str", "Changes?");
ws->addColumn("str", "Extents");
for (int i = 0; i < int(boxes_filtered.size()); i++) {
MDBoxBase<MDE, nd> *box = boxes_filtered[i];
int col = 0;
ws->cell<int>(i, col++) = int(box->getID());
;
ws->cell<int>(i, col++) = int(box->getDepth());
ws->cell<int>(i, col++) = int(box->getNumChildren());
MDBox<MDE, nd> *mdbox = dynamic_cast<MDBox<MDE, nd> *>(box);
Kernel::ISaveable const *const pSaver(box->getISaveable());
ws->cell<int>(i, col++) = pSaver ? int(pSaver->getFilePosition()) : -1;
ws->cell<int>(i, col++) = pSaver ? int(pSaver->getFileSize()) : 0;
ws->cell<int>(i, col++) = mdbox ? int(mdbox->getDataInMemorySize()) : -1;
if (mdbox && pSaver) {
ws->cell<std::string>(i, col++) = (pSaver->wasSaved() ? "yes" : "no");
ws->cell<std::string>(i, col++) = (pSaver->isLoaded() ? "yes" : "no");
bool isDataAdded = (mdbox->isDataAdded());
ws->cell<std::string>(i, col++) =
std::string(isDataAdded ? "Added " : "") +
std::string(pSaver->isBusy() ? "Modif." : "");
} else {
ws->cell<std::string>(i, col++) = (pSaver ? "-" : "NA");
ws->cell<std::string>(i, col++) = (pSaver ? "-" : "NA");
ws->cell<std::string>(i, col++) = (pSaver ? "-" : "NA");
}
ws->cell<std::string>(i, col++) = box->getExtentsStr();
std::cout << tim << " to create the MDBox data table." << std::endl;
return ws;
}
//-----------------------------------------------------------------------------------------------
/** @returns the number of bytes of memory used by the workspace. */
TMDE(size_t MDEventWorkspace)::getMemorySize() const {
// std::cout << "sizeof(MDE) " << sizeof(MDE) << std::endl;
// std::cout << "sizeof(MDBox<MDE,nd>) " << sizeof(MDBox<MDE,nd>) <<
// std::endl;
// std::cout << "sizeof(MDGridBox<MDE,nd>) " << sizeof(MDGridBox<MDE,nd>)
// << std::endl;
size_t total = 0;
if (this->m_BoxController->isFileBacked()) {
// File-backed workspace
// How much is in the cache?
total =
this->m_BoxController->getFileIO()->getWriteBufferUsed() * sizeof(MDE);
} else {
// All the events
total = this->getNPoints() * sizeof(MDE);
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
// The MDBoxes are always in memory
total += this->m_BoxController->getTotalNumMDBoxes() * sizeof(MDBox<MDE, nd>);
total += this->m_BoxController->getTotalNumMDGridBoxes() *
sizeof(MDGridBox<MDE, nd>);
return total;
}
//-----------------------------------------------------------------------------------------------
/** Add a single event to this workspace. Automatic splitting is not performed
*after adding
* (call splitAllIfNeeded).
*
* @param event :: event to add.
*/
TMDE(void MDEventWorkspace)::addEvent(const MDE &event) {
data->addEvent(event);
}
//-----------------------------------------------------------------------------------------------
/** Add a vector of MDEvents to the workspace.
*
* @param events :: const ref. to a vector of events; they will be copied into
*the
* MDBox'es contained within.
*/
TMDE(size_t MDEventWorkspace)::addEvents(const std::vector<MDE> &events) {
return data->addEvents(events);
}
//-----------------------------------------------------------------------------------------------
/** Split the contained MDBox into a MDGridBox or MDSplitBox, if it is not
* that already.
*/
TMDE(void MDEventWorkspace)::splitBox() {
// Want MDGridBox
MDGridBox<MDE, nd> *gridBox = dynamic_cast<MDGridBox<MDE, nd> *>(data);
if (!gridBox) {
// Track how many MDBoxes there are in the overall workspace
this->m_BoxController->trackNumBoxes(data->getDepth());
MDBox<MDE, nd> *box = dynamic_cast<MDBox<MDE, nd> *>(data);
if (!box)
throw std::runtime_error("MDEventWorkspace::splitBox() expected its data "
"to be a MDBox* to split to MDGridBox.");
gridBox = new MDGridBox<MDE, nd>(box);
delete data;
data = gridBox;
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
}
//-----------------------------------------------------------------------------------------------
/** Goes through all the sub-boxes and splits them if they contain
* enough events to be worth it.
*
* @param ts :: optional ThreadScheduler * that will be used to parallelize
* recursive splitting. Set to NULL to do it serially.
*/
TMDE(void MDEventWorkspace)::splitAllIfNeeded(Kernel::ThreadScheduler *ts) {
data->splitAllIfNeeded(ts);
}
//-----------------------------------------------------------------------------------------------
/** Goes through the MDBoxes that were tracked by the BoxController
* as being too large, and splits them.
* @param ts :: optional ThreadScheduler * that will be used to parallelize
* recursive splitting.
*/
TMDE(void MDEventWorkspace)::splitTrackedBoxes(ThreadScheduler *ts) {
UNUSED_ARG(ts);
throw std::runtime_error("Not implemented yet");
// // Get a COPY of the vector (to avoid thread-safety issues)
// std::vector<void *> boxes = this->getBoxController()->getBoxesToSplit();
// //PRAGMA_OMP( parallel for )
// for (int i=0; i<int(boxes.size()); i++)
// {
// MDBox<MDE,nd> * box = dynamic_cast<MDBox<MDE,nd> *>(boxes[i]);
// if (box)
// {
// MDGridBox<MDE,nd> * parent = dynamic_cast<MDGridBox<MDE,nd>
// *>(box->getParent());
// if (parent)
// {
// parent->splitContents(parent->getChildIndexFromID(box->getId()),
// ts);
// }
// }
// }
}
//-----------------------------------------------------------------------------------------------
/** Refresh the cache of # of points, signal, and error.
* NOTE: This is performed in parallel using a threadpool.
* */
TMDE(void MDEventWorkspace)::refreshCache() {
// Function is overloaded and recursive; will check all sub-boxes
data->refreshCache();
// TODO ThreadPool
}
Janik Zikovsky
committed
// //-----------------------------------------------------------------------------------------------
// /** Add a large number of events to this MDEventWorkspace.
// * This will use a ThreadPool/OpenMP to allocate events in parallel.
// *
// * param events :: vector of events to be copied.
// * param prog :: optional Progress object to report progress back to
// GUI/algorithms.
// * return the number of events that were rejected (because of being out of
// bounds)
// void MDEventWorkspace)::addManyEvents(const std::vector<MDE> & events,
// Mantid::Kernel::ProgressBase * prog)
// {
// // Always split the MDBox into a grid box
// this->splitBox();
// MDGridBox<MDE,nd> * gridBox = dynamic_cast<MDGridBox<MDE,nd> *>(data);
//
// // Get some parameters that should optimize task allocation.
// size_t eventsPerTask, numTasksPerBlock;
// this->m_BoxController->getAddingEventsParameters(eventsPerTask,
// numTasksPerBlock);
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
//
// // Set up progress report, if any
// if (prog)
// {
// size_t numTasks = events.size()/eventsPerTask;
// prog->setNumSteps( int( numTasks + numTasks/numTasksPerBlock ));
// }
//
// // Where we are in the list of events
// size_t event_index = 0;
// while (event_index < events.size())
// {
// //Since the costs are not known ahead of time, use a simple FIFO buffer.
// ThreadScheduler * ts = new ThreadSchedulerFIFO();
// // Create the threadpool
// ThreadPool tp(ts);
//
// // Do 'numTasksPerBlock' tasks with 'eventsPerTask' events in each one.
// for (size_t i = 0; i < numTasksPerBlock; i++)
// {
// // Calculate where to start and stop in the events vector
// bool breakout = false;
// size_t start_at = event_index;
// event_index += eventsPerTask;
// size_t stop_at = event_index;
// if (stop_at >= events.size())
// {
// stop_at = events.size();
// breakout = true;
// }
//
// // Create a task and push it into the scheduler
// //std::cout << "Making a AddEventsTask " << start_at << " to " <<
// stop_at << std::endl;
// typename MDGridBox<MDE,nd>::AddEventsTask * task;
// task = new typename MDGridBox<MDE,nd>::AddEventsTask(gridBox, events,
// start_at, stop_at, prog) ;
// ts->push( task );
//
// if (breakout) break;
// }
//
// // Finish all threads.
//// std::cout << "Starting block ending at index " << event_index << " of
///" << events.size() << std::endl;
// Timer tim;
// tp.joinAll();
//// std::cout << "... block took " << tim.elapsed() << " secs.\n";
//
// //Create a threadpool for splitting.
// ThreadScheduler * ts_splitter = new ThreadSchedulerFIFO();
// ThreadPool tp_splitter(ts_splitter);
//
// //Now, shake out all the sub boxes and split those if needed
//// std::cout << "\nStarting splitAllIfNeeded().\n";
// if (prog) prog->report("Splitting MDBox'es.");
//
// gridBox->splitAllIfNeeded(ts_splitter);
// tp_splitter.joinAll();
//// std::cout << "\n... splitAllIfNeeded() took " << tim.elapsed() << "
/// secs.\n";
// }
//
// // Refresh the counts, now that we are all done.
// this->refreshCache();
// }
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
//-----------------------------------------------------------------------------------------------
/** Obtain coordinates for a line plot through a MDWorkspace.
* Cross the workspace from start to end points, recording the signal along the
*line.
* Sets the x,y vectors to the histogram bin boundaries and counts
*
* @param start :: coordinates of the start point of the line
* @param end :: coordinates of the end point of the line
* @param normalize :: how to normalize the signal
* @param x :: is set to the boundaries of the bins, relative to start of the
*line.
* @param y :: is set to the normalized signal for each bin. Length = length(x)
*- 1
* @param e :: vector of errors for each bin.
*/
TMDE(void MDEventWorkspace)::getLinePlot(const Mantid::Kernel::VMD &start,
const Mantid::Kernel::VMD &end,
Mantid::API::MDNormalization normalize,
std::vector<coord_t> &x,
std::vector<signal_t> &y,
std::vector<signal_t> &e) const {
// TODO: Don't use a fixed number of points later
size_t numPoints = 200;
VMD step = (end - start) / double(numPoints);
double stepLength = step.norm();
// These will be the curve as plotted
x.clear();
y.clear();
e.clear();
for (size_t i = 0; i < numPoints; i++) {
// Coordinate along the line
VMD coord = start + step * double(i);
// Record the position along the line
x.push_back(static_cast<coord_t>(stepLength * double(i)));
// Look for the box at this coordinate
// const MDBoxBase<MDE,nd> * box = NULL;
const IMDNode *box = NULL;
// Do an initial bounds check
bool outOfBounds = false;
for (size_t d = 0; d < nd; d++) {
if (data->getExtents(d).outside(coord[d])) {
outOfBounds = true;
break;
}
}
// TODO: make the logic/reuse in the following nicer.
if (!outOfBounds) {
box = this->data->getBoxAtCoord(coord.getBareArray());
if (box != NULL) {
// What is our normalization factor?
signal_t normalizer = 1.0;
switch (normalize) {
case NoNormalization:
break;
case VolumeNormalization:
normalizer = box->getInverseVolume();
break;
case NumEventsNormalization:
normalizer = 1.0 / double(box->getNPoints());
// And add the normalized signal/error to the list
y.push_back(box->getSignal() * normalizer);
e.push_back(box->getError() * normalizer);
} else {
y.push_back(std::numeric_limits<double>::quiet_NaN());
e.push_back(std::numeric_limits<double>::quiet_NaN());
}
} else {
// Point is outside the workspace. Add NANs
y.push_back(std::numeric_limits<double>::quiet_NaN());
e.push_back(std::numeric_limits<double>::quiet_NaN());
// And the last point
x.push_back((end - start).norm());
}
/**
Setter for the masking region.
@param maskingRegion : Implicit function defining mask region.
*/
TMDE(void MDEventWorkspace)::setMDMasking(
Mantid::Geometry::MDImplicitFunction *maskingRegion) {
if (maskingRegion) {
std::vector<API::IMDNode *> toMaskBoxes;
// Apply new masks
this->data->getBoxes(toMaskBoxes, 10000, true, maskingRegion);
for (size_t i = 0; i < toMaskBoxes.size(); ++i) {
toMaskBoxes[i]->mask();
}
/**
Clears ALL existing masks off the workspace.
*/
TMDE(void MDEventWorkspace)::clearMDMasking() {
std::vector<API::IMDNode *> allBoxes;
// Clear old masks
this->data->getBoxes(allBoxes, 10000, true);
for (size_t i = 0; i < allBoxes.size(); ++i) {
allBoxes[i]->unmask();
Get the coordinate system (if any) to use.
@return An enumeration specifying the coordinate system if any.
TMDE(Kernel::SpecialCoordinateSystem
MDEventWorkspace)::getSpecialCoordinateSystem() const {
MDFramesToSpecialCoordinateSystem converter;
auto coordinatesFromMDFrames = converter(this);
auto coordinates = m_coordSystem;
if (coordinatesFromMDFrames) {
coordinates = coordinatesFromMDFrames.get();
}
return coordinates;
Set the coordinate system (if any) to use.
@param coordSystem : Coordinate system to use.
TMDE(void MDEventWorkspace)::setCoordinateSystem(
const Kernel::SpecialCoordinateSystem coordSystem) {
m_coordSystem = coordSystem;
/**
Set the display normalization for any subsequently generated histoworkspaces.
@param preferredNormalization : Display normalization preference to pass on to generated histo workspaces.
*/
TMDE(void MDEventWorkspace)::setDisplayNormalizationHisto(
const Mantid::API::MDNormalization preferredNormalizationHisto) {
m_displayNormalizationHisto = preferredNormalizationHisto;
Return the preferred normalization preference for subsequent histoworkspaces.
TMDE(MDNormalization MDEventWorkspace)::displayNormalizationHisto() const {
return m_displayNormalizationHisto;
Set the display normalization
@param preferredNormalization : Display normalization preference.
TMDE(void MDEventWorkspace)::setDisplayNormalization(
const Mantid::API::MDNormalization preferredNormalization) {
m_displayNormalization = preferredNormalization;
}
/**
Return the preferred normalization to use for visualization.
*/
TMDE(MDNormalization MDEventWorkspace)::displayNormalization() const {
return m_displayNormalization ;
} // namespace DataObjects