###############################################################################
# PythonCalc
#
# A VisTrails package is simply a Python class that subclasses from
# Module. For this class to be executable, it must define a method
# compute(self) that will perform the appropriate computations and set
# the results.
#
# Extra helper methods can be defined, as usual. In this case, we're
# using a helper method op(self, v1, v2) that performs the right
# operations.
from vistrails.core.modules.vistrails_module import Module, ModuleError
from vistrails.core.modules.config import IPort, OPort
class PythonCalc(Module):
"""PythonCalc is a module that performs simple arithmetic operations
on its inputs."""
# You need to report the ports the module wants to make
# available. This is done by creating _input_ports and
# _output_ports lists composed of InputPort (IPort) and OutputPort
# (OPort) objects. These are simple ports that take only one
# value. We'll see in later tutorials how to create compound ports
# which can take a tuple of values. Each port must specify its
# name and signature. The signature specifies the package
# (e.g. "basic" which is shorthand for
# "org.vistrails.vistrails.basic") and module (e.g. "Float").
# Note that the third input port (op) has two other arguments.
# The "enum" entry_type specifies that there are a set of options
# the user should choose from, and the values then specifies those
# options.
_input_ports = [IPort(name="value1", signature="basic:Float"),
IPort(name="value2", signature="basic:Float"),
IPort(name="op", signature="basic:String",
entry_type="enum", values=["+", "-", "*", "/"])]
_output_ports = [OPort(name="value", signature="basic:Float")]
# This constructor is strictly unnecessary. However, some modules
# might want to initialize per-object data. When implementing your
# own constructor, remember that it must not take any extra
# parameters.
def __init__(self):
Module.__init__(self)
# This is the method you should implement in every module that
# will be executed directly. VisTrails does not use the return
# value of this method.
def compute(self):
# get_input is a method defined in Module that returns
# the value stored at an input port. If there's no value
# stored on the port, the method will return None.
v1 = self.get_input("value1")
v2 = self.get_input("value2")
# You should call set_output to store the appropriate results
# on the ports. In this case, we are only storing a
# floating-point result, so we can use the number types
# directly. For more complicated data, you should
# return an instance of a VisTrails Module. This will be made
# clear in further examples that use these more complicated data.
self.set_output("value", self.op(v1, v2))
def op(self, v1, v2):
op = self.get_input("op")
if op == '+':
return v1 + v2
elif op == '-':
return v1 - v2
elif op == '*':
return v1 * v2
elif op == '/':
return v1 / v2
# If a module wants to report an error to VisTrails, it should raise
# ModuleError with a descriptive error. This allows the interpreter
# to capture the error and report it to the caller of the evaluation
# function.
raise ModuleError(self, "unrecognized operation: '%s'" % op)
# VisTrails will only load the modules specified in the _modules list.
# This list contains all of the modules a package defines.
_modules = [PythonCalc,]