/** Execute the algorithm. */ void TransformMD::exec() { Mantid::API::IMDWorkspace_sptr inWS; Mantid::API::IMDWorkspace_sptr outWS; inWS = getProperty("InputWorkspace"); outWS = getProperty("OutputWorkspace"); if (boost::dynamic_pointer_cast<MatrixWorkspace>(inWS)) throw std::runtime_error("TransformMD can only transform a " "MDHistoWorkspace or a MDEventWorkspace."); if (outWS != inWS) { // NOT in-place. So first we clone inWS into outWS IAlgorithm_sptr clone = this->createChildAlgorithm("CloneMDWorkspace", 0.0, 0.5, true); clone->setProperty("InputWorkspace", inWS); clone->executeAsChildAlg(); outWS = clone->getProperty("OutputWorkspace"); } if (!outWS) throw std::runtime_error("Invalid output workspace."); size_t nd = outWS->getNumDims(); m_scaling = getProperty("Scaling"); m_offset = getProperty("Offset"); // Replicate single values if (m_scaling.size() == 1) m_scaling = std::vector<double>(nd, m_scaling[0]); if (m_offset.size() == 1) m_offset = std::vector<double>(nd, m_offset[0]); // Check the size if (m_scaling.size() != nd) throw std::invalid_argument("Scaling argument must be either length 1 or " "match the number of dimensions."); if (m_offset.size() != nd) throw std::invalid_argument("Offset argument must be either length 1 or " "match the number of dimensions."); // Transform the dimensions outWS->transformDimensions(m_scaling, m_offset); MDHistoWorkspace_sptr histo = boost::dynamic_pointer_cast<MDHistoWorkspace>(outWS); IMDEventWorkspace_sptr event = boost::dynamic_pointer_cast<IMDEventWorkspace>(outWS); if (histo) { // Recalculate all the values since the dimensions changed. histo->cacheValues(); } else if (event) { // Call the method for this type of MDEventWorkspace. CALL_MDEVENT_FUNCTION(this->doTransform, outWS); } this->setProperty("OutputWorkspace", outWS); }
/** Free helper function. try to fetch the workspace index. @param ws : The workspace to find the dimensions in @param candidateNameOrId: Either the name or the id of a dimension in the workspace. @return the index of the dimension in the workspace. @throws runtime_error if the requested dimension is unknown either by id, or by name in the workspace. */ size_t tryFetchDimensionIndex(Mantid::API::IMDWorkspace_sptr ws, const std::string &candidateNameOrId) { size_t dimWorkspaceIndex; try { dimWorkspaceIndex = ws->getDimensionIndexById(candidateNameOrId); } catch (const std::runtime_error &) { // this will throw if the name is unknown. dimWorkspaceIndex = ws->getDimensionIndexByName(candidateNameOrId); } return dimWorkspaceIndex; }
/** * Set the minimum and maximum of the workspace data. Code essentially copied from SignalRange.cpp * @param workspace Rreference to an IMD workspace * @returns The minimum and maximum value of the workspace dataset. */ QwtDoubleInterval MetaDataExtractorUtils::getMinAndMax(Mantid::API::IMDWorkspace_sptr workspace) { if (!workspace) throw std::invalid_argument("The workspace is empty."); auto iterators = workspace->createIterators(PARALLEL_GET_MAX_THREADS, 0); std::vector<QwtDoubleInterval> intervals(iterators.size()); // cppcheck-suppress syntaxError PRAGMA_OMP( parallel for schedule(dynamic, 1)) for (int i=0; i < int(iterators.size()); i++) { Mantid::API::IMDIterator * it = iterators[i]; QwtDoubleInterval range = this->getRange(it); intervals[i] = range; // don't delete iterator in parallel. MSVC doesn't like it // when the iterator points to a mock object. } // Combine the overall min/max double minSignal = DBL_MAX; double maxSignal = -DBL_MAX; auto inf = std::numeric_limits<double>::infinity(); for (size_t i=0; i < iterators.size(); i++) { delete iterators[i]; double signal; signal = intervals[i].minValue(); if (signal != inf && signal < minSignal) minSignal = signal; signal = intervals[i].maxValue(); if (signal != inf && signal > maxSignal) maxSignal = signal; } // Set the lowest element to the smallest non-zero element. if (minSignal == DBL_MAX) { minSignal = defaultMin; maxSignal = defaultMax; } QwtDoubleInterval minMaxContainer; if (minSignal < maxSignal) minMaxContainer = QwtDoubleInterval(minSignal, maxSignal); else { if (minSignal != 0) // Possibly only one value in range minMaxContainer = QwtDoubleInterval(minSignal*0.5, minSignal*1.5); else // Other default value minMaxContainer = QwtDoubleInterval(defaultMin, defaultMax); } return minMaxContainer; }
/** Set the workspace being sliced * * @param ws :: IMDWorkspace */ void LineViewer::setWorkspace(Mantid::API::IMDWorkspace_sptr ws) { m_ws = ws; m_thickness = VMD(ws->getNumDims()); createDimensionWidgets(); // Update the dimensions shown in the original workspace m_lineOptions->setOriginalWorkspace(m_ws); }
/** Set the original workspace, to show the axes plot choice */ void LinePlotOptions::setOriginalWorkspace(Mantid::API::IMDWorkspace_sptr ws) { if (!ws) return; for (size_t d = 0; d < (ws->getNumDims()); d++) { IMDDimension_const_sptr dim = ws->getDimension(d); std::string text = dim->getName(); std::string tooltip = "Use the " + dim->getName() + " dimension as the X plot axis."; const bool bIntegrated = dim->getIsIntegrated(); // Index into the radio buttons array int index = int(d) + 2; if (m_radPlots.size() > index) { m_radPlots[index]->setText(QString::fromStdString(text)); m_radPlots[index]->setToolTip(QString::fromStdString(tooltip)); } else addPlotRadioButton(text, tooltip, bIntegrated); } }
/** * Check the inputs for invalid values * @returns A map with validation warnings. */ std::map<std::string, std::string> SetMDFrame::validateInputs() { std::map<std::string, std::string> invalidProperties; Mantid::API::IMDWorkspace_sptr ws = getProperty("InputWorkspace"); if (!boost::dynamic_pointer_cast<Mantid::API::IMDEventWorkspace>(ws) && !boost::dynamic_pointer_cast<Mantid::API::IMDHistoWorkspace>(ws)) { invalidProperties.insert( std::make_pair("InputWorkspace", "The input workspace has to be either " "an MDEvent or MDHisto Workspace.")); } std::vector<int> axesInts = this->getProperty("Axes"); Kernel::MDAxisValidator axisChecker(axesInts, ws->getNumDims(), true); auto axisErrors = axisChecker.validate(); for (auto iter = axisErrors.begin(); iter != axisErrors.end(); iter++) { invalidProperties.insert(*iter); } return invalidProperties; }
/** Compare the dimensions etc. of two MDWorkspaces */ void CompareMDWorkspaces::compareMDGeometry( Mantid::API::IMDWorkspace_sptr ws1, Mantid::API::IMDWorkspace_sptr ws2) { compare(ws1->getNumDims(), ws2->getNumDims(), "Workspaces have a different number of dimensions"); for (size_t d = 0; d < ws1->getNumDims(); d++) { IMDDimension_const_sptr dim1 = ws1->getDimension(d); IMDDimension_const_sptr dim2 = ws2->getDimension(d); compare(dim1->getName(), dim2->getName(), "Dimension #" + Strings::toString(d) + " has a different name"); compare(dim1->getUnits(), dim2->getUnits(), "Dimension #" + Strings::toString(d) + " has different units"); compare(dim1->getNBins(), dim2->getNBins(), "Dimension #" + Strings::toString(d) + " has a different number of bins"); compareTol(dim1->getMinimum(), dim2->getMinimum(), "Dimension #" + Strings::toString(d) + " has a different minimum"); compareTol(dim1->getMaximum(), dim2->getMaximum(), "Dimension #" + Strings::toString(d) + " has a different maximum"); } }
/** Execute the algorithm. */ void TransformMD::exec() { Mantid::API::IMDWorkspace_sptr inWS; Mantid::API::IMDWorkspace_sptr outWS; inWS = getProperty("InputWorkspace"); outWS = getProperty("OutputWorkspace"); std::string outName = getPropertyValue("OutputWorkspace"); if (boost::dynamic_pointer_cast<MatrixWorkspace>(inWS)) throw std::runtime_error("TransformMD can only transform a " "MDHistoWorkspace or a MDEventWorkspace."); if (outWS != inWS) { // NOT in-place. So first we clone inWS into outWS IAlgorithm_sptr clone = this->createChildAlgorithm("CloneMDWorkspace", 0.0, 0.5, true); clone->setProperty("InputWorkspace", inWS); clone->executeAsChildAlg(); outWS = clone->getProperty("OutputWorkspace"); } if (!outWS) throw std::runtime_error("Invalid output workspace."); size_t nd = outWS->getNumDims(); m_scaling = getProperty("Scaling"); m_offset = getProperty("Offset"); // Replicate single values if (m_scaling.size() == 1) m_scaling = std::vector<double>(nd, m_scaling[0]); if (m_offset.size() == 1) m_offset = std::vector<double>(nd, m_offset[0]); // Check the size if (m_scaling.size() != nd) throw std::invalid_argument("Scaling argument must be either length 1 or " "match the number of dimensions."); if (m_offset.size() != nd) throw std::invalid_argument("Offset argument must be either length 1 or " "match the number of dimensions."); // Transform the dimensions outWS->transformDimensions(m_scaling, m_offset); MDHistoWorkspace_sptr histo = boost::dynamic_pointer_cast<MDHistoWorkspace>(outWS); IMDEventWorkspace_sptr event = boost::dynamic_pointer_cast<IMDEventWorkspace>(outWS); if (histo) { // Recalculate all the values since the dimensions changed. histo->cacheValues(); // Expect first 3 dimensions to be -1 for changing conventions for (int i = 0; i < static_cast<int>(m_scaling.size()); i++) if (m_scaling[i] < 0) { std::vector<int> axes(m_scaling.size()); // vector with ints. std::iota(std::begin(axes), std::end(axes), 0); // Fill with 0, 1, ... axes[0] = i; axes[i] = 0; if (i > 0) histo = transposeMD(histo, axes); signal_t *signals = histo->getSignalArray(); signal_t *errorsSq = histo->getErrorSquaredArray(); signal_t *numEvents = histo->getNumEventsArray(); // Find the extents size_t nPoints = static_cast<size_t>(histo->getDimension(0)->getNBins()); size_t mPoints = 1; for (size_t k = 1; k < histo->getNumDims(); k++) { mPoints *= static_cast<size_t>(histo->getDimension(k)->getNBins()); } // other dimensions for (size_t j = 0; j < mPoints; j++) { this->reverse(signals + j * nPoints, nPoints); this->reverse(errorsSq + j * nPoints, nPoints); this->reverse(numEvents + j * nPoints, nPoints); } histo = transposeMD(histo, axes); } // Pass on the display normalization from the input workspace histo->setDisplayNormalization(inWS->displayNormalizationHisto()); this->setProperty("OutputWorkspace", histo); } else if (event) { // Call the method for this type of MDEventWorkspace. CALL_MDEVENT_FUNCTION(this->doTransform, outWS); Progress *prog2 = nullptr; ThreadScheduler *ts = new ThreadSchedulerFIFO(); ThreadPool tp(ts, 0, prog2); event->splitAllIfNeeded(ts); // prog2->resetNumSteps( ts->size(), 0.4, 0.6); tp.joinAll(); event->refreshCache(); // Set the special coordinate system. IMDEventWorkspace_sptr inEvent = boost::dynamic_pointer_cast<IMDEventWorkspace>(inWS); event->setCoordinateSystem(inEvent->getSpecialCoordinateSystem()); if (m_scaling[0] < 0) { // Only need these 2 algorithms for transforming with negative number std::vector<double> extents; std::vector<std::string> names, units; for (size_t d = 0; d < nd; d++) { Geometry::IMDDimension_const_sptr dim = event->getDimension(d); // Find the extents extents.push_back(dim->getMinimum()); extents.push_back(dim->getMaximum()); names.push_back(std::string(dim->getName())); units.push_back(dim->getUnits()); } Algorithm_sptr create_alg = createChildAlgorithm("CreateMDWorkspace"); create_alg->setProperty("Dimensions", static_cast<int>(nd)); create_alg->setProperty("EventType", event->getEventTypeName()); create_alg->setProperty("Extents", extents); create_alg->setProperty("Names", names); create_alg->setProperty("Units", units); create_alg->setPropertyValue("OutputWorkspace", "__none"); create_alg->executeAsChildAlg(); Workspace_sptr none = create_alg->getProperty("OutputWorkspace"); AnalysisDataService::Instance().addOrReplace(outName, event); AnalysisDataService::Instance().addOrReplace("__none", none); Mantid::API::BoxController_sptr boxController = event->getBoxController(); std::vector<int> splits; for (size_t d = 0; d < nd; d++) { splits.push_back(static_cast<int>(boxController->getSplitInto(d))); } Algorithm_sptr merge_alg = createChildAlgorithm("MergeMD"); merge_alg->setPropertyValue("InputWorkspaces", outName + ",__none"); merge_alg->setProperty("SplitInto", splits); merge_alg->setProperty( "SplitThreshold", static_cast<int>(boxController->getSplitThreshold())); merge_alg->setProperty("MaxRecursionDepth", 13); merge_alg->executeAsChildAlg(); event = merge_alg->getProperty("OutputWorkspace"); AnalysisDataService::Instance().remove("__none"); } this->setProperty("OutputWorkspace", event); } }