Skip to content

Commit

Permalink
Add methods to axis classes to find the index of a given value.
Browse files Browse the repository at this point in the history
Refs #9319
  • Loading branch information
martyngigg committed Apr 23, 2014
1 parent 140790b commit 7f8d0a0
Show file tree
Hide file tree
Showing 11 changed files with 114 additions and 2 deletions.
3 changes: 3 additions & 0 deletions Code/Mantid/Framework/API/inc/MantidAPI/Axis.h
Expand Up @@ -83,6 +83,9 @@ class MANTID_API_DLL Axis
/// @param index :: The index
/// @param value :: The new value
virtual void setValue(const std::size_t& index, const double& value) = 0;
/// Find the index of the given double value
virtual size_t indexOfValue(const double value) const = 0;

/// Get the spectrum index
virtual specid_t spectraNo(const std::size_t& index) const;

Expand Down
1 change: 1 addition & 0 deletions Code/Mantid/Framework/API/inc/MantidAPI/NumericAxis.h
Expand Up @@ -59,6 +59,7 @@ class MANTID_API_DLL NumericAxis: public Axis
virtual double operator()(const std::size_t& index, const std::size_t& verticalIndex = 0) const;
/// Set the value at a specific index
virtual void setValue(const std::size_t& index, const double& value);
size_t indexOfValue(const double value) const;
virtual bool operator==(const Axis&) const;
std::string label(const std::size_t& index)const;
/// Create bin boundaries from the point values
Expand Down
1 change: 1 addition & 0 deletions Code/Mantid/Framework/API/inc/MantidAPI/SpectraAxis.h
Expand Up @@ -57,6 +57,7 @@ class MANTID_API_DLL SpectraAxis: public Axis
virtual bool isSpectra() const{return true;}
virtual double operator()(const std::size_t& index, const std::size_t& verticalIndex = 0) const;
virtual void setValue(const std::size_t& index, const double& value);
size_t indexOfValue(const double value) const;
virtual bool operator==(const Axis&) const;
std::string label(const std::size_t& index)const;

Expand Down
2 changes: 2 additions & 0 deletions Code/Mantid/Framework/API/inc/MantidAPI/TextAxis.h
Expand Up @@ -64,6 +64,8 @@ class MANTID_API_DLL TextAxis: public Axis
virtual double operator()(const std::size_t& index, const std::size_t& verticalIndex = 0) const;
/// Set the value at the specified index
virtual void setValue(const std::size_t& index, const double& value);
size_t indexOfValue(const double value) const;

virtual bool operator==(const Axis&) const;
/// Get the label at the specified index
std::string label(const std::size_t& index)const;
Expand Down
2 changes: 1 addition & 1 deletion Code/Mantid/Framework/API/src/Axis.cpp
Expand Up @@ -88,7 +88,7 @@ double Axis::getValue(const std::size_t& index, const std::size_t& verticalIndex
specid_t Axis::spectraNo(const std::size_t& index) const
{
UNUSED_ARG(index)
throw std::domain_error("Cannot call spectraNo() on a non-spectra axis.");
throw std::domain_error("Cannot call spectraNo() on a non-spectra axis.");
}

} // namespace API
Expand Down
23 changes: 23 additions & 0 deletions Code/Mantid/Framework/API/src/NumericAxis.cpp
Expand Up @@ -71,6 +71,29 @@ void NumericAxis::setValue(const std::size_t& index, const double& value)
m_values[index] = value;
}

/**
* Finds the closest index of the given value on the axis
* @param value A value on the axis
* @return The index closest to given value
* @throws std::out_of_range if the value is out of range of the axis
*/
size_t NumericAxis::indexOfValue(const double value) const
{
const auto & yVals = this->getValues();
if(value < yVals.front())
{
throw std::out_of_range("NumericAxis::indexOfValue() - Input lower than first value.");
}
auto it = std::lower_bound(yVals.begin(), yVals.end(), value);
if (it == yVals.end())
{
// Out of range
throw std::out_of_range("NumericAxis::indexOfValue() - Input value out of range");
}
// The workspace index is the point in the vector that we found
return (it - yVals.begin());
}

/** Check if two axis defined as spectra or numeric axis are equivalent
* @param axis2 :: Reference to the axis to compare to
* @return true if self and second axis are equal
Expand Down
25 changes: 25 additions & 0 deletions Code/Mantid/Framework/API/src/SpectraAxis.cpp
Expand Up @@ -89,6 +89,31 @@ void SpectraAxis::setValue(const std::size_t& index, const double& value)
const_cast<MatrixWorkspace*>(m_parentWS)->getSpectrum(index)->setSpectrumNo(static_cast<specid_t>(value));
}

/**
* Finds the index of the given value on the axis
* @param value A value on the axis. It is treated as a spectrum number and cast to specid_t on input
* @return The index closest to given value
* @throws std::out_of_range if the value is out of range of the axis
*/
size_t SpectraAxis::indexOfValue(const double value) const
{
const specid_t specNo = static_cast<specid_t>(value);
// take value as spectrum number
for (size_t i = 0; i < this->length(); ++i)
{
try
{
if (m_parentWS->getSpectrum(i)->getSpectrumNo() == specNo) return i;
}
catch(std::range_error& e)
{
throw std::out_of_range(e.what());
}
}
// Not found if we reached here
throw std::out_of_range("SpectraAxis::indexOfValue() - Value not found on axis");
}

/** Returns the spectrum number at the position given (Spectra axis only)
* @param index The position for which the value is required
* @return The spectrum number as an int
Expand Down
9 changes: 8 additions & 1 deletion Code/Mantid/Framework/API/src/TextAxis.cpp
Expand Up @@ -63,7 +63,14 @@ void TextAxis::setValue(const std::size_t& index, const double& value)
{
UNUSED_ARG(index)
UNUSED_ARG(value)
throw std::domain_error("setValue method cannot be used on a TextAxis.");
throw std::domain_error("setValue method cannot be used on a TextAxis.");
}
/**
* Returns the value that has been passed to it as a size_t
*/
size_t TextAxis::indexOfValue(const double value) const
{
return static_cast<size_t>(value);
}

/** Check if two axis defined as spectra or numeric axis are equivalent
Expand Down
29 changes: 29 additions & 0 deletions Code/Mantid/Framework/API/test/NumericAxisTest.h
Expand Up @@ -159,6 +159,35 @@ class NumericAxisTest : public CxxTest::TestSuite
}
}

void test_indexOfValue_Gives_Correct_Value_When_Input_In_Range()
{
const size_t npoints(5);
NumericAxis axis(npoints);
for(size_t i = 0; i < npoints; ++i)
{
axis.setValue(i, static_cast<double>(i));
}

TS_ASSERT_EQUALS(0, axis.indexOfValue(0.0));
TS_ASSERT_EQUALS(4, axis.indexOfValue(4.0));
TS_ASSERT_EQUALS(3, axis.indexOfValue(2.5));
}

//-------------------------------- Failure cases ----------------------------

void test_indexOfValue_Throws_When_Input_Not_In_Axis_Range()
{
const size_t npoints(5);
NumericAxis axis(npoints);
for(size_t i = 0; i < npoints; ++i)
{
axis.setValue(i, static_cast<double>(i));
}

TS_ASSERT_THROWS(axis.indexOfValue(-0.1), std::out_of_range);
TS_ASSERT_THROWS(axis.indexOfValue(4.1), std::out_of_range);
}

private:
Axis *numericAxis;
};
Expand Down
15 changes: 15 additions & 0 deletions Code/Mantid/Framework/API/test/SpectraAxisTest.h
Expand Up @@ -124,6 +124,21 @@ class SpectraAxisTest : public CxxTest::TestSuite
}
}

void testIndexOfValue_Treats_Input_As_Spectrum_No()
{
for (int i=0; i<5; ++i)
{
TS_ASSERT_EQUALS(i, spectraAxis->indexOfValue(static_cast<double>(2*i)) );
}
}

// --------------------------------------- Failure cases --------------------
void testIndexOfValue_Throws_out_of_range_error_If_Input_Not_In_Range()
{
TS_ASSERT_THROWS(spectraAxis->indexOfValue(20.), std::out_of_range);
}


private:
WorkspaceTester *ws;
Axis *spectraAxis;
Expand Down
6 changes: 6 additions & 0 deletions Code/Mantid/Framework/API/test/TextAxisTest.h
Expand Up @@ -137,6 +137,12 @@ class TextAxisTest : public CxxTest::TestSuite
TS_ASSERT_EQUALS(ta.getMin() + 1, ta.getMax())
}

void test_indexOfValue_Returns_Input_As_Index()
{
TextAxis ta(2);
TS_ASSERT_EQUALS(static_cast<size_t>(1.5), ta.indexOfValue(1.5));
TS_ASSERT_EQUALS(static_cast<size_t>(-1), ta.indexOfValue(-1.5));
}

};

Expand Down

0 comments on commit 7f8d0a0

Please sign in to comment.