Skip to content

Commit

Permalink
Refs #8550. VectorColumn: ability to use it from Python.
Browse files Browse the repository at this point in the history
Plus tests for that.
  • Loading branch information
arturbekasov committed Dec 5, 2013
1 parent d3ca69f commit 6cbe39c
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 3 deletions.
7 changes: 5 additions & 2 deletions Code/Mantid/Framework/DataObjects/src/VectorColumn.cpp
Expand Up @@ -8,7 +8,10 @@ namespace DataObjects
// Please feel free to declare new types as you need them. Syntax is:
// DECLARE_VECTORCOLUMN(type, name-of-the-type);

DECLARE_VECTORCOLUMN(int, vector_int);
DECLARE_VECTORCOLUMN(double, vector_double);
// However, when you do that, please don't forget to add new type to the ITableWorkspace.cpp
// so that it can be converted to Python list

DECLARE_VECTORCOLUMN(int, vector_int)
DECLARE_VECTORCOLUMN(double, vector_double)
} // namespace DataObjects
} // namespace Mantid
Expand Up @@ -2,6 +2,9 @@
#include "MantidAPI/Column.h"
#include "MantidAPI/TableRow.h"
#include "MantidAPI/WorkspaceProperty.h"
#include "MantidPythonInterface/kernel/Converters/NDArrayToVector.h"
#include "MantidPythonInterface/kernel/Converters/PySequenceToVector.h"
#include "MantidPythonInterface/kernel/Converters/CloneToNumpy.h"
#include "MantidPythonInterface/kernel/SharedPtrToPythonMacro.h"
#include "MantidPythonInterface/kernel/Registry/RegisterSingleValueHandler.h"
#include "MantidPythonInterface/kernel/PropertyWithValue.h"
Expand All @@ -14,6 +17,11 @@
#include <boost/preprocessor/tuple/to_list.hpp>
#include <vector>

// See http://docs.scipy.org/doc/numpy/reference/c-api.array.html#PY_ARRAY_UNIQUE_SYMBOL
#define PY_ARRAY_UNIQUE_SYMBOL KERNEL_ARRAY_API
#define NO_IMPORT_ARRAY
#include <numpy/arrayobject.h>

using Mantid::API::ITableWorkspace;
using Mantid::API::ITableWorkspace_sptr;
using Mantid::API::TableRow;
Expand All @@ -26,6 +34,7 @@ using namespace boost::python;
namespace
{
namespace bpl = boost::python;
namespace Converters = Mantid::PythonInterface::Converters;

/// Boost macro for "looping" over builtin types
#define BUILTIN_TYPES \
Expand All @@ -36,6 +45,10 @@ namespace
BOOST_PP_TUPLE_TO_LIST( \
1, (Mantid::Kernel::V3D) \
)
#define ARRAY_TYPES \
BOOST_PP_TUPLE_TO_LIST( \
2, (std::vector<int>, std::vector<double> ) \
)

/**
* Get out the Python value from a specific cell of the supplied column. This is meant to
Expand Down Expand Up @@ -64,12 +77,18 @@ namespace
if(!entry) throw std::invalid_argument("Cannot find converter from C++ type.");\
result = entry->to_python((const void *)&column->cell<T>(row));\
}
#define GET_ARRAY(R, _, T) \
else if(typeID == typeid(T))\
{\
result = Converters::Clone::apply<T::value_type>::create1D( column->cell<T>(row) ); \
}

// -- Use the boost preprocessor to generate a list of else if clause to cut out copy
// and pasted code.
PyObject *result(NULL);
if(false){} // So that it always falls through to the list checking
BOOST_PP_LIST_FOR_EACH(GET_BUILTIN, _ , BUILTIN_TYPES)
BOOST_PP_LIST_FOR_EACH(GET_ARRAY, _ , ARRAY_TYPES)
BOOST_PP_LIST_FOR_EACH(GET_USER, _ , USER_TYPES)
else
{
Expand All @@ -92,18 +111,33 @@ namespace
return;
}

#define SET_CELL(R, _, T) \
#define SET_CELL(R, _, T) \
else if(typeID == typeid(T)) \
{\
column->cell<T>(row) = bpl::extract<T>(value)();\
}
#define SET_VECTOR_CELL(R, _, T) \
else if(typeID == typeid(T)) \
{\
if( ! PyArray_Check( value.ptr() ) ) \
{ \
column->cell<T>(row) = Converters::PySequenceToVector<T::value_type>(value)(); \
} \
else \
{ \
column->cell<T>(row) = Converters::NDArrayToVector<T::value_type>(value)();\
} \
}


// -- Use the boost preprocessor to generate a list of else if clause to cut out copy
// and pasted code.
// I think cppcheck is getting confused by the define
// cppcheck-suppress unreadVariable
const std::type_info & typeID = column->get_type_info();
if(false){} // So that it always falls through to the list checking
BOOST_PP_LIST_FOR_EACH(SET_CELL, _ , BUILTIN_TYPES)
BOOST_PP_LIST_FOR_EACH(SET_VECTOR_CELL, _ , ARRAY_TYPES)
BOOST_PP_LIST_FOR_EACH(SET_CELL, _ , USER_TYPES)
else
{
Expand Down
Expand Up @@ -2,6 +2,7 @@
from testhelpers import run_algorithm
from mantid.kernel import std_vector_str
from mantid.api import WorkspaceFactory
import numpy

class ITableWorkspaceTest(unittest.TestCase):

Expand Down Expand Up @@ -108,6 +109,18 @@ def test_set_and_extract_boolean_columns(self):

self.assertTrue(table.cell(0, 0))
self.assertFalse(table.cell(1, 0))

def test_set_and_extract_vector_columns(self):
table = WorkspaceFactory.createTable()
table.addColumn(type='vector_int', name='values')

# Settings from general Python list
table.addRow([ [1,2,3,4,5] ])
# Setting from numpy array
table.addRow([ numpy.array([6,7,8,9,10]) ])

self.assertTrue( numpy.array_equal( table.cell(0,0), numpy.array([1,2,3,4,5]) ) )
self.assertTrue( numpy.array_equal( table.cell(1,0), numpy.array([6,7,8,9,10]) ) )

if __name__ == '__main__':
unittest.main()

0 comments on commit 6cbe39c

Please sign in to comment.