Skip to content

Commit

Permalink
Refs #4333. IPeaksWorkspace, TableWorkspace and history to Python.
Browse files Browse the repository at this point in the history
  • Loading branch information
martyngigg committed Dec 19, 2011
1 parent 9775b28 commit 4ac1adb
Show file tree
Hide file tree
Showing 12 changed files with 231 additions and 15 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 @@ -77,6 +77,7 @@ set ( TEST_PY_FILES
test/python/IComponentTest.py
test/python/IEventWorkspaceTest.py
test/python/ImportModuleTest.py
test/python/IPeaksWorkspaceTest.py
test/python/InstrumentTest.py
test/python/LoggerTest.py
test/python/MatrixWorkspaceTest.py
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,18 @@ set ( EXPORT_FILES
src/FrameworkManager.cpp
src/IEventList.cpp
src/ISpectrum.cpp
src/WorkspaceHistory.cpp
src/Workspace.cpp
src/ITableWorkspace.cpp
src/IMDWorkspace.cpp
src/ExperimentInfo.cpp
src/MatrixWorkspace.cpp
src/IEventWorkspace.cpp
src/IPeaksWorkspace.cpp
src/BinaryOperations.cpp
src/WorkspaceGroup.cpp
src/Axis.cpp
src/IPeak.cpp
)

# Files containing additional helper code that are not related to exporting class/functions
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "MantidAPI/IMDWorkspace.h"
#include "MantidPythonInterface/kernel/SingleValueTypeHandler.h"
#include <boost/python/class.hpp>
#include <boost/python/register_ptr_to_python.hpp>
#include <boost/python/self.hpp>
Expand All @@ -18,5 +19,8 @@ void export_IMDWorkspace()
.def("getNumDims", &IMDWorkspace::getNumDims, "Returns the number of dimensions in the workspace")
.def("getDimension", &IMDWorkspace::getDimension, "Return the chosen dimension of the workspace")
;

DECLARE_SINGLEVALUETYPEHANDLER(IMDWorkspace, Mantid::Kernel::DataItem_sptr);

}

54 changes: 54 additions & 0 deletions Code/Mantid/Framework/PythonInterface/mantid/api/src/IPeak.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#include "MantidAPI/IPeak.h"
#include <boost/python/class.hpp>
#include <boost/python/register_ptr_to_python.hpp>

using Mantid::API::IPeak;
using namespace boost::python;

void export_IPeak()
{
register_ptr_to_python<IPeak*>();

class_<IPeak, boost::noncopyable>("IPeak", no_init)
.def("getDetectorID", &IPeak::getDetectorID, "Get the ID of the detector at the center of the peak")
.def("setDetectorID", &IPeak::setDetectorID, "Set the detector ID and look up and cache values related to it.")
.def("getRunNumber", &IPeak::getRunNumber, "Return the run number this peak was measured at")
.def("setRunNumber", &IPeak::setRunNumber, "Set the run number that measured this peak")
.def("getH", &IPeak::getH, "Get the H index of the peak")
.def("getK", &IPeak::getK, "Get the K index of the peak")
.def("getL", &IPeak::getL, "Get the L index of the peak")
.def("getHKL", &IPeak::getHKL, "Get HKL as a V3D object")
.def("setHKL", (void (IPeak::*)(double,double,double)) &IPeak::setHKL, "Set the HKL values of this peak")
.def("setH", &IPeak::setH, "Get the H index of the peak")
.def("setK", &IPeak::setK, "Get the K index of the peak")
.def("setL", &IPeak::setL, "Get the L index of the peak")
.def("getQLabFrame", &IPeak::getQLabFrame, "Return the Q change (of the lattice, k_i - k_f) for this peak.\n"
"The Q is in the Lab frame: the goniometer rotation was NOT taken out.\n"
"Note: There is no 2*pi factor used, so |Q| = 1/wavelength.")
.def("getQSampleFrame", &IPeak::getQSampleFrame, "Return the Q change (of the lattice, k_i - k_f) for this peak."
"The Q is in the Sample frame: the goniometer rotation WAS taken out. ")
.def("setQLabFrame", &IPeak::setQLabFrame, "Set the peak using the peak's position in reciprocal space, in the lab frame.")
.def("setQSampleFrame", &IPeak::setQSampleFrame, "Set the peak using the peak's position in reciprocal space, in the sample frame.")
.def("setWavelength", &IPeak::setWavelength, "Set the incident wavelength of the neutron. Calculates the energy from this assuming elastic scattering.")
.def("getWavelength", &IPeak::getWavelength, "Return the incident wavelength")
.def("getScattering", &IPeak::getScattering, "Calculate the scattering angle of the peak")
.def("getDSpacing", &IPeak::getDSpacing, "Calculate the d-spacing of the peak, in 1/Angstroms")
.def("getTOF", &IPeak::getTOF, "Calculate the time of flight (in microseconds) of the neutrons for this peak")
.def("getInitialEnergy", &IPeak::getInitialEnergy, "Get the initial (incident) neutron energy")
.def("getFinalEnergy", &IPeak::getFinalEnergy, "Get the final neutron energy")
.def("setInitialEnergy", &IPeak::setInitialEnergy, "Set the initial (incident) neutron energy")
.def("setFinalEnergy", &IPeak::setFinalEnergy, "Set the final neutron energy")
.def("getIntensity", &IPeak::getIntensity, "Return the integrated peak intensity")
.def("getSigmaIntensity", &IPeak::getSigmaIntensity, "Return the error on the integrated peak intensity")
.def("setIntensity", &IPeak::setIntensity, "Set the integrated peak intensity")
.def("setSigmaIntensity", &IPeak::setSigmaIntensity, "Set the error on the integrated peak intensity")
.def("getBinCount", &IPeak::getBinCount, "Return the # of counts in the bin at its peak")
.def("setBinCount", &IPeak::setBinCount, "Set the # of counts in the bin at its peak")
.def("getRow", &IPeak::getRow, "For RectangularDetectors only, returns the row (y) of the pixel of the detector.")
.def("getCol", &IPeak::getCol, "For RectangularDetectors only, returns the column (x) of the pixel of the detector.")
.def("getDetPos", &IPeak::getDetPos, "Return the detector position vector")
.def("getL1", &IPeak::getL1, "Return the L1 flight path length (source to sample), in meters. ")
.def("getL2", &IPeak::getL2, "Return the L2 flight path length (sample to detector), in meters.")
;
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#include "MantidAPI/IPeaksWorkspace.h"
#include "MantidAPI/IPeak.h"
#include "MantidPythonInterface/kernel/SingleValueTypeHandler.h"
#include <boost/python/class.hpp>
#include <boost/python/register_ptr_to_python.hpp>
#include <boost/python/return_internal_reference.hpp>

using Mantid::API::IPeaksWorkspace;
using Mantid::API::IPeaksWorkspace_sptr;
using Mantid::API::IPeak;
using Mantid::API::ExperimentInfo;
using Mantid::API::ITableWorkspace;

using namespace boost::python;

void export_IPeaksWorkspace()
{
register_ptr_to_python<IPeaksWorkspace_sptr>();

// IPeaksWorkspace class
class_< IPeaksWorkspace, bases<ITableWorkspace, ExperimentInfo>, boost::noncopyable >("IPeaksWorkspace", no_init)
.def("getNumberPeaks", &IPeaksWorkspace::getNumberPeaks, "Returns the number of peaks within the workspace")
.def("addPeak", &IPeaksWorkspace::addPeak, "Add a peak to the workspace")
.def("removePeak", &IPeaksWorkspace::removePeak, "Remove a peak from the workspace")
.def("getPeak", &IPeaksWorkspace::getPeakPtr, return_internal_reference<>(), "Returns a peak at the given index" )
.def("createPeak", &IPeaksWorkspace::createPeak, return_internal_reference<>(), "Create a Peak and return it")
;

DECLARE_SINGLEVALUETYPEHANDLER(IPeaksWorkspace, Mantid::Kernel::DataItem_sptr);

}

Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#include "MantidAPI/ITableWorkspace.h"
#include "MantidPythonInterface/kernel/SingleValueTypeHandler.h"
#include <boost/python/class.hpp>
#include <boost/python/register_ptr_to_python.hpp>

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

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

class_<ITableWorkspace,bases<Workspace>, boost::noncopyable>("ITableWorkspace", no_init)
;

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

Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
#include <boost/python/class.hpp>
#include <boost/python/overloads.hpp>
#include <boost/python/args.hpp>
#include <boost/python/return_value_policy.hpp>
#include <boost/python/copy_const_reference.hpp>
#include <boost/python/register_ptr_to_python.hpp>

Expand All @@ -32,7 +31,7 @@ void export_Workspace()
.def("getComment", &Workspace::getComment, return_value_policy<copy_const_reference>(), "Returns the comment field on the workspace")
.def("isDirty", &Workspace::isDirty, Workspace_isDirtyOverloads(args("n"), "True if the workspace has run more than n algorithms (Default=1)"))
.def("getMemorySize", &Workspace::getMemorySize, "Returns the memory footprint of the workspace in KB")
.def("getHistory", &Workspace::getHistory, return_value_policy<copy_const_reference>(),
.def("getHistory", (const WorkspaceHistory &(Workspace::*)() const)&Workspace::getHistory, return_value_policy<reference_existing_object>(),
"Return read-only access to the workspace history")
;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#include "MantidAPI/WorkspaceHistory.h"
#include "MantidAPI/IAlgorithm.h"
#include <boost/python/class.hpp>
#include <boost/python/self.hpp>
#include <boost/python/operators.hpp>
#include <boost/python/register_ptr_to_python.hpp>

using Mantid::API::WorkspaceHistory;
using Mantid::API::IAlgorithm;
using namespace boost::python;

void export_WorkspaceHistory()
{
register_ptr_to_python<WorkspaceHistory*>();

class_<WorkspaceHistory, boost::noncopyable>("WorkspaceHistory", no_init)
.def("lastAlgorithm", &WorkspaceHistory::lastAlgorithm, "Returns the last algorithm run on this workspace so that its properties can be accessed")
.def("getAlgorithm", &WorkspaceHistory::getAlgorithm, "Returns the algorithm at the given index in the history")
// ----------------- Operators --------------------------------------
.def("__getitem__", &WorkspaceHistory::getAlgorithm)
.def(self_ns::str(self))
;
}

Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ void export_V3D()
//V3D class
class_< V3D >("V3D",init<>("Construct a V3D at the origin"))
.def(init<double, double, double>("Construct a V3D with X,Y,Z coordinates"))
.def("x", &V3D::X, return_value_policy< copy_const_reference >(), "Returns the X coordinate")
.def("y", &V3D::Y, return_value_policy< copy_const_reference >(), "Returns the Y coordinate")
.def("z", &V3D::Z, return_value_policy< copy_const_reference >(), "Returns the Z coordinate")
.def("X", &V3D::X, return_value_policy< copy_const_reference >(), "Returns the X coordinate")
.def("Y", &V3D::Y, return_value_policy< copy_const_reference >(), "Returns the Y coordinate")
.def("Z", &V3D::Z, return_value_policy< copy_const_reference >(), "Returns the Z coordinate")
.def("distance", &V3D::distance, "Returns the distance between this vector and another")
.def("angle", &V3D::angle, "Returns the angle between this vector and another")
.def("zenith", &V3D::zenith, "Returns the zenith between this vector and another")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import unittest
from testhelpers import run_algorithm
from mantid import mtd, IPeaksWorkspace, V3D

class IPeaksWorkspaceTest(unittest.TestCase):
"""
Test the python interface to PeaksWorkspace's
"""

def setUp(self):
run_algorithm('LoadEventNexus',Filename='CNCS_7860_event.nxs', OutputWorkspace='cncs',
FilterByTimeStart=60.0,FilterByTimeStop=60.5,LoadMonitors=False)
run_algorithm('CreatePeaksWorkspace',InstrumentWorkspace='cncs', OutputWorkspace='peaks')

def test_interface(self):
""" Rudimentary test to get peak and get/set some values """
pws = mtd['peaks']
self.assertTrue(isinstance(pws, IPeaksWorkspace))
self.assertEqual(pws.getNumberPeaks(), 1)
p = pws.getPeak(0)

# Try a few IPeak get/setters. Not everything.
p.setH(234)
self.assertEqual(p.getH(), 234)
p.setHKL(5,6,7)
self.assertEqual(p.getH(), 5)
self.assertEqual(p.getK(), 6)
self.assertEqual(p.getL(), 7)

hkl = p.getHKL()
self.assertEquals(hkl, V3D(5,6,7))

p.setIntensity(456)
p.setSigmaIntensity(789)
self.assertEqual(p.getIntensity(), 456)
self.assertEqual(p.getSigmaIntensity(), 789)

# Finally try to remove a peak
pws.removePeak(0)
self.assertEqual(pws.getNumberPeaks(), 0)

# Create a new peak at some Q in the lab frame
qlab = V3D(1,2,3)
p = pws.createPeak(qlab, 1.54)
self.assertAlmostEquals( p.getQLabFrame().X(), 1.0, 3)

# Now try to add the peak back
pws.addPeak(p)
self.assertEqual(pws.getNumberPeaks(), 1)

# Check that it is what we added to it
p = pws.getPeak(0)
self.assertAlmostEquals( p.getQLabFrame().X(), 1.0, 3)

mtd.remove('cncs')
mtd.remove('peaks')

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


Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@ def test_spectrum_retrieval(self):
for i in range(len(ids)):
self.assertEquals(expected[i], ids[i])


def test_that_a_histogram_workspace_is_returned_as_a_MatrixWorkspace_from_a_property(self):
self.assertEquals(type(self._test_ws_prop), WorkspaceProperty_Workspace)
# Is Workspace in the hierarchy of the value
Expand Down Expand Up @@ -148,6 +147,24 @@ def test_operators_with_workspaces_in_ADS(self):
# Commutative: double + workspace
C = B * A
C = B + A

ads.remove('A')
ads.remove('B')
ads.remove('C')

def test_history_access(self):
run_algorithm('CreateWorkspace', OutputWorkspace='raw',DataX=[1.,2.,3.], DataY=[2.,3.], DataE=[2.,3.],UnitX='TOF')
run_algorithm('Rebin', InputWorkspace='raw', Params=[1.,0.5,3.],OutputWorkspace='raw')
ads = AnalysisDataService.Instance()
raw = ads['raw']
history = raw.getHistory()
last = history.lastAlgorithm()
self.assertEquals(last.name(), "Rebin")
self.assertEquals(last.getPropertyValue("InputWorkspace"), "raw")
first = history[0]
self.assertEquals(first.name(), "CreateWorkspace")
self.assertEquals(first.getPropertyValue("OutputWorkspace"), "raw")
ads.remove('raw')

if __name__ == '__main__':
unittest.main()
Expand Down
18 changes: 9 additions & 9 deletions Code/Mantid/Framework/PythonInterface/test/python/V3DTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@ class V3DTest(unittest.TestCase):

def test_default_construction_is_at_origin(self):
p = V3D()
self.assertEquals(p.x(), 0.0)
self.assertEquals(p.y(), 0.0)
self.assertEquals(p.z(), 0.0)
self.assertEquals(p.X(), 0.0)
self.assertEquals(p.Y(), 0.0)
self.assertEquals(p.Z(), 0.0)

def test_construction_with_xyz(self):
p = V3D(1.5,2.4,6.5)
self.assertEquals(p.x(), 1.5)
self.assertEquals(p.y(), 2.4)
self.assertEquals(p.z(), 6.5)
self.assertEquals(p.X(), 1.5)
self.assertEquals(p.Y(), 2.4)
self.assertEquals(p.Z(), 6.5)

def test_distance(self):
a = V3D(0.0,0.0,0.0)
Expand Down Expand Up @@ -56,9 +56,9 @@ def test_crossprod(self):
a = V3D(1.0,0.0,0.0)
b = V3D(0.0,1.0,0.0)
c = a.cross_prod(b)
self.assertAlmostEquals(c.x(),0.0)
self.assertAlmostEquals(c.y(),0.0)
self.assertAlmostEquals(c.z(),1.0)
self.assertAlmostEquals(c.X(),0.0)
self.assertAlmostEquals(c.Y(),0.0)
self.assertAlmostEquals(c.Z(),1.0)

def test_norm(self):
p = V3D(1.0,-5.0,8.0);
Expand Down

0 comments on commit 4ac1adb

Please sign in to comment.