Skip to content

Commit

Permalink
Refs #4333. Port the binary operations to the new-style interface.
Browse files Browse the repository at this point in the history
  • Loading branch information
martyngigg committed Dec 15, 2011
1 parent 48c4d5f commit 454307f
Show file tree
Hide file tree
Showing 8 changed files with 411 additions and 8 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#ifndef MANTID_PYTHONINTERFACE_BINARYOPERATIONS_H_
#define MANTID_PYTHONINTERFACE_BINARYOPERATIONS_H_
//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------
#include <string>

namespace Mantid
{
namespace PythonInterface
{
/**
Defines helpers to run the binary operation algorithms
Copyright &copy; 2011 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>
*/
/** @name Binary operation helpers */
//@{
/// Binary op for two workspaces
template<typename LHSType, typename RHSType, typename ResultType>
ResultType performBinaryOp(const LHSType lhs, const RHSType rhs,
const std::string & op, const std::string & name,
bool inplace, bool reverse);

/// Binary op for two MDworkspaces
template<typename LHSType, typename RHSType, typename ResultType>
ResultType performBinaryOpMD(const LHSType lhs, const RHSType rhs,
const std::string & op, const std::string & name,
bool inplace, bool reverse);

/// Binary op for a workspace and a double
template<typename LHSType, typename ResultType>
ResultType performBinaryOpWithDouble(const LHSType inputWS, const double value,
const std::string & op, const std::string & name,
bool inplace, bool reverse);

/// Binary op for MDworkspaces + double
template<typename LHSType, typename ResultType>
ResultType performBinaryOpMDWithDouble(const LHSType lhs, const double value,
const std::string & op, const std::string & name,
bool inplace, bool reverse);
//@}
}
}

#endif /* MANTID_PYTHONINTERFACE_BINARYOPERATIONS_H_ */
Original file line number Diff line number Diff line change
Expand Up @@ -12,27 +12,31 @@ set ( EXPORT_FILES
src/AlgorithmFactory.cpp
src/AlgorithmManager.cpp
src/AnalysisDataService.cpp
src/ExperimentInfo.cpp
src/FileProperty.cpp
src/FrameworkManager.cpp
src/Workspace.cpp
src/IMDWorkspace.cpp
src/ExperimentInfo.cpp
src/MatrixWorkspace.cpp
src/IEventWorkspace.cpp
src/BinaryOperations.cpp
)

# Files containing additional helper code that do not require processing
# Files containing additional helper code that are not related to exporting class/functions
set ( SRC_FILES
src/AlgorithmWrapper.cpp
src/WorkspaceToNumpy.cpp
)

set ( INC_FILES
${HEADER_DIR}/api/AlgorithmWrapper.h
${HEADER_DIR}/api/BinaryOperations.h
${HEADER_DIR}/api/WorkspaceToNumpy.h
)

set ( PY_FILES
__init__.py
workspaceops.py
)

# Set the destination directory
Expand Down
7 changes: 7 additions & 0 deletions Code/Mantid/Framework/PythonInterface/mantid/api/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@
from _api import *
_dlopen.restore_flags(flags)

###############################################################################
# Attach operators to workspaces
###############################################################################
import workspaceops as _ops
_ops.attach_binary_operators_to_workspace()

###############################################################################
# Make the singleton objects available as named variables
###############################################################################
Expand All @@ -31,6 +37,7 @@
# Disabled for the time being as all algorithms are of the old kind
#_plugins.load(_cfg['pythonalgorithm.directories'])


###############################################################################
# When in GUI mode we want to be picky about algorithm execution as we
# currently can't run the scripts in a separate thread:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
#include "MantidPythonInterface/api/BinaryOperations.h"
#include "MantidAPI/WorkspaceOpOverloads.h"
#include "MantidAPI/AlgorithmManager.h"
#include "MantidAPI/AnalysisDataService.h"
#include "MantidAPI/WorkspaceGroup.h"
#include "MantidAPI/IMDWorkspace.h"
#include "MantidAPI/MatrixWorkspace.h"
#include "MantidAPI/IMDHistoWorkspace.h"

#include <boost/python/def.hpp>

void export_BinaryOperations()
{
using namespace Mantid::API;

//Operator overloads dispatch through the above structure. The typedefs save some typing
typedef IMDWorkspace_sptr(*binary_fn_md_md)(const IMDWorkspace_sptr, const IMDWorkspace_sptr, const std::string &,const std::string &,bool, bool);
typedef WorkspaceGroup_sptr(*binary_fn_md_gp)(const IMDWorkspace_sptr, const WorkspaceGroup_sptr, const std::string &,const std::string &,bool, bool);
typedef WorkspaceGroup_sptr(*binary_fn_gp_md)(const WorkspaceGroup_sptr, const IMDWorkspace_sptr, const std::string &,const std::string &,bool, bool);
typedef WorkspaceGroup_sptr(*binary_fn_gp_gp)(const WorkspaceGroup_sptr, const WorkspaceGroup_sptr, const std::string &,const std::string &,bool, bool);

typedef IMDHistoWorkspace_sptr(*binary_fn_mh_mh)(const IMDHistoWorkspace_sptr, const IMDHistoWorkspace_sptr, const std::string &,const std::string &,bool, bool);

typedef IMDWorkspace_sptr(*binary_fn_md_db)(const IMDWorkspace_sptr, double, const std::string&,const std::string &,bool,bool);
typedef IMDHistoWorkspace_sptr(*binary_fn_mh_db)(const IMDHistoWorkspace_sptr, double, const std::string&,const std::string &,bool,bool);
typedef WorkspaceGroup_sptr(*binary_fn_gp_db)(const WorkspaceGroup_sptr, double, const std::string&,const std::string &,bool,bool);

// Binary operations helpers
using boost::python::def;
using Mantid::PythonInterface::performBinaryOp;
using Mantid::PythonInterface::performBinaryOpWithDouble;

def("performBinaryOp", (binary_fn_md_md)&performBinaryOp);
def("performBinaryOp", (binary_fn_md_gp)&performBinaryOp);
def("performBinaryOp", (binary_fn_gp_md)&performBinaryOp);
def("performBinaryOp", (binary_fn_gp_gp)&performBinaryOp);
def("performBinaryOp", (binary_fn_mh_mh)&performBinaryOp);

def("performBinaryOp", (binary_fn_md_db)&performBinaryOpWithDouble);
def("performBinaryOp", (binary_fn_mh_db)&performBinaryOpWithDouble);
def("performBinaryOp", (binary_fn_gp_db)&performBinaryOpWithDouble);

}


namespace Mantid
{
namespace PythonInterface
{
using namespace Mantid::API;

/** Binary operation for two workspaces. Generic for IMDWorkspaces or MatrixWorkspaces...
* Called by python overloads for _binary_op (see api_exports.cpp)
*
* @param lhs :: the left hand side workspace of the operation
* @param rhs :: the right hand side workspace of the operation
* @param op :: The operation
* @param name :: The output name
* @param inplace :: is this is an inplace operation (i.e. does the output overwrite the lhs
* @param reverse :: Unused parameter. Here for consistent interface
* @returns The resulting workspace
*/
template<typename LHSType, typename RHSType, typename ResultType>
ResultType performBinaryOp(const LHSType lhs, const RHSType rhs,
const std::string& op, const std::string & name,
bool inplace,bool reverse)
{
std::string algoName = op;

// ----- Determine which version of the algo should be called -----
MatrixWorkspace_const_sptr lhs_mat = boost::dynamic_pointer_cast<const MatrixWorkspace>(lhs);
MatrixWorkspace_const_sptr rhs_mat = boost::dynamic_pointer_cast<const MatrixWorkspace>(rhs);
WorkspaceGroup_const_sptr lhs_grp = boost::dynamic_pointer_cast<const WorkspaceGroup>(lhs);
WorkspaceGroup_const_sptr rhs_grp = boost::dynamic_pointer_cast<const WorkspaceGroup>(rhs);

if ( (lhs_mat || lhs_grp) && (rhs_mat || rhs_grp) )
// Both sides are matrixworkspace - use the original algos (e..g "Plus.")
algoName = op;
else
// One of the workspaces must be MDHistoWorkspace or MDEventWorkspace
// Use the MD version, e.g. "PlusMD"
algoName = op + "MD";

ResultType result;
std::string error("");
try
{
if( reverse )
{
result = API::OperatorOverloads::executeBinaryOperation<RHSType, LHSType, ResultType>(algoName, rhs, lhs, inplace, false, name, true);
}
else
{
result = API::OperatorOverloads::executeBinaryOperation<LHSType, RHSType, ResultType>(algoName, lhs, rhs, inplace, false, name, true);
}
}
catch(std::runtime_error & exc)
{
error = exc.what();
if( error.find("algorithm") == 0 )
{
error = "Unknown binary operation requested: " + op;
throw std::runtime_error(error);
}
else
{
throw;
}
}
return result;
}


/**
* Perform the given binary operation on a workspace and a double.
* Generic to MDWorkspaces.
* Called by python overloads for _binary_op (see api_exports.cpp)
*
* @param lhs :: The input workspace
* @param rhs :: The input value
* @param op :: The operation
* @param inplace :: If true, then the lhs argument is replaced by the result of the operation.
* @param reverse :: If true then the double is the lhs argument
* @return A shared pointer to the result workspace
*/
template<typename LHSType, typename ResultType>
ResultType performBinaryOpWithDouble(const LHSType inputWS, const double value,
const std::string& op, const std::string & name,
bool inplace, bool reverse)
{
std::string algoName = op;

// Create the single valued workspace first so that it is run as a top-level algorithm
// such that it's history can be recreated
API::Algorithm_sptr alg = API::AlgorithmManager::Instance().createUnmanaged("CreateSingleValuedWorkspace");
alg->setChild(false);
alg->initialize();
alg->setProperty<double>("DataValue",value);
const std::string & tmp_name("__tmp_binary_operation_double");
alg->setPropertyValue("OutputWorkspace", tmp_name);
alg->execute();
MatrixWorkspace_sptr singleValue;
API::AnalysisDataServiceImpl & data_store = API::AnalysisDataService::Instance();
if( alg->isExecuted() )
{
singleValue = boost::dynamic_pointer_cast<API::MatrixWorkspace>(data_store.retrieve(tmp_name));
}
else
{
throw std::runtime_error("performBinaryOp: Error in execution of CreateSingleValuedWorkspace");
}
// Call the function above with the signle-value workspace
ResultType result = performBinaryOp<LHSType, MatrixWorkspace_sptr, ResultType>(inputWS, singleValue, algoName, name, inplace, reverse);
// Delete the temporary
data_store.remove(tmp_name);
return result;
}


// Concrete instantations
template IMDWorkspace_sptr performBinaryOp(const IMDWorkspace_sptr, const IMDWorkspace_sptr, const std::string& , const std::string & name,
bool, bool);
template WorkspaceGroup_sptr performBinaryOp(const IMDWorkspace_sptr, const WorkspaceGroup_sptr, const std::string& , const std::string & name,
bool, bool);
template WorkspaceGroup_sptr performBinaryOp(const WorkspaceGroup_sptr, const IMDWorkspace_sptr, const std::string& , const std::string & name,
bool, bool);
template WorkspaceGroup_sptr performBinaryOp(const WorkspaceGroup_sptr, const WorkspaceGroup_sptr, const std::string& , const std::string & name,
bool, bool);

template IMDHistoWorkspace_sptr performBinaryOp(const IMDHistoWorkspace_sptr, const IMDHistoWorkspace_sptr, const std::string& , const std::string & name,
bool, bool);
template IMDHistoWorkspace_sptr performBinaryOp(const IMDHistoWorkspace_sptr, const MatrixWorkspace_sptr, const std::string& , const std::string & name,
bool, bool);

// Double variants
template IMDWorkspace_sptr performBinaryOpWithDouble(const IMDWorkspace_sptr, const double, const std::string& op,
const std::string &, bool, bool);
template IMDHistoWorkspace_sptr performBinaryOpWithDouble(const IMDHistoWorkspace_sptr, const double, const std::string& op,
const std::string &, bool, bool);
template WorkspaceGroup_sptr performBinaryOpWithDouble(const WorkspaceGroup_sptr, const double, const std::string& op,
const std::string &, bool, bool);

}
}



Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#include "MantidAPI/IMDWorkspace.h"
#include <boost/python/class.hpp>
#include <boost/python/register_ptr_to_python.hpp>
#include <boost/python/self.hpp>

using Mantid::API::IMDWorkspace;
using Mantid::API::IMDWorkspace_sptr;
using Mantid::API::Workspace;
using namespace boost::python;

void export_IMDWorkspace()
{
register_ptr_to_python<IMDWorkspace_sptr>();

// EventWorkspace class
class_< IMDWorkspace, bases<Workspace>, boost::noncopyable >("IMDWorkspace", no_init)
.def("getNPoints", &IMDWorkspace::getNPoints, "Returns the total number of points within the workspace")
.def("getNumDims", &IMDWorkspace::getNumDims, "Returns the number of dimensions in the workspace")
.def("getDimension", &IMDWorkspace::getDimension, "Return the chosen dimension of the workspace")
;
}

Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,6 @@ namespace

void export_MatrixWorkspace()
{
// Leave this here for now but move it if it needs expanding to add methods
class_<IMDWorkspace, boost::python::bases<Workspace>, boost::noncopyable>("IMDWorkspace", no_init)
;

register_ptr_to_python<MatrixWorkspace_sptr>();

Expand Down Expand Up @@ -60,7 +57,6 @@ void export_MatrixWorkspace()
"Creates a read-only numpy wrapper around the original E data at the given index")
.def("readDx", &Mantid::PythonInterface::Numpy::wrapDx,
"Creates a read-only numpy wrapper around the original E data at the given index")

.def("extractX", Mantid::PythonInterface::Numpy::cloneX,
"Extracts (copies) the X data from the workspace into a 2D numpy array. "
"Note: This can fail for large workspaces as numpy will require a block "
Expand All @@ -77,7 +73,7 @@ void export_MatrixWorkspace()
"Extracts (copies) the E data from the workspace into a 2D numpy array. "
"Note: This can fail for large workspaces as numpy will require a block "
"of memory free that will fit all of the data.")
;
;

DECLARE_SINGLEVALUETYPEHANDLER(MatrixWorkspace, DataItem_sptr);
}
Expand Down

0 comments on commit 454307f

Please sign in to comment.