mapteksdk.workflows module

Module containing utilities to assist in running Python scripts in the Extend Python Workflow component.

exception mapteksdk.workflows.InvalidConnectorNameError

Bases: ValueError

Error raised when a connector name is invalid.

class mapteksdk.workflows.WorkflowArgumentParser(description='')

Bases: object

Class designed to help scripts interface with workflows. In particular, scripts which use this class can automatically generate their input and output connectors via the “Generate Connectors” button in the workflow component configuration. Scripts which use this class are also runnable via the command line - values for the input connectors can be passed as command line arguments.

Using this class is highly recommended for scripts intended to be embedded in workflows.

Parameters

description (str) – A description of the script. If –help is passed to the script, this will appear in the help message.

Notes

This table displays what Python type should be passed to declare_input_connector() or declare_output_connector() for a connector which filters input to a specified type.

Workflow type

Python type

String

str

Integer

int

Double

float

DateTime

datetime.datetime

Boolean

bool

CSV

list

Selection

WorkflowSelection

Other

str

Examples

Creating 3D Text Script which creates 3D text with a specified message at a specified path, using a list to pass the colours and position of the text. If this script was embedded in the Extend Python Workflow component it would need three input connectors “text”, “position” and “colour” which would filter values to types “String”, “List” and “List” respectively. Values passed to these connectors in the workflow could be used to set the text, position and colour of the created 3D text.

The script can also be run through the command line. If it was in a file called “create_3d_text.py” and was run using: py create_3d_text.py Then it would create a 3D text object in the currently running project with green text “Hello World” at [0, 0, 0]. However if were run with the command: create_3d_text.py –text=”Hi” –position=”1, 2, 3” –colour=”255, 0, 0” It will create a 3D text object with text “Hi” at the point [1, 2, 3] and with red text.

>>> from mapteksdk.project import Project
>>> from mapteksdk.workflows import WorkflowArgumentParser
>>> from mapteksdk.data import Text3D
>>> parser = WorkflowArgumentParser("Create 3D text.")
>>> parser.declare_input_connector("text", str, default="Hello World",
...                                description="The text of the new 3D text")
>>> parser.declare_input_connector("position", list, default=[0, 0, 0],
...                                description="[x, y, z] position of text.")
>>> parser.declare_input_connector("colour", list, default=[0, 255, 0],
...                                description="[R, G, B] colour for text.")
>>> parser.parse_arguments()
>>> project = Project()
>>> with project.new(f"{parser['text']}", Text3D) as new_text:
...     new_text.text = parser["text"]
...     new_text.location = parser["position"]
...     new_text.colour = parser["colour"]

Reversing strings

This script takes the string representation of the input and reverses it. For example, the string “Eggs” would be reversed to “sggE” and the number “42.42424” would be reversed to “42424.24”. Note that reversing some types, such as datetime.datetime will not give a valid object of that type.

>>> from mapteksdk.workflows import WorkflowArgumentParser
>>> parser = WorkflowArgumentParser("Reverses the input strings")
>>> parser.declare_input_connector("string", str,
...                                description="String to reverse.",
...                                default="Something to reverse")
>>> parser.declare_output_connector("reversed", str,
...                                 description="The reversed string.")
>>> parser.parse_arguments()
>>> parser.set_output("reversed", parser["string"][::-1])
>>> parser.flush_output() # Calling this is optional.
declare_input_connector(name, input_type, default=None, connector_name=None, description='')

Declares that this script expects an input connector with the specified name to provide a value of the specified type.

This has no effect if parse_arguments is not called.

Parameters
  • name (str) – The name of the input connector. This cannot include any whitespace. Pass this to get_input() after calling parse_arguments() to get any values passed through this input connector.

  • input_type (callable) – The data type the input connector will accept. See table above for how to match types between Workflows and Python.

  • default (any) – The default value to use for this connector if no value is provided when parse_arguments is called (eg: If the connector was deleted from the workflow node). For non-bool connectors this is None by default. For bool connectors this is ignored - the default is always False.

  • connector_name (str) – The user facing name of the connector. If specified, this will be the “Connector Name” and name will be the “Attribute name” of the connector. Unlike name, this can include whitespace characters.

  • description (str) – Description of the input connector. Use this to provide instructions on how to use this input connector. If the input connectors are automatically generated this will be placed in the “Description” field of the input connector. If –help is passed to the script, this will be displayed as part of the help. The description is optional, however it is strongly suggested to provide one.

Raises
  • ValueError – If output_type is not callable.

  • InvalidConnectorNameError – If name contains whitespace.

  • InvalidConnectorNameError – If declaring a connector using a name reserved for use by the SDK.

  • ValueError – If default is not the same type as input_type.

  • RuntimeError – If called after parse_args() has been called.

  • argparse.ArgumentError – If two arguments are declared with the same name and different types.

Notes

Using from workflows

After you have written the script, select it in the Workflow Component and click “Generate Connectors”. The connectors declared by this function (and declare_output_connectors) will be added to the workflow component.

Using via the command line

A script using this class is not restricted to being run in workflows - it can also be run via the command line or a code editor. Inputs can be passed into input connectors as command line arguments. The general form of one of these command line arguments is:

>>> --name=value

Or if the name is only a single character long:

>>> -n=value

The main exception is for bool connectors. For them omit the equals sign and value - the presence of the argument name indicates True and its absence indicates False.

Examples

Command line examples Given a script called “script.py” which uses this module to parse its arguments and python interpreter set to be run via the “py” command, the following examples show how to pass an argument to the script.

Connector with name=”name” of type str. The quotation marks around the string are necessary to include the spaces as part of the string instead of as separate arguments.

>>> py script.py --name="Tim the enchanter"

Connector with name=”n” of type str. For connectors with single letter names the name is prefixed with one dash instead of two.

>>> py script.py -n="King Arthur"

Connector with name=”pre-sorted” of type bool

>>> py script.py --pre-sorted # Gives pre-sorted=True
>>> py script.py              # Gives pre-sorted=False

Connector with name=”count” of type int

>>> py script.py --count=42

Connector with name=”tolerance” of type float.

>>> py script.py --tolerance=3.14159

Connector with name=”time” of type datetime.datetime. Note that the date must be entered in ISO-8601 compliant format.

>>> py script.py --time="2020-07-10T12:54:07"

Connector with name=”overwrite” of type bool. Note that for bool connectors no value is passed.

>>> py script.py --overwrite # Sets overwrite to true
>>> py script.py # No overwrite parameter sets overwrite to false.

Connector with name=”origin” of type list.

>>> py script.py origin="1, 1, 1"
declare_output_connector(name, output_type, connector_name=None, description=None)

Declares that this script will provide a value for an output connector with the specified name and the specified type.

You should call set_output once for each connector declared with this function.

Parameters
  • name (str) – The name of the output connector.

  • output_type (callable) – The python type the output will be converted to. See the table in declare_input_connector to choose the correct Python type to match the workflows type.

  • connector_name (str) – The user facing name of the connector. If specified, this will be the “Connector Name” and name will be the “Attribute name” of the connector. Unlike name, this can include whitespace characters.

  • description (str) – Description of the output connector. If the connectors are automatically generated, this will be placed in the Description field of the connector. If None (default) the description will be the empty string.

Raises
  • ValueError – If output_type is not callable.

  • InvalidConnectorNameError – If the connector name is invalid.

  • RuntimeError – If called after parse_args() has been called.

parse_arguments(arguments=None)

Indicates that the script has finished configuring the connectors and allows values to be read from the input connectors. This will also allow values to be written to the output connectors.

If there is an error parsing the arguments, a SystemExit will be executed. This is useful for ensuring your script will not run if the inputs are invalid.

Parameters

arguments (list of str) – List of arguments to parse. If None (default) then the arguments are parsed from sys.argv[:1]. Generally you should leave this as None.

Raises
  • SystemExit – If the value passed to a connector is not compatible with the type specified when declare_argument was called for that connector.

  • SystemExit – If an unknown argument appears.

Warning

When you click the “Generate Connectors” button in the workflow component, the Python Script will be executed until this function is called (And thus to completion if this is never called). You should make sure that no code which has side effects is called before calling this function.

You should always call this function before calling Project().

Printing to standard output before calling this function will cause the workflow component to fail to generate connectors.

Notes

Usually this function will be called as: workflows.parse_arguments()

get_input(name)

Returns the value passed to the connector with the specified name.

For convenience, this function can also be called via subscripting this object (ie: parser[name])

Parameters

name (str) – The name of the argument to retrieve the value for.

Returns

Value for argument name.

Return type

type

Raises

KeyError – If there is no argument with name (Potentially because parse_arguments has not been called).

set_output(name, value)

Sets the value to be written to an output connector. Note that the value is not written to the output connector until flush_output() is called or the script successfully exits.

Parameters
  • name (str) – Name of the output. This should match the name of the output connector.

  • value (type) – Value to provide for the output. This should be a simple type, such as a int, float, str, list or datetime.

Raises
  • KeyError – If declare_output_connector was not called for name.

  • ValueError – If value cannot be converted to the type passed in to declare_output_connector for name.

  • RuntimeError – If you attempt to call this twice for the same connector.

  • RuntimeError – If called after calling flush_outputs.

flush_output()

Flushes the output making it available to the output connectors. Call this function once you have called set_output() for each output connector.

After this function has been called, you cannot write any more values to the output connectors.

Raises

RuntimeError – If this function is called more than once.

describe_connectors(destination)

Describes the input and output connectors. This is used by the Extend Python Workflow Component to generate the connectors — it is not recommended to use this function in scripts.

This results in an Object with three fields: Description : The description of the Python script. Input : Description of the input connectors. Output : Description of the output connectors.

Parameters

destination (str) – Path to output file to write the description to. If False the description is printed to standard out.

class mapteksdk.workflows.WorkflowSelection(selection_string)

Bases: object

Class representing a read-only list of ObjectIDs. Pass this to declare_input_connector for input connectors expecting a selection - the lists of objects given by the ‘selection’ connectors of many components.

Iterating over this object will iterate over the ObjectIDs in the selection.

You should not access the contents of this object until after Project() has been called.

Parameters

selection_string (str) – String representing the selection.

Raises
  • OSError – If the contents are accessed before Project() has been called.

  • ValueError – If part of the selection cannot be converted to an ObjectID.

Warning

Ensure the ObjectIDs passed to this class are from the same project as is opened with Project() otherwise the ObjectIDs may refer to a completely different object.

Notes

This class does not support object paths which contain quotation marks or commas.

Examples

Script which takes a selection of objects and returns their centroid via a list output connector. This script would have one input connector “Selection” which accepts a selection. There is also one output connector “Centroid” which will return the centroid of all of the points in the objects in the selection. Note that this script does not honour point selection.

>>> from mapteksdk.project import Project
>>> from mapteksdk.workflows import WorkflowArgumentParser, WorkflowSelection
>>> import numpy as np
>>> parser = WorkflowArgumentParser(
...     description="Get the centroid of objects with points")
>>> parser.declare_input_connector(
...     "selection",
...     WorkflowSelection,
...     description="Objects to find the centroid of.")
>>> parser.declare_output_connector(
...     "Centroid",
...     list,
...     description="The centroid of the points in the objects.")
>>> parser.parse_arguments() # Must call before Project().
>>> project = Project() # Must call before get_ids().
>>> sums = np.array([0, 0, 0], dtype=np.float64)
>>> count = 0
>>> for oid in parser["selection"]:
...     with project.read(oid) as read_object:
...         if not hasattr(read_object, "points"): continue
...         sums += np.sum(read_object.points, axis=0)
...         count += read_object.point_count
>>> result = sums / count
>>> parser.set_output("Centroid", result)
>>> parser.flush_output()
property ids

Return the IDs in the selection as a list. This must be called after Project() has been called. Object IDs only have meaning within a Project.

Returns

ObjectIDs in the selection.

Return type

list of ObjectID

Raises
  • ValueError – If any string cannot be converted to an ObjectID.

  • OSError – If called before Project() is called.