-
Notifications
You must be signed in to change notification settings - Fork 122
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refs #4333. Export Run along with the dict-style interface.
- Loading branch information
1 parent
b68b143
commit 0586cc9
Showing
8 changed files
with
204 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
122 changes: 122 additions & 0 deletions
122
Code/Mantid/Framework/PythonInterface/mantid/api/src/Run.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
#include "MantidAPI/Run.h" | ||
#include <boost/python/class.hpp> | ||
#include <boost/python/register_ptr_to_python.hpp> | ||
#include <boost/python/overloads.hpp> | ||
#include <boost/python/args.hpp> | ||
|
||
using Mantid::API::Run; | ||
using namespace boost::python; | ||
|
||
namespace | ||
{ | ||
namespace bpl = boost::python; | ||
|
||
/** | ||
* Emulate dict.get. Returns the value pointed to by the key or the default given | ||
* @param self The object called on | ||
* @param key The key | ||
* @param default_ The default to return if it does not exist | ||
*/ | ||
bpl::object getWithDefault(bpl::object self, bpl::object key, bpl::object default_) | ||
{ | ||
bpl::object exists(self.attr("__contains__")); | ||
if( extract<bool>(exists(key))() ) | ||
{ | ||
return self.attr("__getitem__")(key); | ||
} | ||
else | ||
{ | ||
return default_; | ||
} | ||
} | ||
|
||
/** | ||
* Emulate dict.get. Returns the value pointed to by the key or None if it doesn't exist | ||
* @param self The bpl::object called on | ||
* @param key The key | ||
*/ | ||
bpl::object get(bpl::object self, bpl::object key) | ||
{ | ||
return getWithDefault(self, key, bpl::object()); | ||
} | ||
|
||
|
||
/** | ||
* Add a property with the given name and value | ||
* @param self A reference to the run object that we have been called on | ||
* @param name The name of the new property | ||
* @param value The value of the property | ||
* @param units A string representing a unit | ||
* @param replace If true, replace an existing property with this one else raise an error | ||
*/ | ||
void addPropertyWithUnit(Run & self, const std::string & name, PyObject *value, const std::string & units, bool replace) | ||
{ | ||
if( PyFloat_Check(value) ) | ||
{ | ||
self.addProperty(name, extract<double>(value)(), units, replace); | ||
} | ||
else if( PyInt_Check(value) ) | ||
{ | ||
self.addProperty(name, extract<long>(value)(), units, replace); | ||
} | ||
else if( PyString_Check(value) ) | ||
{ | ||
self.addProperty(name, extract<std::string>(value)(), units, replace); | ||
} | ||
else | ||
{ | ||
std::ostringstream msg; | ||
msg << "Run::addProperty - Unknown value type given: " << value->ob_type->tp_name; | ||
throw std::invalid_argument(msg.str()); | ||
} | ||
} | ||
|
||
/** | ||
* Add a property with the given name and value | ||
* @param self A reference to the run object that we have been called on | ||
* @param name The name of the new property | ||
* @param value The value of the property | ||
* @param replace If true, replace an existing property with this one else raise an error | ||
*/ | ||
void addProperty(Run & self, const std::string & name, PyObject *value, bool replace) | ||
{ | ||
addPropertyWithUnit(self, name, value, "", replace); | ||
} | ||
|
||
/** | ||
* Add a property with the given name and value. An existing property is overwritten if it exists | ||
* @param self A reference to the run object that we have been called on | ||
* @param name The name of the new property | ||
* @param value The value of the property | ||
*/ | ||
void addOrReplaceProperty(Run & self, const std::string & name, PyObject *value) | ||
{ | ||
addProperty(self, name, value, true); | ||
} | ||
|
||
|
||
} | ||
|
||
void export_Run() | ||
{ | ||
//Pointer | ||
register_ptr_to_python<Run*>(); | ||
|
||
//Run class | ||
class_< Run, boost::noncopyable >("Run", no_init) | ||
.def("getProtonCharge", &Run::getProtonCharge, "Return the total good proton charge for the run") | ||
.def("hasProperty", &Run::hasProperty, "Returns True if the given log value is contained within the run") | ||
.def("getProperty", &Run::getProperty, return_value_policy<return_by_value>(), "Returns the named property (log value). Use '.value' to return the value.") | ||
.def("getProperties", &Run::getProperties, return_internal_reference<>(), "Return the list of run properties managed by this object.") | ||
.def("addProperty", &addProperty, "Adds a property with the given name and value. If replace=True then an existing property is overwritten") | ||
.def("addProperty", &addPropertyWithUnit, "Adds a property with the given name, value and unit. If replace=True then an existing property is overwritten") | ||
//--------------------------- Dictionary access---------------------------- | ||
.def("get", &getWithDefault, "Returns the value pointed to by the key or None if it does not exist") | ||
.def("get", &get, "Returns the value pointed to by the key or the default value given") | ||
.def("__contains__", &Run::hasProperty) | ||
.def("__getitem__", &Run::getProperty, return_value_policy<return_by_value>()) | ||
.def("__setitem__", &addOrReplaceProperty) | ||
|
||
; | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
66 changes: 66 additions & 0 deletions
66
Code/Mantid/Framework/PythonInterface/test/python/RunTest.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
import unittest | ||
from testhelpers import run_algorithm | ||
|
||
class RunTest(unittest.TestCase): | ||
|
||
_expt_ws = None | ||
|
||
def setUp(self): | ||
if self.__class__._expt_ws is None: | ||
alg = run_algorithm('Load', Filename='LOQ48127.raw', SpectrumMax=1, child=True) | ||
self.__class__._expt_ws = alg.getProperty("OutputWorkspace").value | ||
|
||
def test_proton_charge_returns_a_double(self): | ||
run = self._expt_ws.run() | ||
charge = run.getProtonCharge() | ||
self.assertEquals(type(charge), float) | ||
self.assertAlmostEquals(charge, 10.040912628173828, 15) | ||
|
||
def test_run_hasProperty(self): | ||
self.assertTrue(self._expt_ws.run().hasProperty('run_start')) | ||
self.assertTrue('run_start' in self._expt_ws.run()) | ||
self.assertFalse('not a log' in self._expt_ws.run()) | ||
|
||
def test_run_getProperty(self): | ||
run_start = self._expt_ws.run().getProperty('run_start') | ||
self.assertEquals(type(run_start.value), str) | ||
self.assertEquals(run_start.value, "2008-12-18T17:58:38") | ||
|
||
def do_spectra_check(nspectra): | ||
self.assertEquals(type(nspectra.value), int) | ||
self.assertEquals(nspectra.value, 8) | ||
self.assertRaises(RuntimeError, self._expt_ws.run().getProperty, 'not_a_log') | ||
|
||
do_spectra_check(self._expt_ws.run().getProperty('nspectra')) | ||
do_spectra_check(self._expt_ws.run()['nspectra']) | ||
do_spectra_check(self._expt_ws.run().get('nspectra')) | ||
|
||
# get returns the default if key does not exist, or None if no default | ||
self.assertEquals(self._expt_ws.run().get('not_a_log'), None) | ||
self.assertEquals(self._expt_ws.run().get('not_a_log', 5.), 5.) | ||
|
||
def test_add_property_with_known_type_succeeds(self): | ||
run = self._expt_ws.run() | ||
nprops = len(run.getProperties()) | ||
run.addProperty('int_t', 1, False) | ||
self.assertEquals(len(run.getProperties()), nprops + 1) | ||
run.addProperty('float_t', 2.4, False) | ||
self.assertEquals(len(run.getProperties()), nprops + 2) | ||
run.addProperty('str_t', 'from_python', False) | ||
self.assertEquals(len(run.getProperties()), nprops + 3) | ||
run['int_t'] = 6.5 | ||
self.assertEquals(len(run.getProperties()), nprops + 3) | ||
self.assertEquals(run.getProperty('int_t').value, 6.5) | ||
|
||
def test_add_propgates_units_correctly(self): | ||
run = self._expt_ws.run() | ||
run.addProperty('float_t', 2.4, 'metres', True) | ||
prop = run.getProperty('float_t') | ||
self.assertEquals(prop.units, 'metres') | ||
|
||
def test_add_property_with_unknown_type_raises_error(self): | ||
run = self._expt_ws.run() | ||
self.assertRaises(ValueError, run.addProperty, 'dict_t', {}, False) | ||
|
||
if __name__ == '__main__': | ||
unittest.main() |