mapteksdk.project package

Core functionality for connecting to a Maptek MDF-based application.

This handles connecting to the application and initialises internal dependencies. The Project class provides methods for interacting with user facing objects and data within the application.

ObjectT

Type hint used for arguments which are subclasses of DataObject.

alias of TypeVar(‘ObjectT’, bound=DataObject)

ObjectIdT

Type hint used for ObjectID of any DataObject subclass.

Note that ObjectT and ObjectIdT may not refer to the same type for certain functions.

alias of TypeVar(‘ObjectIdT’, bound=DataObject)

class Project(options=None, existing_mcpd=None)

Bases: object

Main class to connect to an instance of an MDF application. Project() establishes the communication protocol and provides base functionality into the application, such as object naming, locating, copying and deleting.

Parameters
  • options (ProjectOptions) – Optional specification of project and connection settings. Used for unit testing to start a new database and processes without an MDF host application already running.

  • existing_mcpd (ExistingMcpdInstance | McpdConnection | None) –

    If None (default) then the latest relevant application that was launched will be connected to. This is equivalent to passing in Project.find_running_applications()[0].

    Otherwise it may be ExistingMcpdInstance which refers to the host application to connect to otherwise a McpdConnection which is an existing connection to a host application (its mcpd).

Raises

ProjectConnectionFailureError – If the script fails to connect to the project. Generally this is because there is no application running, or the specified application is no longer running.

unload_project()

Call the mcp class to unload a spawned mcp instance (i.e. when not using a host application like Eureka or PointStudio). Use this when finished operating on a project that has ProjectOptions that requested an mcpd_mode of CREATE_NEW.

Also unloads dataengine created with same methods.

Failure to call this un-loader may leave orphan mcpd.exe processes running on the machine.

Return type

None

property api_version: tuple[int, int]

Returns the API version reported by the application.

Returns

The API version of the application in the form: (major, minor).

Return type

tuple

Notes

The following table summarises the API version for officially supported applications:

Application

api_version

Eureka 2020

(1, 1)

PointStudio 2020

(1, 1)

PointStudio 2021

(1, 2)

PointStudio 2021.1

(1, 3)

PointStudio 2022

(1, 3)

PointStudio 2022.0.1

(1, 3)

PointStudio 2022.1

(1, 3)

Vulcan GeologyCore 2021

(1, 4)

Vulcan GeologyCore 2021.1

(1, 4)

Vulcan GeologyCore 2022

(1, 5)

Vulcan GeologyCore 2022.1

(1, 7)

Earlier applications will have an API version of (0, 0). It is not recommended to connect to applications with API versions less than (1, 1).

raise_if_version_below(version)

Raises an error if the script has connected to an application whose version is lower than the specified version.

This allows for scripts to exit early when attaching to an application which does not support the required data types.

Parameters

version (tuple[int, int]) – A tuple (major, minor). If the API version is less than this tuple an error will be raised.

Raises

ApplicationTooOldError – If the API version is lower than the specified version.

Return type

None

Examples

Exit if the application does not support GridSurface (api_version is less than (1, 2)).

>>> from mapteksdk.project import Project
>>> project = Project()
>>> project.raise_if_version_below((1, 2))

It is also possible to catch this error and add extra information.

>>> from mapteksdk.project import Project, ApplicationTooOldError
>>> project = Project()
>>> try:
...     project.raise_if_version_below((1, 2))
>>> except ApplicationTooOldError as error:
...     raise SystemExit("The attached application does not support "
...                      "irregular grids") from error
find_object(path)

Find the ObjectID of the object at the given path.

Parameters

path (str) – Path to the object.

Returns

  • ObjectID – The ID of the object at the given path.

  • None – If there was no object at path.

Return type

Optional[ObjectID[DataObject]]

read(path_or_id: str) Generator[DataObject, None, None]
read(path_or_id: ObjectID[ObjectIdT]) Generator[ObjectIdT, None, None]
read(path_or_id: str, expected_object_type: type[ObjectT]) Generator[ObjectT, None, None]
read(path_or_id: ObjectID[ObjectIdT], expected_object_type: type[ObjectT]) Generator[ObjectT, None, None]

Open an existing object in read-only mode.

In read-only mode the values in the object can be read, but no changes can be saved. Use this function instead of edit() if you do not intend to make any changes to the object.

If this is called using a with statement, close() is called automatically at the end of the with block.

Parameters
  • path_or_id – The path or the ID of the object to open.

  • expected_object_type – The expected type for the object. If None (default), then the type will be determined automatically. If set to a DataObject subclass, the object will be opened as that subclass. If the object is not of this type, a TypeMismatchError will be raised.

Raises
  • ObjectDoesNotExistError – If path_or_id is not an existent object.

  • TypeMismatchError – If expected_object_type is specified and path_or_id refers to an object which cannot be opened as that type.

  • TypeError – If path_or_id is an unsupported object.

Examples

Read an object at path/to/object/to/read and then print out the point, edge and facet counts of the object.

>>> from mapteksdk.project import Project
>>> project = Project()
>>> path = "path/to/object/to/read"
>>> with project.read(path) as read_object:
...     if hasattr(read_object, "point_count"):
...         print(f"{path} contains {read_object.point_count} points")
...     if hasattr(read_object, "edge_count"):
...         print(f"{path} contains {read_object.edge_count} edges")
...     if hasattr(read_object, "facet_count"):
...         print(f"{path} contains {read_object.facet_count} facets")
...     if hasattr(read_object, "cell_count"):
...         print(f"{path} contains {read_object.cell_count} blocks")
...     if hasattr(read_object, "block_count"):
...         print(f"{path} contains {read_object.block_count} blocks")

The optional expected_object_type parameter can be used to ensure that the read object is of a specified type. This will cause Project.read() to raise an error if the object is not of the specified type, however it also guarantees that within the with block the read object will be of the specified type. This is demonstrated by the following example:

>>> from mapteksdk.project import Project
>>> from mapteksdk.data import Surface
>>> path = "path/to/object/to/read"
>>> with Project() as project:
...     # Because the second argument was set to Surface, this will raise
...     # an error if the object is not a Surface.
...     with project.read(path, Surface) as surface:
...         # The surface variable is guaranteed to be a surface here,
...         # so it is not necessary to check if the object has these
...         # properties.
...         print(f"{path} contains {surface.point_count} points")
...         print(f"{path} contains {surface.edge_count} edges")
...         print(f"{path} contains {surface.facet_count} facets")
new(object_path, object_class, overwrite=False)

Create a new object and add it to the project. Note that changes made to the created object will not appear in the view until save() or close() is called.

If this is called using a with statement, save() and close() are called automatically at the end of the with block.

Parameters
  • object_path (str) – Full path for new object. e.g. “surfaces/generated/new surface 1” If None, the new object will not be assigned a path and will only be available through its object ID.

  • object_class (Union[type[~ObjectT], ObjectT]) – The type of the object to create. (e.g. Surface).

  • overwrite (bool) – If overwrite=False (default) a ValueError is raised if there is already an object at new_name. If overwrite=True then any object at object_path is replaced by the new object. The overwritten object is orphaned rather than deleted and may still be accessible through its id.

Yields

DataObject – The newly created object. The type of this will be object_class.

Raises
  • ValueError – If an object already exists at new_path and overwrite = False.

  • ValueError – If object path is blank, ‘.’ or ‘/’.

  • TypeError – If creating an object of the given type is not supported.

  • NotImplementedError – If creating an object of the given type is not implemented but may be implemented in a future version of the SDK.

  • InvalidParentError – If object_path contains an object that can’t be a parent of the new object.

Return type

Generator[ObjectT, None, None]

Notes

If an exception is raised while creating the object the object will not be saved.

If you do not assign a path to an object on creation, project.add_object() can be used to assign a path to the object after creation.

Examples

Create a new surface and set it to be a square with side length of two and centred at the origin.

>>> from mapteksdk.project import Project
>>> from mapteksdk.data import Surface
>>> project = Project()
>>> points = [[-1, -1, 0], [1, -1, 0], [-1, 1, 0], [1, 1, 0]]
>>> facets = [[0, 1, 2], [1, 2, 3]]
>>> with project.new("surfaces/square", Surface) as new_surface:
...   new_surface.points = points
...   new_surface.facets = facets
...   # new_surface.close is called implicitly here.
edit(path_or_id: str) Generator[DataObject, None, None]
edit(path_or_id: ObjectID[ObjectIdT]) Generator[ObjectIdT, None, None]
edit(path_or_id: str, expected_object_type: type[ObjectT]) Generator[ObjectT, None, None]
edit(path_or_id: ObjectID[ObjectIdT], expected_object_type: type[ObjectT]) Generator[ObjectT, None, None]

Open an existing object in read/write mode.

Unlike read, this allows changes to be made to the object. Note that changes made will not appear in the view until save() or close() is called.

If this is called using a with statement, save() and close() are called automatically at the end of the with block.

Parameters
  • path_or_id – Path or ID of the object to edit.

  • expected_object_type – The expected type for the object. If None (default), then the type will be determined automatically. If set to a DataObject subclass, the object will be opened as that subclass. If the object is not of this type, a TypeMismatchError will be raised.

Yields

DataObject – The object at the specified path opened for editing.

Raises
  • ObjectDoesNotExistError – If the object to edit does not exist.

  • TypeMismatchError – If expected_object_type is specified and path_or_id refers to an object which cannot be opened as that type.

  • TypeError – If the object type is not supported.

Notes

If an exception is raised while editing an object, any changes made inside the with block are not saved.

Examples

Edit the surface created in the example for project.new to a hourglass shape instead of a square.

>>> from mapteksdk.project import Project
>>> points = [[-1, -1, 0], [1, -1, 0], [-1, 1, 0], [1, 1, 0], [0, 0, 0]]
>>> facets = [[0, 1, 4], [2, 3, 4]]
>>> project = Project()
>>> with project.edit("surfaces/square") as edit_surface:
...     edit_surface.points = points
...     edit_surface.facets = facets
...     # edit_surface.close is called implicitly here.

One problem with the above example is that if the object at “surfaces/square” is not a Surface it will fail. e.g. If “surfaces/square” is a Polyline, Polygon or EdgeNetwork:

  • The assignment to “points” would succeed because these objects have points, just like a surface.

  • The assignment to “facets” would fail silently because Python allows the assignment even though the object does not have facets.

  • The script would exit with a success even though it actually failed to set the facets.

This can be avoided by specifying the expected type of the object when opening it. This ensures that if the object is of an unexpected type, the script will fail before any changes have been made to the object. By failing quickly, the chances of unintentional changes are minimised. A fixed version of the above example is shown below:

>>> from mapteksdk.project import Project
>>> from mapteksdk.data import Surface
>>> points = [[-1, -1, 0], [1, -1, 0], [-1, 1, 0], [1, 1, 0], [0, 0, 0]]
>>> facets = [[0, 1, 4], [2, 3, 4]]
>>> project = Project()
>>> # The second argument of Surface means this will fail immediately
>>> # with an exception if the object at "surfaces/square" is not
>>> # a surface.
>>> with project.edit("surfaces/square", Surface) as edit_surface:
...     edit_surface.points = points
...     edit_surface.facets = facets
new_or_edit(path, object_class, overwrite=False)

This function works as project.new if the specified object does not exist. Otherwise it acts as project.edit.

Parameters
  • path (str) – Path to the object to create or edit.

  • object_class (Union[ObjectT, type[~ObjectT]]) – Class of the object to create or edit.

  • overwrite (bool) – If False (default) and there is already an object at path whose type is not editable as object_class a ValueError is raised. If True, any object at path which is not object_class is orphaned to make room for the new object.

Yields

DataObject – The newly created object or the object at the specified path.

Raises
  • ValueError – If overwrite=False and there exists an object at path whose type is not object class.

  • AttributeError – If path is not a string.

  • InvalidParentError – If object_path contains an object that can’t be a parent of the new object.

Return type

Generator[ObjectT, None, None]

add_object(full_path: str, new_object: ObjectID[ObjectIdT], overwrite: bool = False) ObjectID[ObjectIdT]
add_object(full_path: str, new_object: ObjectT, overwrite: bool = False) ObjectID[ObjectT]

Adds a new DataObject to the project. Normally this is not necessary because Project.new() will add the object for you. This should only need to be called if Project.new() was called with path = None or after a call to a function from the mapteksdk.io module.

Parameters
  • full_path – Full path to the new object (e.g. ‘/surfaces/new obj’).

  • new_object (DataObject or ObjectID) – Instance or ObjectID of the object to store at full_path.

  • overwrite – If overwrite=False (default) a ValueError will be raised if there is already an object at full_path. If overwrite=True and there is an object at full_path it will be overwritten and full_path will now point to the new object. The overwritten object becomes an orphan.

Returns

ID of newly stored object. This will be the object ID of new_object.

Return type

ObjectID

Raises
  • ValueError – If invalid object name (E.g. ‘/’, ‘’, or (starting with) ‘.’ when project options don’t allow hidden objects).

  • ValueError – If path contains back slashes ().

  • ValueError – If overwrite=False and there is already an object at full_path.

  • TypeError – If full_path is not a string.

  • TypeError – If new_object is not a DataObject or ObjectID

  • InvalidParentError – If new_object is being added to an object that is not a container. Topology objects are not considered containers when the project options don’t allow hidden objects. The fact that they’re containers is a implementation detail and they’re not portrayed as containers to end users in the applications.

Notes

Has no effect if new_object is already at full_path.

add_objects(destination_container, new_objects, overwrite=False)

Adds multiple objects into the project.

This can be used to batch the insertions. Most likely you will want to use this with an object that hasn’t been added to the project before. You can avoid adding new objects to the project when calling Project.new() by providing a path of None.

This is treated as an atomic operation so either all objects are added or none are added. This means if there is a problem with adding one of the objects then none of the objects will be added and the destination container will remain unchanged.

Parameters
  • destination_container (str) – Full path to the container where the objects will be added.

  • new_objects (list[tuple[str, mapteksdk.data.objectid.ObjectID[mapteksdk.data.base.DataObject]]] | dict[str, mapteksdk.data.objectid.ObjectID[mapteksdk.data.base.DataObject]]) – If new_objects is a dictionary then the keys are names and the values are the objects to add. If new_objects is a list then the list should contain (name, object) pairs. The objects can be either DataObject or ObjectID.

  • overwrite (bool) – If overwrite=False (default) a ValueError will be raised if there is already an object in the destination container with that name that isn’t the object itself. If overwrite=True and there is an object in the destination container then it will be overwritten. The overwritten object becomes an orphan.

Returns

A list of object IDs of newly added objects. This will be in the same order as add_objects(). If an object was already in the container under that name it will still be returned even when it wasn’t added.

Return type

list

Raises
  • ValueError – If invalid object name (E.g. ‘/’, ‘’, or (starting with) ‘.’ when project options don’t allow hidden objects).

  • ValueError – If paths contains back slashes ().

  • ValueError – If overwrite=False and there is already an object in the destination container with that name and it is not the object being added.

  • InvalidParentError – If destination_container or an object in the path is not a container. Topology objects are not considered containers when the project options don’t allow hidden objects. The fact that they’re containers is a implementation detail and they’re not portrayed as containers to end users in the applications.

Warning

For older versions of the application, if an error occurs any objects added prior to the object which triggered the error will still be added.

Notes

If any object in new_objects is already in the destination container with the specified name, it will be left unchanged.

get_children(path_or_id='')

Return the children of the container at path as (name, id) pairs.

Parameters

path_or_id (Union[str, ObjectID[DataObject]]) – The path or object ID of the container to work with.

Returns

Provides a sequence that can be iterated over to provide the (name, id) for each child. It also provides name() and ids() functions for querying just the names and object IDs respectively.

Return type

ChildView

Raises
  • ObjectDoesNotExistError – If the path does not exist in the project.

  • TypeError – If the path is not a container.

  • ValueError – If the path is a container but not suitable for accessing its children.

get_descendants(path_or_id='')

Return all descendants of the container at path as (name, id) pairs.

Parameters

path_or_id (Union[str, ObjectID[Container]]) – The path or object ID of the container to work with.

Returns

Provides a sequence that can be iterated over to provide the (name, id) for each child. It also provides name() and ids() functions for querying just the names and object IDs respectively.

Return type

ChildView

Raises
  • KeyError – If the path does not exist in the project.

  • TypeError – If the path is not a container.

  • ValueError – If the path is a container but not suitable for accessing its children.

copy_object(object_to_clone: ObjectID[ObjectIdT], new_path: str, overwrite: bool = False, allow_standard_containers: bool = False) ObjectID[ObjectIdT]
copy_object(object_to_clone: str, new_path: str, overwrite: bool = False, allow_standard_containers: bool = False) ObjectID[DataObject]
copy_object(object_to_clone: ObjectT, new_path: str, overwrite: bool = False, allow_standard_containers: bool = False) ObjectID[ObjectT]

Deep clone DataObject to a new object (and ObjectID).

If this is called on a container, it will also copy all of the container’s contents.

Parameters
  • object_to_clone – The object to clone or the ID for the object to clone or a str representing the path to the object.

  • new_path – full path to place the copy (e.g. ‘surfaces/new/my copy’). Set as None for just a backend object copy.

  • overwrite – If False (default) a ValueError will be raised if there is already an object at new_name. If True and there is an object at new_path the object at new_path is overwritten. The overwritten object is orphaned instead of deleted and may still be accessible via its id.

  • allow_standard_containers – If False (default) then attempting to copy a standard container will create a visual container instead. If True (not recommended) copying a standard container will create a new standard container.

Returns

  • ObjectID – Id of new object (The clone).

  • None – If the operation failed.

Raises
  • ObjectDoesNotExistError – If object_to_clone does not exist.

  • ValueError – If an object already exists at new_path and overwrite = False.

  • RuntimeError – If object_to_clone is a DataObject subclass and it is open with Project.edit().

rename_object(object_to_rename, new_name, overwrite=False, allow_standard_containers=False)

Rename (and/or move) an object.

Renaming an object to its own name has no effect.

Parameters
  • object_to_rename (Union[DataObject, ObjectID[DataObject], str]) – The object to rename or the ID of the object to rename or full path to object in the Project.

  • new_name (str) – new name for object. Standalone name (e.g. ‘new tri’) will keep root path. Full path (e.g. ‘surfaces/new tri’) will change location. Prefix with ‘/’ (e.g. ‘/new tri’ to move to the root container).

  • overwrite (bool) – If False (default) then if there is already an object at new_name then a ValueError is raised. If True and if there is already an object at new_name then the object at new_name is overwritten. The overwritten object is orphaned rather than deleted and may still be accessible via its ID.

  • allow_standard_containers (bool) – If False (default) then attempting to rename a standard container will create a new container and move everything in the standard container into the new container. If True (not recommended) standard containers can be renamed.

Returns

True if rename/move successful, False if failed (overwrite checks failed).

Return type

bool

Raises
  • ValueError – New object name begins with full stop when project attribute allow_hidden_objects is False (default).

  • ValueError – New object name can’t be ‘.’.

  • ValueError – If there is already an object at new_name and overwrite=False.

  • ObjectDoesNotExistError – Attempting to rename an object that doesn’t exist.

  • DeleteRootError – Attempting to rename root container.

Notes

new_name can not start with a full stop ‘.’ when allow_hidden_objects is False and cannot be ‘/’ or ‘’ or ‘.’.

delete_container_contents(container)

Deletes all the contents of a container.

Any child objects that are not in another container will be deleted.

Parameters

container (Union[DataObject, ObjectID[DataObject], str]) – the object to delete or the ID for the object to delete or path to container (e.g. ‘/surfaces/old’).

Raises

ObjectDoesNotExistError – If container is not an existent object.

new_visual_container(parent_container, container_name)

Creates a new visual container.

Parameters
  • parent_container (str) – The path to the parent container or the parent container.

  • container_name (str) – New container name.

Returns

The object ID for newly created container.

Return type

ObjectID

Raises
  • ValueError – When attempting to create a container name or part of path that would result in hidden objects (i.e. starts with ‘.’) and allow_hidden_objects is False.

  • ValueError – If the container name contains “/” characters.

  • ValueError – If there is already an object called container_name in parent_container.

  • InvalidParentError – If object_path contains an object that can’t be a parent of the new object.

Examples

To add a visual container to the root container, use “/” as the parent container name. The following example creates a container called “example_container” in the root container.

>>> from mapteksdk.project import Project
>>> project = Project()
>>> project.new_visual_container("/", "example_container")

To add a visual container to another container, use the path to that container as the container name. The following example creates a container called “sub_container” in the “example_container” created in the previous example.

>>> from mapteksdk.project import Project
>>> project = Project()
>>> project.new_visual_container("example_container", "sub_container")

This is the full path to that container if that container is in another container. The following example creates a container called “sub_sub_container” inside the “sub_container” created in the previous example. In particular, note that the path to “sub_container” includes a “/” because it is inside of another container.

>>> from mapteksdk.project import Project
>>> project = Project()
>>> project.new_visual_container(
...     "example_container/sub_container",
...     "sub_sub_container"
... )
delete(mdf_object_or_name, allow_standard_containers=False)

Deletes the given object.

Parameters
  • mdf_object_or_name (Union[str, DataObject, ObjectID[DataObject]]) – Container name, instance of object as DataObject or ObjectID of the object.

  • allow_standard_containers (bool) – If False (default) then attempting to delete a standard container will result in the container contents being deleted. If True then standard containers will be deleted. See warnings for why you shouldn’t do this.

Returns

True if deleted successfully or False if not.

Return type

bool

Raises
  • DeleteRootError – If the object provided is the root container.

  • RuntimeError – If the the object can’t be deleted. The most common cause is something is writing to the object at this time.

Warning

Deleting a standard container created by a Maptek application may cause the application to crash. The allow_standard_containers flag should only be used to delete standard containers you have created yourself (It is not recommended to create your own standard containers).

get_selected()

Return the IDs of the selected objects.

When connected to an existing application, these are the objects selected in that application (via the explorer, view or some other method).

Returns

A list of selected ObjectIDs.

Return type

Selection

set_selected(object_ids_or_paths=None, include_descendants=True)

Set active project selection to one or more objects. If None specified, selection will be cleared. If objects are provided but are not valid, they will not be selected. No action will be taken if entire selection specified is invalid. Any VisualContainer objects specified will include their descendants.

Parameters
  • mdf_objects_or_paths – List of object paths to select, List of ObjectID to select, path to object to select, ObjectID of object to select. Pass None or an empty list to clear the existing selection.

  • include_descendants (bool) – whether to also select descendants of any VisualContainer provided within the selection criteria (default=True).

  • object_ids_or_paths (Optional[Union[Selection, list[str], list[mapteksdk.data.objectid.ObjectID[mapteksdk.data.base.DataObject]], str, ObjectID[DataObject]]]) –

Raises

ValueError – If any or all objects within the selection specified is invalid.

Return type

None

property recycle_bin_id: ObjectID

The object ID of the recycle bin.

Returns

The ID of the recycle bin object.

Return type

ObjectID

Raises

NoRecycleBinError – The project has no recycle bin.

See also

recycle

Move an object to the recycle bin.

recycle(object_to_recycle)

Move the given object to the recycle bin.

This does not provide the ability to recycle a standard container because the user will be unable to move the item out of the recycle bin.

Raises

NoRecycleBinError – The project has no recycle bin.

Parameters

object_to_recycle (Union[DataObject, ObjectID[DataObject]]) –

is_recycled(mdf_object)

Check if an object is in the recycle bin.

Parameters

mdf_object (Union[DataObject, ObjectID[DataObject]]) – Object to check.

Returns

True if the object is in the recycle bin (deleted) and False if it is not.

Return type

bool

type_name(path_or_id)

Return the type name of an object.

This name is for diagnostics purposes only. Do not use it to alter the behaviour of your code. If you wish to check if an object is of a given type, use ObjectID.is_a() instead.

Parameters

path_or_id (Union[str, ObjectID[DataObject]]) – The path or the ID of the object to query its type’s name.

Returns

The name of the type of the given object.

Return type

str

See also

mapteksdk.data.objectid.ObjectID.is_a

Check if the type of an object is the expected type.

static find_running_applications()

Return a list of applications that are candidates to be connected to.

No checking is performed on the application to determine if it is suitable to connect to. For example, if the product is too old to support the SDK.

Once you select which application is suitable then pass the result as the existing_mcpd parameter of the Project class’s constructor.

The list is ordered based on the creation time of the mcpd process with the latest time appearing first in the list.

Returns

The list of candidate applications (host) that are running.

Return type

list of ExistingMcpdInstance

Examples

Finds the running applications and chooses the oldest one.

>>> from mapteksdk.project import Project
>>> applications = Project.find_running_applications()
>>> project = Project(existing_mcpd=applications[-1])

Submodules