Commit 19ee13f6 authored by Owen Arnold's avatar Owen Arnold
Browse files

re #2917. Iterator introduced. No dependencies yet, but well under test.

parent ceabb88d
......@@ -11,6 +11,7 @@ set ( SRC_FILES
src/MDImage.cpp
src/MDIndexCalculator.cpp
src/MDWorkspace.cpp
src/MDWorkspaceIterator.cpp
src/MD_FileFormatFactory.cpp
src/MD_FileHoraceReader.cpp
src/MD_FileTestDataGenerator.cpp
......@@ -34,6 +35,7 @@ set ( INC_FILES
inc/MDDataObjects/MDIndexCalculator.h
inc/MDDataObjects/MDTestWorkspace.h
inc/MDDataObjects/MDWorkspace.h
inc/MDDataObjects/MDWorkspaceIterator.h
inc/MDDataObjects/MD_FileFormatFactory.h
inc/MDDataObjects/MD_FileHoraceReader.h
inc/MDDataObjects/MD_FileTestDataGenerator.h
......@@ -58,6 +60,7 @@ test/MDDataPointTest.h
test/MDImageTest.h
test/MDPixelsTest.h
test/MDWorkspaceTest.h
test/MDWorkspaceIteratorTest.h
#test/MDPointTest.h
#test/MDBoxTest.h
)
......
......@@ -179,6 +179,9 @@ namespace Mantid
void setInstrument(const Mantid::Geometry::IInstrument_sptr& instr);
/// Creates a new iterator pointing to the first cell in the workspace
Mantid::API::IMDIterator* createIterator() const;
private:
/// Cache. Gives MDWorkspace ownership of MDPoints (as an IMDWorkspace), while allowing polymorphic behaviour.
/// Note this is NOT an optimized implementation yet, but it does support lazy instantiation.
......
#ifndef MD_WORKSPACE_ITERATOR_H
#define MD_WORKSPACE_ITERATOR_H
#include "MantidAPI/IMDIterator.h"
#include "MDDataObjects/MDIndexCalculator.h"
#include "MantidGeometry/MDGeometry/IMDDimension.h"
#include <vector>
namespace Mantid
{
namespace MDDataObjects
{
/** Concrete implementation of IMDIterator for use with MDWorkspaces. Based closely upon Roman Tolchenov's implementation
used in MDFitWorkspace.
@author Owen Arnold, Tessella Support Services plc
@date 03/05/2011
Copyright &copy; 2009 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory
This file is part of Mantid.
Mantid is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
Mantid is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
File change history is stored at: <https://svn.mantidproject.org/mantid/trunk/Code/Mantid>.
Code Documentation is available at: <http://doxygen.mantidproject.org>
*/
class DLLExport MDWorkspaceIterator : public Mantid::API::IMDIterator
{
public:
MDWorkspaceIterator(const MDWorkspaceIndexCalculator& indexCalculator, std::vector<Mantid::Geometry::IMDDimension_sptr> dimensions);
~MDWorkspaceIterator();
/// Get the size of the data
virtual size_t getDataSize() const;
/// Get the i-th coordinate of the current cell
virtual double getCoordinate(int i) const;
/// Advance to the next cell. If the current cell is the last one in the workspace
/// do nothing and return false.
virtual bool next();
///< return the current data pointer (index)
virtual size_t getPointer() const;
private:
const MDWorkspaceIndexCalculator m_indexCalculator;
size_t m_cur_pointer;
size_t m_end_pointer;
std::vector<size_t> m_index;
std::vector<boost::shared_ptr<Mantid::Geometry::IMDDimension> > m_dimensions;
};
}
}
#endif
\ No newline at end of file
......@@ -2,6 +2,7 @@
#include "MDDataObjects/MDWorkspace.h"
#include "MantidKernel/IPropertyManager.h"
#include "MDDataObjects/MDIndexCalculator.h"
#include "MDDataObjects/MDWorkspaceIterator.h"
namespace Mantid{
namespace MDDataObjects{
......@@ -342,6 +343,20 @@ MDWorkspace::MDWorkspace(unsigned int nDimensions, unsigned int nRecDims)
return this->m_spMDImage->get_const_MDGeometry().toXMLString();
}
/// Creates a new iterator pointing to the first cell in the workspace
Mantid::API::IMDIterator* MDWorkspace::createIterator() const
{
typedef std::vector<Mantid::Geometry::IMDDimension_sptr> IMDDimensions_sptr_vec;
IMDDimensions_sptr_vec dimensions = m_spMDImage->get_const_MDGeometry().getDimensions();
MDWorkspaceIndexCalculator calculator(dimensions.size());
for(int i = 0; i < dimensions.size(); i++)
{
calculator.setDimensionSize(i, dimensions[i]->getNBins());
}
return new MDWorkspaceIterator(calculator, dimensions);
}
VecCoordinate create4DPolyhedron(
unsigned int dim1Increment,
unsigned int dim2Increment,
......
#include "MDDataObjects/MDWorkspaceIterator.h"
namespace Mantid
{
namespace MDDataObjects
{
MDWorkspaceIterator::MDWorkspaceIterator(const MDWorkspaceIndexCalculator& indexCalculator,
const std::vector<Mantid::Geometry::IMDDimension_sptr> dimensions):
m_indexCalculator(indexCalculator),m_cur_pointer(),m_end_pointer(indexCalculator.getIndexUpperBounds()), m_dimensions(dimensions)
{
m_index.resize(indexCalculator.getNDimensions());
indexCalculator.calculateDimensionIndexes(m_cur_pointer,m_index);
}
MDWorkspaceIterator::~MDWorkspaceIterator()
{
}
size_t MDWorkspaceIterator::getDataSize()const
{
return m_indexCalculator.getIndexUpperBounds() + 1;
}
double MDWorkspaceIterator::getCoordinate(int i)const
{
return m_dimensions[i]->getX(m_index[i]);
}
bool MDWorkspaceIterator::next()
{
if (m_cur_pointer < m_end_pointer)
{
++m_cur_pointer;
m_indexCalculator.calculateDimensionIndexes(m_cur_pointer,m_index);
return true;
}
return false;
}
size_t MDWorkspaceIterator::getPointer()const
{
return m_cur_pointer;
}
}
}
\ No newline at end of file
#ifndef MDWORKSPACE_ITERATOR_TEST_H
#define MDWORKSPACE_ITERATOR_TEST_H
#include <cxxtest/TestSuite.h>
#include "gtest/gtest.h"
#include "gmock/gmock.h"
#include "MDDataObjects/MDIndexCalculator.h"
#include "MDDataObjects/MDWorkspaceIterator.h"
using Mantid::Geometry::IMDDimension_sptr;
using Mantid::MDDataObjects::MDWorkspaceIndexCalculator;
using Mantid::MDDataObjects::MDWorkspaceIterator;
using namespace testing;
class MDWorkspaceIteratorTest : public CxxTest::TestSuite
{
private:
/// Mock IMDDimension allows tests to specify exact expected behavior of dependency.
class MockIMDDimension : public Mantid::Geometry::IMDDimension {
public:
MOCK_CONST_METHOD0(getName,
std::string());
MOCK_CONST_METHOD0(getUnits,
std::string());
MOCK_CONST_METHOD0(getDimensionId,
std::string());
MOCK_CONST_METHOD0(getMaximum,
double());
MOCK_CONST_METHOD0(getMinimum,
double());
MOCK_CONST_METHOD0(getNBins,
size_t());
MOCK_CONST_METHOD0(toXMLString,
std::string());
MOCK_CONST_METHOD1(getX,
double(size_t ind));
};
public:
typedef std::vector<IMDDimension_sptr> IMDDimension_sptr_vec;
void testGetCoordinate()
{
int dimensionality = 2;
MockIMDDimension* pDimensionX = new MockIMDDimension();
MockIMDDimension* pDimensionY = new MockIMDDimension();
EXPECT_CALL(*pDimensionX, getX(_)).Times(1);
EXPECT_CALL(*pDimensionY, getX(_)).Times(1);
IMDDimension_sptr_vec dimensions(dimensionality);
dimensions[0] = IMDDimension_sptr(pDimensionX);
dimensions[1] = IMDDimension_sptr(pDimensionY);
MDWorkspaceIndexCalculator calculator(dimensionality, 10, 10);
MDWorkspaceIterator iterator(calculator, dimensions);
iterator.getCoordinate(0); // Of the 1st dimension should get the 2nd coordinate.
iterator.getCoordinate(1); // Of the 2nd dimension should get the 2nd coordinate.
TSM_ASSERT("Extracting coordinates has not utilized dimension x as expected.", Mock::VerifyAndClearExpectations(pDimensionX));
TSM_ASSERT("Extracting coordinates has not utilized dimension y as expected.", Mock::VerifyAndClearExpectations(pDimensionY));
}
void testNext()
{
int dimensionality = 1;
MockIMDDimension* pDimensionX = new MockIMDDimension();
IMDDimension_sptr_vec dimensions(dimensionality);
dimensions[0] = IMDDimension_sptr(pDimensionX);
MDWorkspaceIndexCalculator calculator(dimensionality, 3); // 100 cells.
MDWorkspaceIterator iterator(calculator, dimensions);
size_t valuePointerA = iterator.getPointer();
iterator.next();
size_t valuePointerB = iterator.getPointer();
iterator.next();
size_t valuePointerC = iterator.getPointer();
TS_ASSERT_EQUALS(0, valuePointerA);
TS_ASSERT_EQUALS(1, valuePointerB);
TS_ASSERT_EQUALS(2, valuePointerC);
TS_ASSERT_EQUALS(false, iterator.next());
}
void testLooping()
{
int dimensionality = 2;
MockIMDDimension* pDimensionX = new MockIMDDimension();
MockIMDDimension* pDimensionY = new MockIMDDimension();
IMDDimension_sptr_vec dimensions(dimensionality);
dimensions[0] = IMDDimension_sptr(pDimensionX);
dimensions[1] = IMDDimension_sptr(pDimensionY);
MDWorkspaceIndexCalculator calculator(dimensionality, 10, 10); // 100 cells.
MDWorkspaceIterator iterator(calculator, dimensions);
size_t valuePointer;
while(iterator.next())
{
valuePointer = iterator.getPointer();
}
// 0 to 100. expected value is 99
TSM_ASSERT_EQUALS("Pointer does not have expected value after looping through entire workspace.", 99, valuePointer );
}
void testGetDataSize()
{
int dimensionality = 3;
MockIMDDimension* pDimensionX = new MockIMDDimension();
MockIMDDimension* pDimensionY = new MockIMDDimension();
MockIMDDimension* pDimensionZ = new MockIMDDimension();
IMDDimension_sptr_vec dimensions(dimensionality);
dimensions[0] = IMDDimension_sptr(pDimensionX);
dimensions[1] = IMDDimension_sptr(pDimensionY);
dimensions[2] = IMDDimension_sptr(pDimensionZ);
MDWorkspaceIndexCalculator calculator(dimensionality, 10, 10, 10); // 1000 cells.
MDWorkspaceIterator iterator(calculator, dimensions);
TSM_ASSERT_EQUALS("Incorrect data size calculated", 1000, iterator.getDataSize());
}
};
#endif
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