Commit e56e9979 authored by Robert Applin's avatar Robert Applin
Browse files

Refs #24691. Correct binIndexOf for point data

parent 7b21490c
......@@ -144,7 +144,8 @@ public:
Types::Core::DateAndTime getLastPulseTime() const;
/// Returns the bin index for a given X value of a given workspace index
size_t binIndexOf(const double xValue, const std::size_t = 0) const;
size_t binIndexOf(const double xValue, const std::size_t = 0,
const double tolerance = 0.0) const;
//----------------------------------------------------------------------
// DATA ACCESSORS
......
......@@ -1241,10 +1241,12 @@ Types::Core::DateAndTime MatrixWorkspace::getLastPulseTime() const {
* Returns the bin index of the given X value
* @param xValue :: The X value to search for
* @param index :: The index within the workspace to search within (default = 0)
* @param tolerance :: The tolerance to accept between the passed xValue and the
* stored value (default = 0.0)
* @returns An index to the bin containing X
*/
size_t MatrixWorkspace::binIndexOf(const double xValue,
const std::size_t index) const {
size_t MatrixWorkspace::binIndexOf(const double xValue, const std::size_t index,
const double tolerance) const {
if (index >= getNumberHistograms()) {
throw std::out_of_range(
"MatrixWorkspace::binIndexOf - Index out of range.");
......@@ -1260,28 +1262,54 @@ size_t MatrixWorkspace::binIndexOf(const double xValue,
throw std::out_of_range("MatrixWorkspace::binIndexOf - X value greater"
" than highest in current range.");
}
size_t hops;
// Check if the workspace is a histogram workspace (len(x) = len(y) + 1 for a
// histogram workspace)
auto const ySize = this->y(index).size();
auto const xSize = xValues.size();
bool const isHistogram = xSize == ySize + 1;
std::size_t hops;
if (ascendingOrder) {
auto lowit = std::lower_bound(xValues.cbegin(), xValues.cend(), xValue);
auto lowerIter =
std::lower_bound(xValues.cbegin(), xValues.cend(), xValue - tolerance);
auto const upperIter =
std::lower_bound(xValues.cbegin(), xValues.cend(), xValue + tolerance);
// If we are pointing at the first value then that means we still want to be
// in the first bin
if (lowit == xValues.cbegin()) {
++lowit;
}
hops = std::distance(xValues.cbegin(), lowit);
if (isHistogram && lowerIter == xValues.cbegin())
++lowerIter;
else if (!isHistogram && lowerIter == xValues.cend())
--lowerIter;
hops = std::distance(xValues.cbegin(), lowerIter);
// If the tolerance makes no difference in the chosen iterator
if (!isHistogram && tolerance != 0.0 && lowerIter == upperIter)
--hops;
} else {
auto lowit = std::upper_bound(xValues.crbegin(), xValues.crend(), xValue);
if (lowit == xValues.crend()) {
--lowit;
} else if (lowit == xValues.crbegin()) {
++lowit;
}
hops = xValues.size() - std::distance(xValues.crbegin(), lowit);
auto lowerIter = std::upper_bound(xValues.crbegin(), xValues.crend(),
xValue + tolerance);
auto const upperIter = std::upper_bound(xValues.crbegin(), xValues.crend(),
xValue - tolerance);
if (isHistogram && lowerIter == xValues.crend())
--lowerIter;
else if (lowerIter == xValues.crbegin())
++lowerIter;
hops = xValues.size() - std::distance(xValues.crbegin(), lowerIter);
// If the tolerance makes no difference in the chosen iterator
if (!isHistogram && tolerance != 0.0 && lowerIter == upperIter)
--hops;
}
// The bin index is offset by one from the number of hops between iterators as
// they start at zero
return hops - 1;
}
// they start at zero (for a histogram workspace)
return isHistogram ? hops - 1 : hops;
} // namespace API
uint64_t MatrixWorkspace::getNPoints() const {
return static_cast<uint64_t>(this->size());
......
......@@ -1732,7 +1732,114 @@ public:
checkDetectorSignedTwoTheta(Geometry::X, {{1., -1., -1., 1.}});
}
void
test_that_binIndexOf_returns_the_correct_index_for_a_histogram_workspace_when_the_x_bins_are_in_ascending_order() {
std::vector<double> const xValues{1.0, 2.0, 3.0, 4.0};
auto const workspace = getWorkspaceWithPopulatedX(1, 4, 3, xValues);
TS_ASSERT_EQUALS(workspace.binIndexOf(3.0), 1);
}
void
test_that_binIndexOf_returns_the_correct_index_for_a_histogram_workspace_when_the_x_bins_are_in_descending_order() {
std::vector<double> const xValues{4.0, 3.0, 2.0, 1.0};
auto const workspace = getWorkspaceWithPopulatedX(1, 4, 3, xValues);
TS_ASSERT_EQUALS(workspace.binIndexOf(3.0), 0);
}
void
test_that_binIndexOf_returns_the_correct_index_for_a_nonHistogram_workspace_when_the_x_bins_are_in_ascending_order() {
std::vector<double> const xValues{1.0, 2.0, 3.0, 4.0};
auto const workspace = getWorkspaceWithPopulatedX(1, 4, 4, xValues);
TS_ASSERT_EQUALS(workspace.binIndexOf(3.0), 2);
}
void
test_that_binIndexOf_returns_the_correct_index_for_a_nonHistogram_workspace_when_the_x_bins_are_in_descending_order() {
std::vector<double> const xValues{4.0, 3.0, 2.0, 1.0};
auto const workspace = getWorkspaceWithPopulatedX(1, 4, 4, xValues);
TS_ASSERT_EQUALS(workspace.binIndexOf(3.0), 1);
}
void
test_that_binIndexOf_returns_the_ascending_index_for_a_nonHistogram_workspace_when_passed_an_x_value_within_a_tolerance() {
std::vector<double> const xValues{1.0, 1.9997, 3.0, 4.0};
auto const workspace = getWorkspaceWithPopulatedX(1, 4, 4, xValues);
TS_ASSERT_EQUALS(workspace.binIndexOf(2.0, 0, 0.0005), 1);
}
void
test_that_binIndexOf_returns_the_ascending_index_for_a_nonHistogram_workspace_when_passed_an_x_value_within_a_tolerance2() {
std::vector<double> const xValues{1.0, 1.9997, 3.0, 4.0};
auto const workspace = getWorkspaceWithPopulatedX(1, 4, 4, xValues);
TS_ASSERT_EQUALS(workspace.binIndexOf(1.9995, 0, 0.0005), 1);
}
void
test_that_binIndexOf_returns_the_ascending_index_for_a_nonHistogram_workspace_when_passed_an_x_value_just_outside_a_tolerance() {
std::vector<double> const xValues{1.0, 1.9997, 3.0, 4.0};
auto const workspace = getWorkspaceWithPopulatedX(1, 4, 4, xValues);
TS_ASSERT_EQUALS(workspace.binIndexOf(2.0, 0, 0.0002), 1);
}
void
test_that_binIndexOf_returns_the_ascending_index_for_a_nonHistogram_workspace_when_passed_an_x_value_just_outside_a_tolerance2() {
std::vector<double> const xValues{1.0, 1.9997, 3.0, 4.0};
auto const workspace = getWorkspaceWithPopulatedX(1, 4, 4, xValues);
TS_ASSERT_EQUALS(workspace.binIndexOf(1.9992, 0, 0.0002), 0);
}
void
test_that_binIndexOf_returns_the_descending_index_for_a_nonHistogram_workspace_when_passed_an_x_value_within_a_tolerance() {
std::vector<double> const xValues{4.0, 3.0, 1.9997, 1.0};
auto const workspace = getWorkspaceWithPopulatedX(1, 4, 4, xValues);
TS_ASSERT_EQUALS(workspace.binIndexOf(1.9994, 0, 0.0005), 2);
}
void
test_that_binIndexOf_returns_the_descending_index_for_a_nonHistogram_workspace_when_passed_an_x_value_within_a_tolerance2() {
std::vector<double> const xValues{4.0, 3.0, 1.9997, 1.0};
auto const workspace = getWorkspaceWithPopulatedX(1, 4, 4, xValues);
TS_ASSERT_EQUALS(workspace.binIndexOf(1.9999, 0, 0.0005), 2);
}
void
test_that_binIndexOf_returns_the_descending_index_for_a_nonHistogram_workspace_when_passed_an_x_value_just_outside_a_tolerance() {
std::vector<double> const xValues{4.0, 3.0, 1.9997, 1.0};
auto const workspace = getWorkspaceWithPopulatedX(1, 4, 4, xValues);
TS_ASSERT_EQUALS(workspace.binIndexOf(1.9994, 0, 0.0002), 2);
}
void
test_that_binIndexOf_returns_the_descending_index_for_a_nonHistogram_workspace_when_passed_an_x_value_just_outside_a_tolerance2() {
std::vector<double> const xValues{4.0, 3.0, 1.9997, 1.0};
auto const workspace = getWorkspaceWithPopulatedX(1, 4, 4, xValues);
TS_ASSERT_EQUALS(workspace.binIndexOf(2.0, 0, 0.0002), 1);
}
private:
WorkspaceTester getWorkspaceWithPopulatedX(
std::size_t const &nVectors, std::size_t const &xLength,
std::size_t const &yLength, std::vector<double> const &xValues) {
WorkspaceTester workspace;
workspace.initialize(nVectors, xLength, yLength);
auto &X = workspace.dataX(0);
std::copy(xValues.begin(), xValues.end(), X.begin());
return workspace;
}
void checkDetectorSignedTwoTheta(const Geometry::PointingAlong thetaSignAxis,
const std::array<double, 4> &signs) {
constexpr size_t numDets{4};
......
......@@ -8,7 +8,6 @@
#define MANTID_ALGORITHMS_COPYDATARANGE_H_
#include "MantidAPI/Algorithm.h"
#include "MantidAPI/MatrixWorkspace.h"
#include "MantidKernel/System.h"
namespace Mantid {
......
......@@ -7,7 +7,7 @@
#include "MantidAlgorithms/CopyDataRange.h"
#include "MantidAPI/AlgorithmManager.h"
#include "MantidAPI/NumericAxis.h"
#include "MantidAPI/MatrixWorkspace.h"
#include "MantidKernel/BoundedValidator.h"
#include <algorithm>
......@@ -40,8 +40,10 @@ void copyDataRange(MatrixWorkspace_const_sptr inputWorkspace,
MatrixWorkspace_sptr destWorkspace, int const &specMin,
int const &specMax, double const &xMin, double const &xMax,
int yInsertionIndex, int const &xInsertionIndex) {
int const xMinIndex = static_cast<int>(inputWorkspace->binIndexOf(xMin));
int const xMaxIndex = static_cast<int>(inputWorkspace->binIndexOf(xMax));
int const xMinIndex =
static_cast<int>(inputWorkspace->binIndexOf(xMin, 0, 0.000001));
int const xMaxIndex =
static_cast<int>(inputWorkspace->binIndexOf(xMax, 0, 0.000001));
copyDataRange(inputWorkspace, destWorkspace, specMin, specMax, xMinIndex,
xMaxIndex, yInsertionIndex, xInsertionIndex);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment