diff --git a/Framework/Algorithms/inc/MantidAlgorithms/SortXAxis2.h b/Framework/Algorithms/inc/MantidAlgorithms/SortXAxis2.h index 4afb2c5b8b8016a53d6f11452c81ad1f499da1f6..9fd20ca28e6dde1d81c121e994cacc9d396409da 100644 --- a/Framework/Algorithms/inc/MantidAlgorithms/SortXAxis2.h +++ b/Framework/Algorithms/inc/MantidAlgorithms/SortXAxis2.h @@ -11,8 +11,7 @@ namespace Mantid { namespace Algorithms { -/** SortXAxis - +/** Copyright © 2018 ISIS Rutherford Appleton Laboratory, NScD Oak Ridge National Laboratory & European Spallation Source @@ -33,10 +32,17 @@ namespace Algorithms { File change history is stored at: <https://github.com/mantidproject/mantid> Code Documentation is available at: <http://doxygen.mantidproject.org> - - @author Samuel Jones */ +/** + * @brief SortXAxis will take Histogram or Point data and reorder it based on + * the X Axis' values, whilst maintaining it's Dx, Y and E axis relative values. + * @author Samuel Jones + * @version 2.0 + * @date 07-2018 + * @copyright GNU General Public License + */ + class DLLExport SortXAxis : public API::Algorithm { public: const std::string name() const override; @@ -58,7 +64,7 @@ private: std::vector<std::size_t> &workspaceIndecies, Mantid::API::MatrixWorkspace_const_sptr inputWorkspace, Mantid::API::MatrixWorkspace_sptr outputWorkspace, const size_t sizeOfY, - unsigned int SpecNum/*, bool isAProperHistogram*/); + unsigned int SpecNum, bool isAProperHistogram); void copyXandDxToOutputWorkspace( std::vector<std::size_t> &workspaceIndecies, @@ -71,10 +77,10 @@ private: Mantid::API::MatrixWorkspace_const_sptr inputWorkspace, Mantid::API::MatrixWorkspace_sptr outputWorkspace, const size_t sizeOfX, const size_t sizeOfY, - unsigned int specNum/*, bool isAProperHistogram*/); + unsigned int specNum, bool isAProperHistogram); - /*bool determineIfHistogramIsValid( - Mantid::API::MatrixWorkspace_const_sptr inputWorkspace);*/ + bool determineIfHistogramIsValid( + Mantid::API::MatrixWorkspace_const_sptr inputWorkspace); }; } // namespace Algorithms diff --git a/Framework/Algorithms/src/SortXAxis2.cpp b/Framework/Algorithms/src/SortXAxis2.cpp index 18fe0b3c0d5f96116db3cd6f3cb22a1c21452be5..eb9abc8f1352541119ee913600c1e45146143446 100644 --- a/Framework/Algorithms/src/SortXAxis2.cpp +++ b/Framework/Algorithms/src/SortXAxis2.cpp @@ -43,7 +43,7 @@ void SortXAxis::exec() { MatrixWorkspace_sptr outputWorkspace = inputWorkspace->clone(); // Check if it is a valid histogram here - /*bool isAProperHistogram = determineIfHistogramIsValid(inputWorkspace);*/ + bool isAProperHistogram = determineIfHistogramIsValid(inputWorkspace); // Define everything you can outside of the for loop // Assume that all spec are the same size @@ -61,7 +61,7 @@ void SortXAxis::exec() { sortIndicesByX(workspaceIndicies, theOrder, inputWorkspace, specNum); copyToOutputWorkspace(workspaceIndicies, inputWorkspace, outputWorkspace, - sizeOfX, sizeOfY, specNum/*, isAProperHistogram*/); + sizeOfX, sizeOfY, specNum, isAProperHistogram); PARALLEL_END_INTERUPT_REGION } PARALLEL_CHECK_INTERUPT_REGION @@ -69,6 +69,12 @@ void SortXAxis::exec() { setProperty("OutputWorkspace", outputWorkspace); } +/** + * @brief Gets a vector of numbers from 0 to the sizeOfX-1 and returns it + * + * @param sizeOfX The size of the Spectrum's X axis + * @return std::vector<std::size_t> + */ std::vector<std::size_t> SortXAxis::createIndexes(const size_t sizeOfX) { std::vector<std::size_t> workspaceIndicies; workspaceIndicies.reserve(sizeOfX); @@ -78,6 +84,16 @@ std::vector<std::size_t> SortXAxis::createIndexes(const size_t sizeOfX) { return workspaceIndicies; } +/** + * @brief A template for sorting the values given a comparator + * + * @tparam Comparator + * @param workspaceIndicies, the vector of indicies values + * @param inputWorkspace, the original workspace + * @param specNum, the Spectrum number to be sorted + * @param compare, std::less<double> for Ascending order, std::greater<double> + * for descending order + */ template <typename Comparator> void sortByXValue(std::vector<std::size_t> &workspaceIndicies, MatrixWorkspace_const_sptr inputWorkspace, @@ -102,6 +118,17 @@ void SortXAxis::sortIndicesByX(std::vector<std::size_t> &workspaceIndicies, } } +/** + * @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 sizeOfX the Maximum index of X + * @param specNum the Spectrum it is currently copying over + */ void SortXAxis::copyXandDxToOutputWorkspace( std::vector<std::size_t> &workspaceIndicies, MatrixWorkspace_const_sptr inputWorkspace, @@ -113,6 +140,7 @@ void SortXAxis::copyXandDxToOutputWorkspace( 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 < sizeOfX; workspaceIndex++) { @@ -122,24 +150,39 @@ void SortXAxis::copyXandDxToOutputWorkspace( } } +/** + * @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 sizeOfY the Maxiumum index of Y + * @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, MatrixWorkspace_const_sptr inputWorkspace, MatrixWorkspace_sptr outputWorkspace, const size_t sizeOfY, - unsigned int specNum) { + unsigned int specNum, bool isAProperHistogram) { // If Histogram data find the biggest index value and remove it from // workspaceIndicies - if (inputWorkspace->isHistogramData()) { + if (isAProperHistogram) { auto lastIndexIt = std::find(workspaceIndicies.begin(), workspaceIndicies.end(), sizeOfY); workspaceIndicies.erase(lastIndexIt); } + auto &inSpaceY = inputWorkspace->y(specNum); + auto &inSpaceE = inputWorkspace->e(specNum); for (auto workspaceIndex = 0u; workspaceIndex < sizeOfY; workspaceIndex++) { outputWorkspace->mutableY(specNum)[workspaceIndex] = - inputWorkspace->y(specNum)[workspaceIndicies[workspaceIndex]]; + inSpaceY[workspaceIndicies[workspaceIndex]]; outputWorkspace->mutableE(specNum)[workspaceIndex] = - inputWorkspace->e(specNum)[workspaceIndicies[workspaceIndex]]; + inSpaceE[workspaceIndicies[workspaceIndex]]; } } @@ -147,11 +190,74 @@ void SortXAxis::copyToOutputWorkspace( std::vector<std::size_t> &workspaceIndicies, MatrixWorkspace_const_sptr inputWorkspace, MatrixWorkspace_sptr outputWorkspace, const size_t sizeOfX, - const size_t sizeOfY, unsigned int specNum) { + const size_t sizeOfY, unsigned int specNum, bool isAProperHistogram) { copyXandDxToOutputWorkspace(workspaceIndicies, inputWorkspace, outputWorkspace, sizeOfX, specNum); copyYandEToOutputWorkspace(workspaceIndicies, inputWorkspace, outputWorkspace, - sizeOfY, specNum); + sizeOfY, specNum, isAProperHistogram); } + +/** + * @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( + MatrixWorkspace_const_sptr 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. + bool ascending = true; + for (auto specNum = 0u; specNum < inputWorkspace->getNumberHistograms(); + specNum++) { + if (!isItSorted(std::greater<double>(), inputWorkspace, specNum)) { + ascending = false; + break; + } + } + if (!ascending) { + for (auto specNum = 0u; specNum < inputWorkspace->getNumberHistograms(); + specNum++) { + if (!isItSorted(std::less<double>(), inputWorkspace, specNum)) { + // It is not ascending nor descending and is thus not a histogram + throw std::runtime_error( + "Data entered looks like a histogram, but is " + "not a valid histogram"); + } + } + } + return true; + } + return false; +} + +/** + * @brief determines whether or not a given spectrum is sorted based on a passed + * comparator + * + * @tparam Comparator + * @param compare std::less<double> for descending, and std::greater<double> for + * ascending. + * @param inputWorkspace the unsorted input workspace + * @param specNum the spectrum number currently being compared + * @return true if it is sorted + * @return false if it is not sorted + */ +template <typename Comparator> +bool isItSorted(Comparator const &compare, + MatrixWorkspace_const_sptr inputWorkspace, + unsigned int specNum) { + return std::is_sorted(inputWorkspace->x(specNum).begin(), + inputWorkspace->x(specNum).end(), + [&](std::size_t lhs, std::size_t rhs) -> bool { + return compare(inputWorkspace->x(specNum)[lhs], + inputWorkspace->x(specNum)[rhs]); + }); +} + } // namespace Algorithms -} // namespace Mantid +} // namespace Mantid \ No newline at end of file