void MinusMD::doMinus(typename MDEventWorkspace<MDE, nd>::sptr ws)
{
typename MDEventWorkspace<MDE, nd>::sptr ws1 = ws;
typename MDEventWorkspace<MDE, nd>::sptr ws2 = boost::dynamic_pointer_cast<MDEventWorkspace<MDE, nd> >(m_operand_event);
if (!ws1 || !ws2)
throw std::runtime_error("Incompatible workspace types passed to MinusMD.");
MDBoxBase<MDE,nd> * box1 = ws1->getBox();
MDBoxBase<MDE,nd> * box2 = ws2->getBox();
Progress prog(this, 0.0, 0.4, box2->getBoxController()->getTotalNumMDBoxes());
// How many events you started with
size_t initial_numEvents = ws1->getNPoints();
// Make a leaf-only iterator through all boxes with events in the RHS workspace
MDBoxIterator<MDE,nd> it2(box2, 1000, true);
do
{
MDBox<MDE,nd> * box = dynamic_cast<MDBox<MDE,nd> *>(it2.getBox());
if (box)
{
// Copy the events from WS2 and add them into WS1
const std::vector<MDE> & events = box->getConstEvents();
// Perform a copy while flipping the signal
std::vector<MDE> eventsCopy;
eventsCopy.reserve(events.size());
for (auto it = events.begin(); it != events.end(); it++)
{
MDE eventCopy(*it);
eventCopy.setSignal( -eventCopy.getSignal());
eventsCopy.push_back(eventCopy);
}
// Add events, with bounds checking
box1->addEvents(eventsCopy);
box->releaseEvents();
}
prog.report("Adding Events");
} while (it2.next());
this->progress(0.41, "Splitting Boxes");
Progress * prog2 = new Progress(this, 0.4, 0.9, 100);
ThreadScheduler * ts = new ThreadSchedulerFIFO();
ThreadPool tp(ts, 0, prog2);
ws1->splitAllIfNeeded(ts);
prog2->resetNumSteps( ts->size(), 0.4, 0.6);
tp.joinAll();
this->progress(0.95, "Refreshing cache");
ws1->refreshCache();
// Set a marker that the file-back-end needs updating if the # of events changed.
if (ws1->getNPoints() != initial_numEvents)
ws1->setFileNeedsUpdating(true);
}
void CreateMDWorkspace::finish(typename MDEventWorkspace<MDE, nd>::sptr ws)
{
// ------------ Set up the box controller ----------------------------------
BoxController_sptr bc = ws->getBoxController();
this->setBoxController(bc);
// Split to level 1
ws->splitBox();
// Do we split more due to MinRecursionDepth?
int minDepth = this->getProperty("MinRecursionDepth");
if (minDepth<0) throw std::invalid_argument("MinRecursionDepth must be >= 0.");
ws->setMinRecursionDepth(size_t(minDepth));
}
void CloneMDWorkspace::doClone(const typename MDEventWorkspace<MDE, nd>::sptr ws)
{
std::string outWSName = getPropertyValue("OutputWorkspace");
Progress prog(this, 0.0, 10.0, 100);
BoxController_sptr bc = ws->getBoxController();
if (!bc) throw std::runtime_error("Error with InputWorkspace: no BoxController!");
if (bc->isFileBacked())
{
// Generate a new filename to copy to
prog.report("Copying File");
std::string originalFile = bc->getFilename();
std::string outFilename = getPropertyValue("Filename");
if (outFilename.empty())
{
// Auto-generated name
Poco::Path path = Poco::Path(originalFile).absolute();
std::string newName = path.getBaseName() + "_clone." + path.getExtension();
path.setFileName(newName);
outFilename = path.toString();
}
// Perform the copying
g_log.notice() << "Cloned workspace file being copied to: " << outFilename << std::endl;
Poco::File(originalFile).copyTo(outFilename);
g_log.information() << "File copied successfully." << std::endl;
// Now load it back
IAlgorithm_sptr alg = createSubAlgorithm("LoadMD", 0.5, 1.0, false);
alg->setPropertyValue("Filename", outFilename);
alg->setPropertyValue("FileBackEnd", "1");
alg->setPropertyValue("Memory", "0"); //TODO: How much memory?
alg->setPropertyValue("OutputWorkspace", outWSName);
alg->executeAsSubAlg();
// Set the output workspace to this
IMDEventWorkspace_sptr outWS = alg->getProperty("OutputWorkspace");
this->setProperty("OutputWorkspace", outWS);
}
else
{
// Perform the clone in memory.
boost::shared_ptr<MDEventWorkspace<MDE,nd> > outWS(new MDEventWorkspace<MDE,nd>(*ws));
this->setProperty("OutputWorkspace", boost::dynamic_pointer_cast<IMDEventWorkspace>(outWS) );
}
}
开发者ID:,项目名称:,代码行数:46,代码来源:
示例6: doLoad
void LoadMD::doLoad(typename MDEventWorkspace<MDE, nd>::sptr ws) {
// Are we using the file back end?
bool fileBackEnd = getProperty("FileBackEnd");
if (fileBackEnd && m_BoxStructureAndMethadata)
throw std::invalid_argument("Combination of BoxStructureOnly or "
"MetaDataOnly were set to TRUE with "
"fileBackEnd "
": this is not possible.");
CPUTimer tim;
auto prog = new Progress(this, 0.0, 1.0, 100);
prog->report("Opening file.");
std::string title;
try {
m_file->getAttr("title", title);
} catch (std::exception &) {
// Leave the title blank if error on loading
}
ws->setTitle(title);
// Load the WorkspaceHistory "process"
if (this->getProperty("LoadHistory")) {
ws->history().loadNexus(m_file.get());
}
this->loadAffineMatricies(boost::dynamic_pointer_cast<IMDWorkspace>(ws));
m_file->closeGroup();
m_file->close();
// Add each of the dimension
for (size_t d = 0; d < nd; d++)
ws->addDimension(m_dims[d]);
// Coordinate system
ws->setCoordinateSystem(m_coordSystem);
// ----------------------------------------- Box Structure
// ------------------------------
prog->report("Reading box structure from HDD.");
MDBoxFlatTree FlatBoxTree;
int nDims = static_cast<int>(nd); // should be safe
FlatBoxTree.loadBoxStructure(m_filename, nDims, MDE::getTypeName());
BoxController_sptr bc = ws->getBoxController();
bc->fromXMLString(FlatBoxTree.getBCXMLdescr());
prog->report("Restoring box structure and connectivity");
std::vector<API::IMDNode *> boxTree;
FlatBoxTree.restoreBoxTree(boxTree, bc, fileBackEnd,
m_BoxStructureAndMethadata);
size_t numBoxes = boxTree.size();
// ---------------------------------------- DEAL WITH BOXES
// ------------------------------------
if (fileBackEnd) { // TODO:: call to the file format factory
auto loader = boost::shared_ptr<API::IBoxControllerIO>(
new DataObjects::BoxControllerNeXusIO(bc.get()));
loader->setDataType(sizeof(coord_t), MDE::getTypeName());
bc->setFileBacked(loader, m_filename);
// boxes have been already made file-backed when restoring the boxTree;
// How much memory for the cache?
{
// TODO: Clean up, only a write buffer now
double mb = getProperty("Memory");
// Defaults have changed, default disk buffer size should be 10 data
// chunks TODO: find optimal, 100 may be better.
if (mb <= 0)
mb = double(10 * loader->getDataChunk() * sizeof(MDE)) /
double(1024 * 1024);
// Express the cache memory in units of number of events.
uint64_t cacheMemory =
static_cast<uint64_t>((mb * 1024. * 1024.) / sizeof(MDE)) + 1;
// Set these values in the diskMRU
bc->getFileIO()->setWriteBufferSize(cacheMemory);
g_log.information() << "Setting a DiskBuffer cache size of " << mb
<< " MB, or " << cacheMemory << " events.\n";
}
} // Not file back end
else if (!m_BoxStructureAndMethadata) {
// ---------------------------------------- READ IN THE BOXES
// ------------------------------------
// TODO:: call to the file format factory
auto loader =
file_holder_type(new DataObjects::BoxControllerNeXusIO(bc.get()));
loader->setDataType(sizeof(coord_t), MDE::getTypeName());
loader->openFile(m_filename, "r");
const std::vector<uint64_t> &BoxEventIndex = FlatBoxTree.getEventIndex();
prog->setNumSteps(numBoxes);
for (size_t i = 0; i < numBoxes; i++) {
prog->report();
MDBox<MDE, nd> *box = dynamic_cast<MDBox<MDE, nd> *>(boxTree[i]);
//.........这里部分代码省略.........
void CompareMDWorkspaces::compareMDWorkspaces(
typename MDEventWorkspace<MDE, nd>::sptr ws) {
typename MDEventWorkspace<MDE, nd>::sptr ws1 = ws;
typename MDEventWorkspace<MDE, nd>::sptr ws2 =
boost::dynamic_pointer_cast<MDEventWorkspace<MDE, nd>>(inWS2);
if (!ws1 || !ws2)
throw std::runtime_error("Incompatible workspace types passed to PlusMD.");
std::vector<API::IMDNode *> boxes1;
std::vector<API::IMDNode *> boxes2;
ws1->getBox()->getBoxes(boxes1, 1000, false);
ws2->getBox()->getBoxes(boxes2, 1000, false);
this->compare(boxes1.size(), boxes2.size(),
"Workspaces do not have the same number of boxes");
for (size_t j = 0; j < boxes1.size(); j++) {
API::IMDNode *box1 = boxes1[j];
API::IMDNode *box2 = boxes2[j];
if (m_CompareBoxID)
this->compare(box1->getID(), box2->getID(), "Boxes have different ID");
else {
if (box1->getID() != box2->getID())
g_log.debug() << " Boxes N: " << j << " have box ID: " << box1->getID()
<< " and " << box2->getID() << " correspondingly\n";
}
this->compare(size_t(box1->getDepth()), size_t(box2->getDepth()),
"Boxes are at a different depth");
this->compare(box1->getNumChildren(), box2->getNumChildren(),
"Boxes do not have the same number of children");
for (size_t i = 0; i < box1->getNumChildren(); i++) {
if (m_CompareBoxID)
this->compare(box1->getChild(i)->getID(), box2->getChild(i)->getID(),
"Child of boxes do not match IDs");
else {
if (box1->getID() != box2->getID())
g_log.debug() << " Boxes N: " << j << " children N: " << i
<< " have box ID: " << box1->getChild(i)->getID()
<< " and " << box2->getChild(i)->getID()
<< " correspondingly\n";
}
}
for (size_t d = 0; d < nd; d++) {
this->compareTol(box1->getExtents(d).getMin(),
box2->getExtents(d).getMin(),
"Extents of box do not match");
this->compareTol(box1->getExtents(d).getMax(),
box2->getExtents(d).getMax(),
"Extents of box do not match");
}
this->compareTol(box1->getInverseVolume(), box2->getInverseVolume(),
"Box inverse volume does not match");
this->compareTol(box1->getSignal(), box2->getSignal(),
"Box signal does not match");
this->compareTol(box1->getErrorSquared(), box2->getErrorSquared(),
"Box error squared does not match");
if (m_CheckEvents)
this->compare(box1->getNPoints(), box2->getNPoints(),
"Number of points in box does not match");
// Are both MDGridBoxes ?
MDGridBox<MDE, nd> *gridbox1 = dynamic_cast<MDGridBox<MDE, nd> *>(box1);
MDGridBox<MDE, nd> *gridbox2 = dynamic_cast<MDGridBox<MDE, nd> *>(box2);
if (gridbox1 && gridbox2) {
for (size_t d = 0; d < nd; d++)
this->compareTol(gridbox1->getBoxSize(d), gridbox2->getBoxSize(d),
"Box sizes do not match");
}
// Are both MDBoxes (with events)
MDBox<MDE, nd> *mdbox1 = dynamic_cast<MDBox<MDE, nd> *>(box1);
MDBox<MDE, nd> *mdbox2 = dynamic_cast<MDBox<MDE, nd> *>(box2);
if (mdbox1 && mdbox2) {
if (m_CheckEvents) {
const std::vector<MDE> &events1 = mdbox1->getConstEvents();
const std::vector<MDE> &events2 = mdbox2->getConstEvents();
try {
this->compare(events1.size(), events2.size(),
"Box event vectors are not the same length");
if (events1.size() == events2.size() && events1.size() > 2) {
// Check first and last event
for (size_t i = 0; i < events1.size(); i++) {
for (size_t d = 0; d < nd; d++) {
this->compareTol(events1[i].getCenter(d),
events2[i].getCenter(d),
"Event center does not match");
}
this->compareTol(events1[i].getSignal(), events2[i].getSignal(),
"Event signal does not match");
this->compareTol(events1[i].getErrorSquared(),
events2[i].getErrorSquared(),
"Event error does not match");
}
}
} catch (CompareFailsException &) {
//.........这里部分代码省略.........
void FindPeaksMD::findPeaks(typename MDEventWorkspace<MDE, nd>::sptr ws)
{
if (nd < 3)
throw std::invalid_argument("Workspace must have at least 3 dimensions.");
progress(0.01, "Refreshing Centroids");
// TODO: This might be slow, progress report?
// Make sure all centroids are fresh
ws->getBox()->refreshCentroid();
typedef IMDBox<MDE,nd>* boxPtr;
if (ws->getNumExperimentInfo() == 0)
throw std::runtime_error("No instrument was found in the MDEventWorkspace. Cannot find peaks.");
// TODO: Do we need to pick a different instrument info?
ExperimentInfo_sptr ei = ws->getExperimentInfo(0);
// Instrument associated with workspace
Geometry::Instrument_const_sptr inst = ei->getInstrument();
// Find the run number
int runNumber = ei->getRunNumber();
// Check that the workspace dimensions are in Q-sample-frame or Q-lab-frame.
eDimensionType dimType;
std::string dim0 = ws->getDimension(0)->getName();
if (dim0 == "H")
{
dimType = HKL;
throw std::runtime_error("Cannot find peaks in a workspace that is already in HKL space.");
}
else if (dim0 == "Q_lab_x")
{
dimType = QLAB;
}
else if (dim0 == "Q_sample_x")
dimType = QSAMPLE;
else
throw std::runtime_error("Unexpected dimensions: need either Q_lab_x or Q_sample_x.");
// Find the goniometer rotation matrix
Mantid::Kernel::Matrix<double> goniometer(3,3, true); // Default IDENTITY matrix
try
{
goniometer = ei->mutableRun().getGoniometerMatrix();
}
catch (std::exception & e)
{
g_log.warning() << "Error finding goniometer matrix. It will not be set in the peaks found." << std::endl;
g_log.warning() << e.what() << std::endl;
}
/// Arbitrary scaling factor for density to make more manageable numbers, especially for older file formats.
signal_t densityScalingFactor = 1e-6;
// Calculate a threshold below which a box is too diffuse to be considered a peak.
signal_t thresholdDensity = 0.0;
thresholdDensity = ws->getBox()->getSignalNormalized() * DensityThresholdFactor * densityScalingFactor;
g_log.notice() << "Threshold signal density: " << thresholdDensity << std::endl;
// We will fill this vector with pointers to all the boxes (up to a given depth)
typename std::vector<boxPtr> boxes;
// Get all the MDboxes
progress(0.10, "Getting Boxes");
ws->getBox()->getBoxes(boxes, 1000, true);
// TODO: Here keep only the boxes > e.g. 3 * mean.
typedef std::pair<double, boxPtr> dens_box;
// Map that will sort the boxes by increasing density. The key = density; value = box *.
typename std::multimap<double, boxPtr> sortedBoxes;
progress(0.20, "Sorting Boxes by Density");
typename std::vector<boxPtr>::iterator it1;
typename std::vector<boxPtr>::iterator it1_end = boxes.end();
for (it1 = boxes.begin(); it1 != it1_end; it1++)
{
boxPtr box = *it1;
double density = box->getSignalNormalized() * densityScalingFactor;
// Skip any boxes with too small a signal density.
if (density > thresholdDensity)
sortedBoxes.insert(dens_box(density,box));
}
// List of chosen possible peak boxes.
std::vector<boxPtr> peakBoxes;
prog = new Progress(this, 0.30, 0.95, MaxPeaks);
int64_t numBoxesFound = 0;
// Now we go (backwards) through the map
// e.g. from highest density down to lowest density.
typename std::multimap<double, boxPtr>::reverse_iterator it2;
typename std::multimap<double, boxPtr>::reverse_iterator it2_end = sortedBoxes.rend();
for (it2 = sortedBoxes.rbegin(); it2 != it2_end; it2++)
{
//.........这里部分代码省略.........
开发者ID:,项目名称:,代码行数:101,代码来源:
示例9: doSaveEvents
void SaveMD::doSaveEvents(typename MDEventWorkspace<MDE, nd>::sptr ws) {
std::string filename = getPropertyValue("Filename");
bool update = getProperty("UpdateFileBackEnd");
bool MakeFileBacked = getProperty("MakeFileBacked");
bool wsIsFileBacked = ws->isFileBacked();
if (update && MakeFileBacked)
throw std::invalid_argument(
"Please choose either UpdateFileBackEnd or MakeFileBacked, not both.");
if (MakeFileBacked && wsIsFileBacked)
throw std::invalid_argument(
"You picked MakeFileBacked but the workspace is already file-backed!");
BoxController_sptr bc = ws->getBoxController();
if (!wsIsFileBacked) { // Erase the file if it exists
Poco::File oldFile(filename);
if (oldFile.exists())
oldFile.remove();
}
auto prog = new Progress(this, 0.0, 0.05, 1);
if (update) // workspace has its own file and ignores any changes to the
// algorithm parameters
{
if (!ws->isFileBacked())
throw std::runtime_error(" attempt to update non-file backed workspace");
filename = bc->getFileIO()->getFileName();
}
//-----------------------------------------------------------------------------------------------------
// create or open WS group and put there additional information about WS and
// its dimensions
int nDims = static_cast<int>(nd);
bool data_exist;
auto file = file_holder_type(MDBoxFlatTree::createOrOpenMDWSgroup(
filename, nDims, MDE::getTypeName(), false, data_exist));
// Save each NEW ExperimentInfo to a spot in the file
MDBoxFlatTree::saveExperimentInfos(file.get(), ws);
if (!update || !data_exist) {
MDBoxFlatTree::saveWSGenericInfo(file.get(), ws);
}
file->closeGroup();
file->close();
MDBoxFlatTree BoxFlatStruct;
//-----------------------------------------------------------------------------------------------------
if (update) // the workspace is already file backed;
{
// remove all boxes from the DiskBuffer. DB will calculate boxes positions
// on HDD.
bc->getFileIO()->flushCache();
// flatten the box structure; this will remember boxes file positions in the
// box structure
BoxFlatStruct.initFlatStructure(ws, filename);
} else // not file backed;
{
// the boxes file positions are unknown and we need to calculate it.
BoxFlatStruct.initFlatStructure(ws, filename);
// create saver class
auto Saver = boost::shared_ptr<API::IBoxControllerIO>(
new DataObjects::BoxControllerNeXusIO(bc.get()));
Saver->setDataType(sizeof(coord_t), MDE::getTypeName());
if (MakeFileBacked) {
// store saver with box controller
bc->setFileBacked(Saver, filename);
// get access to boxes array
std::vector<API::IMDNode *> &boxes = BoxFlatStruct.getBoxes();
// calculate the position of the boxes on file, indicating to make them
// saveable and that the boxes were not saved.
BoxFlatStruct.setBoxesFilePositions(true);
prog->resetNumSteps(boxes.size(), 0.06, 0.90);
for (auto &boxe : boxes) {
auto saveableTag = boxe->getISaveable();
if (saveableTag) // only boxes can be saveable
{
// do not spend time on empty boxes
if (boxe->getDataInMemorySize() == 0)
continue;
// save boxes directly using the boxes file postion, precalculated in
// boxFlatStructure.
saveableTag->save();
// remove boxes data from memory. This will actually correctly set the
// tag indicatin that data were not loaded.
saveableTag->clearDataFromMemory();
// put boxes into write buffer wich will save them when necessary
// Saver->toWrite(saveTag);
prog->report("Saving Box");
}
}
// remove everything from diskBuffer; (not sure if it really necessary
// but just in case , should not make any harm)
Saver->flushCache();
// drop NeXus on HDD (not sure if it really necessary but just in case )
Saver->flushData();
} else // just save data, and finish with it
{
Saver->openFile(filename, "w");
//.........这里部分代码省略.........
void BinToMDHistoWorkspace::binByIterating(typename MDEventWorkspace<MDE, nd>::sptr ws)
{
BoxController_sptr bc = ws->getBoxController();
// Start with signal at 0.0
outWS->setTo(0.0, 0.0);
// Cache some data to speed up accessing them a bit
indexMultiplier = new size_t[outD];
for (size_t d=0; d<outD; d++)
{
if (d > 0)
indexMultiplier[d] = outWS->getIndexMultiplier()[d-1];
else
indexMultiplier[d] = 1;
}
signals = outWS->getSignalArray();
errors = outWS->getErrorSquaredArray();
// The dimension (in the output workspace) along which we chunk for parallel processing
// TODO: Find the smartest dimension to chunk against
size_t chunkDimension = 0;
// How many bins (in that dimension) per chunk.
// Try to split it so each core will get 2 tasks:
int chunkNumBins = int(binDimensions[chunkDimension]->getNBins() / (Mantid::Kernel::ThreadPool::getNumPhysicalCores() * 2));
if (chunkNumBins < 1) chunkNumBins = 1;
// Do we actually do it in parallel?
bool doParallel = getProperty("Parallel");
// Not if file-backed!
if (bc->isFileBacked()) doParallel = false;
if (!doParallel)
chunkNumBins = int(binDimensions[chunkDimension]->getNBins());
// Total number of steps
size_t progNumSteps = 0;
if (prog) prog->setNotifyStep(0.1);
if (prog) prog->resetNumSteps(100, 0.00, 1.0);
// Run the chunks in parallel. There is no overlap in the output workspace so it is
// thread safe to write to it..
PRAGMA_OMP( parallel for schedule(dynamic,1) if (doParallel) )
for(int chunk=0; chunk < int(binDimensions[chunkDimension]->getNBins()); chunk += chunkNumBins)
{
PARALLEL_START_INTERUPT_REGION
// Region of interest for this chunk.
size_t * chunkMin = new size_t[outD];
size_t * chunkMax = new size_t[outD];
for (size_t bd=0; bd<outD; bd++)
{
// Same limits in the other dimensions
chunkMin[bd] = 0;
chunkMax[bd] = binDimensions[bd]->getNBins();
}
// Parcel out a chunk in that single dimension dimension
chunkMin[chunkDimension] = size_t(chunk);
if (size_t(chunk+chunkNumBins) > binDimensions[chunkDimension]->getNBins())
chunkMax[chunkDimension] = binDimensions[chunkDimension]->getNBins();
else
chunkMax[chunkDimension] = size_t(chunk+chunkNumBins);
// Build an implicit function (it needs to be in the space of the MDEventWorkspace)
MDImplicitFunction * function = this->getImplicitFunctionForChunk(chunkMin, chunkMax);
// Use getBoxes() to get an array with a pointer to each box
std::vector<IMDBox<MDE,nd>*> boxes;
// Leaf-only; no depth limit; with the implicit function passed to it.
ws->getBox()->getBoxes(boxes, 1000, true, function);
// Sort boxes by file position IF file backed. This reduces seeking time, hopefully.
if (bc->isFileBacked())
IMDBox<MDE, nd>::sortBoxesByFilePos(boxes);
// For progress reporting, the # of boxes
if (prog)
{
PARALLEL_CRITICAL(BinToMDHistoWorkspace_progress)
{
std::cout << "Chunk " << chunk << ": found " << boxes.size() << " boxes within the implicit function." << std::endl;
progNumSteps += boxes.size();
prog->setNumSteps( progNumSteps );
}
}
// Go through every box for this chunk.
for (size_t i=0; i<boxes.size(); i++)
{
MDBox<MDE,nd> * box = dynamic_cast<MDBox<MDE,nd> *>(boxes[i]);
// Perform the binning in this separate method.
if (box)
this->binMDBox(box, chunkMin, chunkMax);
// Progress reporting
if (prog) prog->report();
}// for each box in the vector
PARALLEL_END_INTERUPT_REGION
} // for each chunk in parallel
PARALLEL_CHECK_INTERUPT_REGION
//.........这里部分代码省略.........
开发者ID:,项目名称:,代码行数:101,代码来源:
示例11: slice
void SliceMD::slice(typename MDEventWorkspace<MDE, nd>::sptr ws) {
// Create the ouput workspace
typename MDEventWorkspace<OMDE, ond>::sptr outWS(
new MDEventWorkspace<OMDE, ond>());
for (size_t od = 0; od < m_binDimensions.size(); od++) {
outWS->addDimension(m_binDimensions[od]);
}
outWS->setCoordinateSystem(ws->getSpecialCoordinateSystem());
outWS->initialize();
// Copy settings from the original box controller
BoxController_sptr bc = ws->getBoxController();
// store wrute buffer size for the future
// uint64_t writeBufSize =
// bc->getFileIO()getDiskBuffer().getWriteBufferSize();
// and disable write buffer (if any) for input MD Events for this algorithm
// purposes;
// bc->setCacheParameters(1,0);
BoxController_sptr obc = outWS->getBoxController();
// Use the "number of bins" as the "split into" parameter
for (size_t od = 0; od < m_binDimensions.size(); od++)
obc->setSplitInto(od, m_binDimensions[od]->getNBins());
obc->setSplitThreshold(bc->getSplitThreshold());
bool bTakeDepthFromInputWorkspace =
getProperty("TakeMaxRecursionDepthFromInput");
int tempDepth = getProperty("MaxRecursionDepth");
size_t maxDepth =
bTakeDepthFromInputWorkspace ? bc->getMaxDepth() : size_t(tempDepth);
obc->setMaxDepth(maxDepth);
// size_t outputSize = writeBufSize;
// obc->setCacheParameters(sizeof(OMDE),outputSize);
obc->resetNumBoxes();
// Perform the first box splitting
outWS->splitBox();
size_t lastNumBoxes = obc->getTotalNumMDBoxes();
// --- File back end ? ----------------
std::string filename = getProperty("OutputFilename");
if (!filename.empty()) {
// First save to the NXS file
g_log.notice() << "Running SaveMD to create file back-end" << std::endl;
IAlgorithm_sptr alg = createChildAlgorithm("SaveMD");
alg->setPropertyValue("Filename", filename);
alg->setProperty("InputWorkspace", outWS);
alg->setProperty("MakeFileBacked", true);
alg->executeAsChildAlg();
if (!obc->isFileBacked())
throw std::runtime_error("SliceMD with file-backed output: Can not set "
"up file-backed output workspace ");
auto IOptr = obc->getFileIO();
size_t outBufSize = IOptr->getWriteBufferSize();
// the buffer size for resulting workspace; reasonable size is at least 10
// data chunk sizes (nice to verify)
if (outBufSize < 10 * IOptr->getDataChunk()) {
outBufSize = 10 * IOptr->getDataChunk();
IOptr->setWriteBufferSize(outBufSize);
}
}
// Function defining which events (in the input dimensions) to place in the
// output
MDImplicitFunction *function = this->getImplicitFunctionForChunk(NULL, NULL);
std::vector<API::IMDNode *> boxes;
// Leaf-only; no depth limit; with the implicit function passed to it.
ws->getBox()->getBoxes(boxes, 1000, true, function);
// Sort boxes by file position IF file backed. This reduces seeking time,
// hopefully.
bool fileBackedWS = bc->isFileBacked();
if (fileBackedWS)
API::IMDNode::sortObjByID(boxes);
Progress *prog = new Progress(this, 0.0, 1.0, boxes.size());
// The root of the output workspace
MDBoxBase<OMDE, ond> *outRootBox = outWS->getBox();
// if target workspace has events, we should count them as added
uint64_t totalAdded = outWS->getNEvents();
uint64_t numSinceSplit = 0;
// Go through every box for this chunk.
// PARALLEL_FOR_IF( !bc->isFileBacked() )
for (int i = 0; i < int(boxes.size()); i++) {
MDBox<MDE, nd> *box = dynamic_cast<MDBox<MDE, nd> *>(boxes[i]);
// Perform the binning in this separate method.
if (box) {
// An array to hold the rotated/transformed coordinates
coord_t outCenter[ond];
const std::vector<MDE> &events = box->getConstEvents();
typename std::vector<MDE>::const_iterator it = events.begin();
//.........这里部分代码省略.........
void PlusMD::doPlus(typename MDEventWorkspace<MDE, nd>::sptr ws)
{
typename MDEventWorkspace<MDE, nd>::sptr ws1 = ws;
typename MDEventWorkspace<MDE, nd>::sptr ws2 = boost::dynamic_pointer_cast<MDEventWorkspace<MDE, nd> >(m_operand_event);
if (!ws1 || !ws2)
throw std::runtime_error("Incompatible workspace types passed to PlusMD.");
MDBoxBase<MDE,nd> * box1 = ws1->getBox();
MDBoxBase<MDE,nd> * box2 = ws2->getBox();
Progress prog(this, 0.0, 0.4, box2->getBoxController()->getTotalNumMDBoxes());
// How many events you started with
size_t initial_numEvents = ws1->getNPoints();
// Make a leaf-only iterator through all boxes with events in the RHS workspace
MDBoxIterator<MDE,nd> it2(box2, 1000, true);
do
{
MDBox<MDE,nd> * box = dynamic_cast<MDBox<MDE,nd> *>(it2.getBox());
if (box)
{
// Copy the events from WS2 and add them into WS1
const std::vector<MDE> & events = box->getConstEvents();
// Add events, with bounds checking
box1->addEvents(events);
box->releaseEvents();
}
prog.report("Adding Events");
} while (it2.next());
this->progress(0.41, "Splitting Boxes");
Progress * prog2 = new Progress(this, 0.4, 0.9, 100);
ThreadScheduler * ts = new ThreadSchedulerFIFO();
ThreadPool tp(ts, 0, prog2);
ws1->splitAllIfNeeded(ts);
prog2->resetNumSteps( ts->size(), 0.4, 0.6);
tp.joinAll();
// // Now we need to save all the data that was not saved before.
// if (ws1->isFileBacked())
// {
// // Flush anything else in the to-write buffer
// BoxController_sptr bc = ws1->getBoxController();
//
// prog.resetNumSteps(bc->getTotalNumMDBoxes(), 0.6, 1.0);
// MDBoxIterator<MDE,nd> it1(box1, 1000, true);
// while (true)
// {
// MDBox<MDE,nd> * box = dynamic_cast<MDBox<MDE,nd> *>(it1.getBox());
// if (box)
// {
// // Something was maybe added to this box
// if (box->getEventVectorSize() > 0)
// {
// // By getting the events, this will merge the newly added and the cached events.
// box->getEvents();
// // The MRU to-write cache will optimize writes by reducing seek times
// box->releaseEvents();
// }
// }
// prog.report("Saving");
// if (!it1.next()) break;
// }
// //bc->getDiskBuffer().flushCache();
// // Flush the data writes to disk.
// box1->flushData();
// }
this->progress(0.95, "Refreshing cache");
ws1->refreshCache();
// Set a marker that the file-back-end needs updating if the # of events changed.
if (ws1->getNPoints() != initial_numEvents)
ws1->setFileNeedsUpdating(true);
}
void FakeMDEventData::addFakePeak(typename MDEventWorkspace<MDE, nd>::sptr ws) {
std::vector<double> params = getProperty("PeakParams");
bool RandomizeSignal = getProperty("RandomizeSignal");
if (params.empty())
return;
if (params.size() != nd + 2)
throw std::invalid_argument("PeakParams needs to have ndims+2 arguments.");
if (params[0] <= 0)
throw std::invalid_argument("PeakParams: number_of_events needs to be > 0");
size_t num = size_t(params[0]);
Progress prog(this, 0.0, 1.0, 100);
size_t progIncrement = num / 100;
if (progIncrement == 0)
progIncrement = 1;
// Width of the peak
double desiredRadius = params.back();
boost::mt19937 rng;
boost::uniform_real<coord_t> u2(0, 1.0); // Random from 0 to 1.0
boost::variate_generator<boost::mt19937 &, boost::uniform_real<coord_t>>
genUnit(rng, u2);
int randomSeed = getProperty("RandomSeed");
rng.seed((unsigned int)(randomSeed));
// Inserter to help choose the correct event type
auto eventHelper =
MDEvents::MDEventInserter<typename MDEventWorkspace<MDE, nd>::sptr>(ws);
for (size_t i = 0; i < num; ++i) {
// Algorithm to generate points along a random n-sphere (sphere with not
// necessarily 3 dimensions)
// from http://en.wikipedia.org/wiki/N-sphere as of May 6, 2011.
// First, points in a hyper-cube of size 1.0, centered at 0.
coord_t centers[nd];
coord_t radiusSquared = 0;
for (size_t d = 0; d < nd; d++) {
centers[d] = genUnit() - 0.5f; // Distribute around +- the center
radiusSquared += centers[d] * centers[d];
}
// Make a unit vector pointing in this direction
coord_t radius = static_cast<coord_t>(sqrt(radiusSquared));
for (size_t d = 0; d < nd; d++)
centers[d] /= radius;
// Now place the point along this radius, scaled with ^1/n for uniformity.
coord_t radPos = genUnit();
radPos = static_cast<coord_t>(
pow(radPos, static_cast<coord_t>(1.0 / static_cast<coord_t>(nd))));
for (size_t d = 0; d < nd; d++) {
// Multiply by the scaling and the desired peak radius
centers[d] *= (radPos * static_cast<coord_t>(desiredRadius));
// Also offset by the center of the peak, as taken in Params
centers[d] += static_cast<coord_t>(params[d + 1]);
}
// Default or randomized error/signal
float signal = 1.0;
float errorSquared = 1.0;
if (RandomizeSignal) {
signal = float(0.5 + genUnit());
errorSquared = float(0.5 + genUnit());
}
// Create and add the event.
eventHelper.insertMDEvent(signal, errorSquared, 1, pickDetectorID(),
centers); // 1 = run number
// Progress report
if ((i % progIncrement) == 0)
prog.report();
}
ws->splitBox();
Kernel::ThreadScheduler *ts = new ThreadSchedulerFIFO();
ThreadPool tp(ts);
ws->splitAllIfNeeded(ts);
tp.joinAll();
ws->refreshCache();
}
请发表评论