/** * @brief Extract Q values from vertical dimension of the workspace, or compute * them. * @param workspace workspace possibly containing Q values. */ std::vector<double> FunctionQDepends::extractQValues( const Mantid::API::MatrixWorkspace &workspace) { std::vector<double> qs; // Check if the vertical axis has units of momentum transfer, then extract Q // values... auto axis_ptr = dynamic_cast<Mantid::API::NumericAxis *>(workspace.getAxis(1)); if (axis_ptr) { const boost::shared_ptr<Kernel::Unit> &unit_ptr = axis_ptr->unit(); if (unit_ptr->unitID() == "MomentumTransfer") { qs = axis_ptr->getValues(); } } // ...otherwise, compute the momentum transfer for each spectrum, if possible else { const auto &spectrumInfo = workspace.spectrumInfo(); size_t numHist = workspace.getNumberHistograms(); for (size_t wi = 0; wi < numHist; wi++) { if (spectrumInfo.hasDetectors(wi)) { const auto detID = spectrumInfo.detector(wi).getID(); double efixed = workspace.getEFixed(detID); double usignTheta = 0.5 * spectrumInfo.twoTheta(wi); double q = Mantid::Kernel::UnitConversion::convertToElasticQ(usignTheta, efixed); qs.push_back(q); } else { g_log.debug("Cannot populate Q values from workspace"); qs.clear(); break; } } } return qs; }
/** * Constructs a title using the unicode methods of the UnitLabel * @param workspace The workspace containing the Y title information * @param plottingDistribution If true, the Y axis has been divided by the bin * width */ void PlotAxis::titleFromYData(const Mantid::API::MatrixWorkspace &workspace, const bool plottingDistribution) { // The workspace can have a custom label so we should use that as a // preference. // The workspace.YUnitLabel does some mangling of the string if the user set // no // custom label. See MatrixWorkspace::YUnitLabel const std::string customLabel = workspace.YUnitLabel(); const std::string yunit = workspace.YUnit(); if ((yunit == customLabel) || (customLabel.find("per") != std::string::npos)) { m_title = QString::fromStdString(yunit); if (plottingDistribution && workspace.axes() > 0 && workspace.getAxis(0)->unit()) { const auto xunit = workspace.getAxis(0)->unit(); const auto lbl = xunit->label(); if (!lbl.utf8().empty()) { m_title += " (" + QString::fromStdWString(lbl.utf8()) + ")" + QString::fromWCharArray(L"\u207b\u00b9"); } } } else { m_title = QString::fromStdString(customLabel); } }
bool isItSorted(Comparator const &compare, const Mantid::API::MatrixWorkspace &inputWorkspace) { for (auto specNum = 0u; specNum < inputWorkspace.getNumberHistograms(); specNum++) { if (!std::is_sorted(inputWorkspace.x(specNum).begin(), inputWorkspace.x(specNum).end(), [&](double lhs, double rhs) -> bool { return compare(lhs, rhs); })) { return false; } } return true; }
/** * @brief Determines whether it is a valid histogram or not. * * @param inputWorkspace the unsorted input workspace * @return true if it is a valid histogram else produce a runtime_error * @return false if it is not a histogram, and is thus point data */ bool SortXAxis::determineIfHistogramIsValid( const Mantid::API::MatrixWorkspace &inputWorkspace) { // Assuming all X and Ys are the same, if X is not the same size as y, assume // it is a histogram if (inputWorkspace.x(0).size() != inputWorkspace.y(0).size()) { // The only way to guarantee that a histogram is a proper histogram, is to // check whether each data value is in the correct order. if (!isItSorted(std::greater<double>(), inputWorkspace)) { if (!isItSorted(std::less<double>(), inputWorkspace)) { throw std::runtime_error("Data entered looks like a histogram, but is " "not a valid histogram"); } } return true; } return false; }
/** * @brief Copies the sorted inputworkspace into the output workspace without * using clone because of how histograms are supported, for the Y Axis and the E * Axis. * * @param workspaceIndicies the sorted vector of indicies * @param inputWorkspace the unsorted input workspaces * @param outputWorkspace the empty output workspace * @param specNum the spectrum number being copied into * @param isAProperHistogram whether or not it has been determined to be a valid * histogram earlier on. */ void SortXAxis::copyYandEToOutputWorkspace( std::vector<std::size_t> &workspaceIndicies, const Mantid::API::MatrixWorkspace &inputWorkspace, Mantid::API::MatrixWorkspace &outputWorkspace, unsigned int specNum, bool isAProperHistogram) { // If Histogram data find the biggest index value and remove it from // workspaceIndicies if (isAProperHistogram) { auto lastIndexIt = std::find(workspaceIndicies.begin(), workspaceIndicies.end(), inputWorkspace.y(specNum).size()); workspaceIndicies.erase(lastIndexIt); } auto &inSpaceY = inputWorkspace.y(specNum); for (auto workspaceIndex = 0u; workspaceIndex < inputWorkspace.y(specNum).size(); workspaceIndex++) { outputWorkspace.mutableY(specNum)[workspaceIndex] = inSpaceY[workspaceIndicies[workspaceIndex]]; } auto &inSpaceE = inputWorkspace.e(specNum); for (auto workspaceIndex = 0u; workspaceIndex < inputWorkspace.e(specNum).size(); workspaceIndex++) { outputWorkspace.mutableE(specNum)[workspaceIndex] = inSpaceE[workspaceIndicies[workspaceIndex]]; } }
void sortByXValue(std::vector<std::size_t> &workspaceIndicies, const Mantid::API::MatrixWorkspace &inputWorkspace, unsigned int specNum, Comparator const &compare) { std::sort(workspaceIndicies.begin(), workspaceIndicies.end(), [&](std::size_t lhs, std::size_t rhs) -> bool { return compare(inputWorkspace.x(specNum)[lhs], inputWorkspace.x(specNum)[rhs]); }); }
/** * Construct a QwtWorkspaceSpectrumData object with a source workspace * @param workspace The workspace containing the data * @param wsIndex Index of the spectrum to plot * @param logScaleY If true, plot a log scale * @param plotAsDistribution If true and the data is histogram and not already a * distribution then plot the Y values/X bin-width */ QwtWorkspaceSpectrumData::QwtWorkspaceSpectrumData( const Mantid::API::MatrixWorkspace &workspace, int wsIndex, const bool logScaleY, const bool plotAsDistribution) : MantidQwtMatrixWorkspaceData(logScaleY), m_wsIndex(wsIndex), m_X(workspace.readX(wsIndex)), m_Y(workspace.readY(wsIndex)), m_E(workspace.readE(wsIndex)), m_xTitle(), m_yTitle(), m_isHistogram(workspace.isHistogramData()), m_dataIsNormalized(workspace.isDistribution()), m_binCentres(false), m_isDistribution(false) { // Actual plotting based on what type of data we have setAsDistribution(plotAsDistribution && !m_dataIsNormalized); // takes into account if this is a // histogram and sets m_isDistribution m_xTitle = MantidQt::API::PlotAxis(workspace, 0).title(); m_yTitle = MantidQt::API::PlotAxis((m_dataIsNormalized || m_isDistribution), workspace).title(); // Calculate the min and max values calculateYMinAndMax(); }
/** * @param workspace A reference to the workspace object that this data refers to */ void QwtWorkspaceBinData::init(const Mantid::API::MatrixWorkspace &workspace) { if(workspace.axes() != 2) { std::ostringstream os; os << "QwtWorkspaceBinData(): Workspace must have two axes, found " << workspace.axes(); throw std::invalid_argument(os.str()); } // Check binIndex is valid if(static_cast<size_t>(m_binIndex) >= workspace.blocksize()) { std::ostringstream os; os << "QwtWorkspaceBinData(): Index out of range. index=" << m_binIndex << ", nvalues=" << workspace.blocksize(); throw std::out_of_range(os.str()); } // Fill vectors of data const size_t nhist = workspace.getNumberHistograms(); auto* vertAxis = workspace.getAxis(1); //supplies X values m_X.resize(nhist); m_Y.resize(nhist); m_E.resize(nhist); for(size_t i = 0; i < nhist; ++i) { m_X[i] = vertAxis->getValue(i); m_Y[i] = workspace.readY(i)[m_binIndex]; m_E[i] = workspace.readE(i)[m_binIndex]; } // meta data m_xTitle = MantidQt::API::PlotAxis(workspace, 1).title(); m_yTitle = MantidQt::API::PlotAxis(workspace).title(); }
/** * @brief Copies the sorted inputworkspace into the output workspace without * using clone because of how histograms are supported, for the X Axis and the * Dx Axis. * * @param workspaceIndicies the sorted vector of indecies * @param inputWorkspace the unsorted initial workspace * @param outputWorkspace the emptry output workspace * @param specNum the Spectrum it is currently copying over */ void SortXAxis::copyXandDxToOutputWorkspace( std::vector<std::size_t> &workspaceIndicies, const Mantid::API::MatrixWorkspace &inputWorkspace, Mantid::API::MatrixWorkspace &outputWorkspace, unsigned int specNum) { // Move an ordered X to the output workspace for (auto workspaceIndex = 0u; workspaceIndex < inputWorkspace.x(specNum).size(); workspaceIndex++) { outputWorkspace.mutableX(specNum)[workspaceIndex] = inputWorkspace.x(specNum)[workspaceIndicies[workspaceIndex]]; } // If Dx's are present, move Dx's to the output workspace // If Dx's are present, move Dx's to the output workspace if (inputWorkspace.hasDx(specNum)) { for (auto workspaceIndex = 0u; workspaceIndex < inputWorkspace.dx(specNum).size(); workspaceIndex++) { outputWorkspace.mutableDx(specNum)[workspaceIndex] = inputWorkspace.dx(specNum)[workspaceIndicies[workspaceIndex]]; } } }