Skip to content

Commit

Permalink
Refs #4333. Rationalize the table workspace access.
Browse files Browse the repository at this point in the history
The get[Type] functions are gone on the new interface in favour of a
single cell function that will return the appropriate type based
on the column data type.
  • Loading branch information
martyngigg committed Dec 21, 2011
1 parent f54a051 commit d4ebb09
Show file tree
Hide file tree
Showing 5 changed files with 134 additions and 3 deletions.
1 change: 1 addition & 0 deletions Code/Mantid/Framework/PythonInterface/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ set ( TEST_PY_FILES
test/python/ImportModuleTest.py
test/python/IPeaksWorkspaceTest.py
test/python/InstrumentTest.py
test/python/ITableWorkspaceTest.py
test/python/LoggerTest.py
test/python/MatrixWorkspaceTest.py
test/python/MDHistoWorkspaceTest.py
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,116 @@
#include "MantidAPI/ITableWorkspace.h"
#include "MantidAPI/Column.h"
#include "MantidAPI/WorkspaceProperty.h"
#include "MantidPythonInterface/kernel/SingleValueTypeHandler.h"
#include "MantidPythonInterface/kernel/PropertyWithValue.h"

#include <boost/python/class.hpp>
#include <boost/python/register_ptr_to_python.hpp>
#include <boost/python/converter/builtin_converters.hpp>

using Mantid::API::ITableWorkspace;
using Mantid::API::ITableWorkspace_sptr;
using Mantid::API::Workspace;
using Mantid::Kernel::DataItem_sptr;
using namespace boost::python;

namespace
{
namespace bpl = boost::python;

/**
* Access a cell and return a corresponding Python type
* @param self A reference to the TableWorkspace python object that we were called on
* @param value A python object containing either a row index or a column name
* @param row_or_col An integer giving the row if value is a string or the column if value is an index
*/
PyObject * cell(ITableWorkspace &self, bpl::object value, int row_or_col)
{
// Find the column and row
Mantid::API::Column_const_sptr column;
int row(-1);
if( PyString_Check(value.ptr()) )
{
column = self.getColumn( extract<std::string>(value)());
row = row_or_col;
}
else
{
row = extract<int>(value)();
column = self.getColumn(row_or_col);
}
// Boost.Python doesn't have a searchable registry for builtin types so
// this is yet another lookup. There must be a better way to do this!

const std::type_info & typeID = column->get_type_info();
PyObject *result(NULL);
if( typeID == typeid(double) )
{
result = to_python_value<const double&>()(column->cell<double>(row));
}
else if( typeID == typeid(std::string) )
{
result = to_python_value<const std::string&>()(column->cell<std::string>(row));
}
else if( typeID == typeid(int) )
{
result = to_python_value<const int &>()(column->cell<int>(row));
}
else if( typeID == typeid(int64_t) )
{
result = to_python_value<const int64_t &>()(column->cell<int64_t>(row));
}
else if( typeID == typeid(bool) )
{
result = to_python_value<const bool &>()(column->cell<bool>(row));
}
else if( typeID == typeid(float) )
{
result = to_python_value<const float &>()(column->cell<float>(row));
}
else if( typeID == typeid(Mantid::Kernel::V3D) )
{
const converter::registration *entry = converter::registry::query(typeid(Mantid::Kernel::V3D));
if(!entry) throw std::invalid_argument("ITableWorkspace::cell - Cannot find convert to V3D type.");
result = entry->to_python((const void *)&column->cell<Mantid::Kernel::V3D>(row));
}
else
{
throw std::invalid_argument("ITableWorkspace::cell - Cannot convert column data type to python: " + column->type());
}

return result;
}
}

void export_ITableWorkspace()
{
register_ptr_to_python<ITableWorkspace_sptr>();

class_<ITableWorkspace,bases<Workspace>, boost::noncopyable>("ITableWorkspace", no_init)
;
.def("columnCount", &ITableWorkspace::columnCount, "Returns the number of columns in the workspace")
.def("rowCount", &ITableWorkspace::rowCount, "Returns the number of rows within the workspace")
.def("getColumnNames",&ITableWorkspace::getColumnNames, "Return a list of the column names")
.def("cell", &cell, "Return the given cell. If the first argument is a number then it is interpreted as a row"
"otherwise it is interpreted as a column name")
;

DECLARE_SINGLEVALUETYPEHANDLER(ITableWorkspace, Mantid::Kernel::DataItem_sptr);
}

void export_ITableWorkspaceProperty()
{
using Mantid::API::WorkspaceProperty;
using Mantid::API::IWorkspaceProperty;
using Mantid::Kernel::PropertyWithValue;

// PropertyWithValue<ITableWorkspace_sptr>
EXPORT_PROP_W_VALUE(ITableWorkspace_sptr, ITableWorkspace);
// Register a bare pointer to the type
register_ptr_to_python<WorkspaceProperty<ITableWorkspace>*>();
// Finally the WorkspaceProperty<ITableWorkspace> hierarchy
class_<WorkspaceProperty<ITableWorkspace>, bases<PropertyWithValue<ITableWorkspace_sptr>,IWorkspaceProperty>,
boost::noncopyable>("WorkspaceProperty_ITableWorkspace", no_init)
;
}

Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ namespace Mantid
}
else
{
throw std::invalid_argument("PropertyMarshal::setProperty - No C++ function registered to handle python type '" + std::string(pytype->tp_name) + "'");
throw std::invalid_argument("PropertyMarshal::setProperty - No C++ function registered to handle python type '"
+ std::string(pytype->tp_name) + "'");
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import unittest
from testhelpers import run_algorithm
from mantid.kernel import std_vector_str

class ITableWorkspaceTest(unittest.TestCase):

_test_ws = None

def setUp(self):
if self._test_ws is None:
alg = run_algorithm('RawFileInfo', Filename='LOQ48127.raw',GetRunParameters=True, child=True)
self.__class__._test_ws = alg.getProperty('RunParameterTable').value

def test_meta_information_is_correct(self):
self.assertEquals(self._test_ws.columnCount(), 19)
self.assertEquals(self._test_ws.rowCount(), 1)

column_names = self._test_ws.getColumnNames()
self.assertEquals(len(column_names), 19)
self.assertEquals(type(column_names), std_vector_str)

def test_cell_access_returns_variables_as_native_python_types(self):
self.assertAlmostEquals(self._test_ws.cell('r_gd_prtn_chrg',0), 10.040912628173828, 15)
self.assertAlmostEquals(self._test_ws.cell(0, 7), 10.040912628173828, 15)

self.assertEquals(self._test_ws.cell('r_goodfrm', 0), 9229)
self.assertEquals(self._test_ws.cell(0, 9), 9229)

self.assertEquals(self._test_ws.cell('r_enddate', 0), "18-DEC-2008")
self.assertEquals(self._test_ws.cell(0, 16), "18-DEC-2008")

if __name__ == '__main__':
unittest.main()
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ def run_algorithm(name, **kwargs):
if 'child'in kwargs:
alg.setChild(True)
del kwargs['child']
alg.setPropertyValue("OutputWorkspace","UNUSED_NAME_FOR_CHILD")
if 'OutputWorkspace' in alg:
alg.setPropertyValue("OutputWorkspace","UNUSED_NAME_FOR_CHILD")
for key, value in kwargs.iteritems():
alg.setProperty(key, value)
alg.execute()
Expand Down

0 comments on commit d4ebb09

Please sign in to comment.