Examples
The examples provided below assume you have imported sample data. Before getting started, please import the sample data Maptek_PythonSDK_SampleData_20200101.maptekobj using either of the following methods:
- Use File > Import (or Home > Import) in PointStudio or GeologyCore.
- Use the SDK in the first example below (Importing a Maptek object file).
All examples provided on this page have been demonstrated using Maptek PointStudio 2020 or above.
Importing a Maptek object file
This example will show how to import the provided sample dataset Maptek_PythonSDK_SampleData_20200101.maptekobj into your current project. The following snippet has been written to mimic the same result that would occur if importing this data using Home > Import within the software.
from mapteksdk.project import Project import mapteksdk.data.io as io project = Project() # Connect to default project # Use the path you have saved Maptek_PythonSDK_SampleData_20200101.maptekobj path_to_maptekobj = "F:/Python SDK Help/Maptek_PythonSDK_SampleData_20200101.maptekobj" # This will import the maptekobj file which may contain an arbitrary # number of objects within. These will not automatically be assigned # a project path. object_id = io.import_maptekobj(path_to_maptekobj) # Assign all of the imported data to a path for id in project.get_children(object_id).ids(): # Move each child found in the imported data into the scrapbook container # Project().rename_object can be used for moving objects project.rename_object( id, # The ObjectID representing the current object "scrapbook/{}".format(id.name), # New path to assign overwrite=True # Replace any existing data at this path )
Check the contents of the project have been imported:
Checking existence of an object
The following snippet shows how to check if an object exists and if it does, a valid is returned for it.
from mapteksdk.project import Project project = Project() # Connect to default project # The Project().find_object() function will return an # ObjectID if an object exists. If it doesn't, None # will be returned. if project.find_object("/scrapbook/surfaces/Pit model"): print("it exists!") # Expected output: # >>> it exists!
Checking existence of a container
A container in a Maptek project is like a folder on your file system. It can contain sub-containers and objects. The following snippet will verify data from the example above has been imported into /scrapbook/scans and /scrapbook/surfaces.
from mapteksdk.project import Project from mapteksdk.data import VisualContainer project = Project() # Connect to default project scans_container = project.find_object("/scrapbook/scans") # Verify it is a VisualContainer using the ObjectID.is_a() function if scans_container and scans_container.is_a(VisualContainer): print("/scrapbook/scans is a VisualContainer!") surfaces_container = project.find_object("/scrapbook/surfaces") # Verify it is a VisualContainer using the ObjectID.is_a() function if surfaces_container and surfaces_container.is_a(VisualContainer): print("/scrapbook/surfaces is a VisualContainer!")
Listing contents of a container
As a container may contain an arbitrary number of objects, it is useful to be able to list its content. The following snippet will list the names of the objects immediately below /scrapbook/scans/set1.
from mapteksdk.project import Project project = Project() # Connect to default project for name in project.get_children("scrapbook/scans/set1/").names(): print("name: {}".format(name)) # Expected output: # >>> name: points1of4 # >>> name: points2of4 # >>> name: points3of4 # >>> name: points4of4
Listing all objects in all containers
The above snippet demonstrated the Project.get_children() function, which queries the direct children within a container. Another function available that will seek our all children within all containers from a given starting point is Project.get_descendants(). When a path is requested, the use of "" indicates the root of the project. In this example, "scrapbook" will be used to get all of the objects imported earlier.
from mapteksdk.project import Project project = Project() # Connect to default project for child_name, child in project.get_descendants("scrapbook"): print("name: {}, path: {}, type: {}".format( child_name, child.path, # ObjectID.path property. child.type_name # The name of type of object. )) # Project().get_children() and Project().get_descendants() return # a ChildView (mapteksdk.data.ChildView) type. # This can be used like: # for name, id in proj.get_descendants("path" or ObjectID) # (name is a string, id is an ObjectID) # or # for id in proj.get_descendants().ids() # (results as list of ObjectID) # or # for name in proj.get_descendants().names() # (results as list of string)
Listing only containers (or object of type)
The example above will list all contents. However you might want to get a list of PointSet objects that exist under that path, or VisualContainer objects within the project. This can be done by applying a type check in the following snippet.
from mapteksdk.project import Project, Selection from mapteksdk.data import VisualContainer, PointSet, ObjectID with Project() as project: print("List of all VisualContainer objects in project with count of children") selection = Selection(project.get_descendants().ids()).where([VisualContainer]) for container in selection: container: ObjectID[Selection] child_count = len(project.get_children(container)) print( f"Path: {container.path}, count of children: {child_count}" ) print("\nList of all PointSet objects in project") point_set_selection = Selection(project.get_descendants().ids()).where([PointSet]) for point_set_id in point_set_selection: point_set_id: ObjectID[PointSet] print(f"Path: {point_set_id.path}")
Listing contents of a selection
The Maptek Python SDK can be used to query the objects currently selected by the user. This can be useful if requiring the user to select an object of a specific type to do an operation against.
from mapteksdk.project import Project project = Project() # Connect to default project # Ensure user has made a selection selection = project.get_selected() while len(selection) == 0: input("Please selection one or more objects and press any key to continue.") selection = project.get_selected() # get_selection() returns a list of ObjectID # ObjectIDs are useful for getting names, paths, parents, icon names # and use within several project functions print("You have selected these objects:") for item in selection: print(" name: {}, path: {}, type: {}, icon name: {}".format( item.name, item.path, item.type_name, item.icon_name)) # Example output: # >>> You have selected these objects: # >>> name: Pit model toes and crests, path: /scrapbook/surfaces/Pit model toes and crests, type # >>> name: legends, path: /legends, type: VisualContainer, icon name: StandardContainerClosed # >>> name: actual toes and crests, path: /scrapbook/surfaces/Pit model toes and crests/actual tork # >>> name: Pit model, path: /scrapbook/surfaces/Pit model, type: Surface, icon name: FacetNetwo # >>> name: points3of4, path: /scrapbook/scans/set1/points3of4, type: PointSet, icon name: Point
Listing a specific type from a selection
The following example will filter the user's selection to include only PointSet and Surface objects from the total selection.
This example uses a newer feature from 1.1. To make this example work with 1.0, the part item.is_a(types_to_find) can be changed to any(item.is_a(ty) for ty in types_to_find).
from mapteksdk.project import Project # Import some data types to work with for this example: from mapteksdk.data import Surface, PointSet if __name__ == "__main__": with Project() as main_project: # Filter existing selection to PointSet and Surface objects selection = main_project.get_selected().where([PointSet, Surface]) print("You have selected the following PointSet and Surface objects:") for item in selection: print(f" Name: {item.name}, Path: {item.path}, Type: {item.type_name}") # Example output: # >>> Please make a selection of the following types and press any key to continue: PointSet,Surface # >>> You have selected the following PointSet, Surface objects: # >>> Name: Pit model, Path: /scrapbook/surfaces/Pit model, Type: Surface # >>> Name: points1of4, Path: /scrapbook/scans/set1/points1of4, Type: PointSet # >>> Name: points2of4, Path: /scrapbook/scans/set1/points2of4, Type: PointSet # >>> Name: points3of4, Path: /scrapbook/scans/set1/points3of4, Type: PointSet # >>> Name: points4of4, Path: /scrapbook/scans/set1/points4of4, Type: PointSet
Accessing ObjectID properties
The ObjectID class is used in many places throughout the SDK and can used in many of the same functions that accept a path string to an object. Instances of ObjectID are normally returned when querying the Project class for object information or selections. Referring to an ObjectID is useful when objects are assigned multiple paths or no path at all (orphan).
from mapteksdk.project import Project project = Project() # Connect to default project path = "scrapbook/surfaces/Pit model" example_object = project.find_object(path) # If the object has been found it will be returned as an ObjectID # ObjectID <mapteksdk.data.ObjectID> if example_object: print("Object properties for {}:".format(path)) print((" Name: {}\n Icon name: {}\n Path: {}\n Parent path: {}" "\n String ID: {}\n Handle: {}\n Is hidden: {}\n Type name: {}" "\n Exists: {}\n Is orphan: {}").format( example_object.name, example_object.icon_name, example_object.path, # Note: Primary path only if it has multiple example_object.parent.path, example_object, example_object.native_handle, example_object.hidden, # Note: use of hidden objects must be explicitly enabled project.type_name(example_object), example_object.exists, example_object.is_orphan # Note: An orphan is an object without a path )) else: print("{} not found".format(path)) # Example output: # >>> Object properties for scrapbook/surfaces/Pit model: # >>> Name: Pit model # >>> Icon name: FacetNetwork # >>> Path: /scrapbook/surfaces/Pit model # >>> Parent path: /scrapbook/surfaces # >>> String ID: OID(I27, C0, T146) # >>> Handle: 41095346599755803 # >>> Is hidden: False # >>> Type name: Surface # >>> Exists: True # >>> Is orphan: False
Opening an object for read-only access
The following example demonstrates opening an existing object for reading using the Project.read() function with context management.
from mapteksdk.project import Project project = Project() # Connect to default project path = "scrapbook/surfaces/Pit model" # Project().find_object() will return an ObjectID if found if project.find_object(path): # Project().read(path or ObjectID) provides read-only access to an object. # Attempting changes on read-only arrays will result in exceptions. with project.read(path) as surface: print("Point count: {}\nFacet count: {}\nEdge count: {}".format( surface.point_count, surface.facet_count, surface.edge_count )) # Example output: # Point count: 64268 # Facet count: 127778 # Edge count: 192047
Opening an object for read and write
The following example demonstrates opening an existing object for editing using the Project.edit() function with context management. In this example, half of the points within the surface are coloured red.
from mapteksdk.project import Project import math project = Project() # Connect to default project path = "scrapbook/surfaces/Pit model" if project.find_object(path): # Project().edit(path) provides edit access to an object with context management. # Once leaving he context of the 'with' statement, the object is saved. with project.edit(path) as surface: # Make half of the points on surface red [Red,Green,Blue,Alpha] first_half = math.floor(surface.point_count / 2) surface.point_colours[first_half:] = [255, 0, 0, 255]
Creating a new object and opening for read and write
The following example demonstrates how to create a new object in the Project, of a specific type. This is done using the Project.new() function. This example will create a Polyline object and make all of its edges (lines) blue and store it under /cad/zigzag line.
from mapteksdk.project import Project from mapteksdk.data import Polyline import numpy as np project = Project() # Connect to default project path = "/cad/zigzag line" # Project().new(path, Type) provides creation and edit access to a new object # of the specified type with context management. The object is stored in the # project when exiting the scope of the with statement. with project.new(path, Polyline, overwrite=True) as zigzag: # Create a blue zigzag line zigzag.points = np.array([[0, 0, 0], [10, 10, 0], [20, 0, 0], [30, 10, 0], [40, 0, 0], [50, 10, 0]]) zigzag.point_colours = [0,0,255] if project.find_object(path): print("Saved {}".format(path))
Renaming an object
Objects can be renamed by using the Project.rename_object() function. This is done by providing an absolute path to an object and a new name for it (either with a new absolute path or by name only, excluding its path—demonstrated in this example).
This example renames scrapbook/surfaces/Pit model to Pit model 2 then changes it back to its original name.
import sys from mapteksdk.project import Project, ObjectDoesNotExistError # It is possible for an object to exist with multiple paths in a project, # so the Project().rename() function is used for renaming and/or moving an object. with Project() as project: path = "scrapbook/surfaces/Pit model" try: project.rename_object(path, "Pit model 2", overwrite=True) found_at = project.find_object("/scrapbook/surfaces/Pit model 2") if found_at is None: print("Copy operation failed.") sys.exit(0) print(f"Object now called: {found_at.name}") project.rename_object(found_at, "Pit model") print(f"Object renamed back to: {found_at.name}") except ObjectDoesNotExistError: print(f"Object to copy not found at: {path}") # Example output: # Object now called: Pit model 2 # Object renamed back to: Pit model
Moving an object within a project
The Project.rename_object() function can be used to rename objects as well as move them. The reason this function has multiple uses is because it is possible for an object to contain multiple paths. Therefore when moving it, you are really re-assigning one of (though normally its only) destination path(s).
This example moves an existing object, then moves it back to its original parent container.
from mapteksdk.project import Project # The main difference is to move an object, you define an absolute path # in the 'new_name' parameter. old_path = "scrapbook/surfaces/Pit model" new_path = "/surfaces/Pit model" with Project() as project: project.rename_object(old_path, new_path) print(f"Object now exists here: {new_path}") project.rename_object(new_path, old_path) print("Object moved back to: {}".format(old_path))
Copying an object
The Project.copy_object() function provides an efficient way to make copies of objects within the project.
from mapteksdk.project import Project with Project() as project: path = "/scrapbook/surfaces/Pit model" copy_to = "/scrapbook/surfaces/copies/Pit model (copy)" item_to_copy = project.find_object(path) if item_to_copy: # Project().copy_object() allows convenient copying of project objects # by using a path or ObjectID as source and a path as destination. # An ObjectID for the new copy is returned from the function. copied = project.copy_object(item_to_copy, copy_to, overwrite=True) print("Made a copy of \n '{}'\n to '{}'".format(item_to_copy.path, copied.path)) else: raise RuntimeError(f"Source object not found at: {path}") # Example output: # >>> Made a copy of # >>> '/scrapbook/surfaces/Pit model' # >>> to '/scrapbook/surfaces/copies/Pit model (copy)'
Deleting an object
The Project.delete() function can be used to delete objects from the project.
from mapteksdk.project import Project with Project() as project: path = "scrapbook/surfaces/Pit model" item_to_delete = project.find_object(path) # Project().delete() allows deletion of an object. Note that # if deleting a container, you may leave 'orphan' child objects in the # project that no longer have a parent path available. if item_to_delete: # Temporarily copy the object to put back when finished. copy = project.copy_object(path, path + "(temp copy)") project.delete(path) deleted_exists = project.find_object(path) != None print(f"Verify if anything found at path {path}? {deleted_exists}") if project.rename_object(copy, "Pit model"): print(f"Restored original {copy.path}") else: raise RuntimeError(f"Source object not found at: {path}") # Example output: # >>> Verify if anything found at path scrapbook/surfaces/Pit model? False # >>> Restored original scrapbook/surfaces/Pit model
Deleting contents of a container
The Project.delete_container_contents() function can be used to clear all objects within a container. The example below first creates some copies of data into /surfaces/, then deletes it.
from mapteksdk.project import Project with Project() as project, project.undo(): # WARNING: This will delete everything in your surfaces container. Run # this script at your own risk (But you can undo it). project.delete_container_contents("surfaces")
Determining object type
Within the project contents you may see objects of several types. Depending on the name of an object is not a suitable way to infer its type. The following example demonstrates how to query the type of the data you are interacting with.
from mapteksdk.project import Project with Project() as project: selection = project.get_selected() if selection: for item in selection: print(f"'{item.path}' is a {item.type_name}, displayed with icon: {item.icon_name or 'Unknown'}") try: with project.read(item) as reader: pass except TypeError: print(" - Note: This object is not yet supported properly by the SDK") else: print("You have not selected anything.") # Example output: # >>> '/scrapbook/other types/legend' is a NumericColourMap, displayed with icon: ColourMapNumeric1D # >>> '/surfaces' is a StandardContainer displayed with icon: StandardContainerClosed # >>> '/cad/zigzag line' is a Polyline, displayed with icon: EdgeChain # >>> '/scrapbook/surfaces/Pit model toes and crests/actual toes and crests' is a EdgeNetwork, displayed with icon: EdgeNetwork # >>> '/scrapbook/other types/ellipsoid' is a Ellipsoid, displayed with icon: Ellipsoid # >>> - Note: This object is not yet supported properly by the SDK # >>> '/scrapbook/surfaces/Pit model' is a Surface, displayed with icon: FacetNetwork # >>> '/scrapbook/scans/set1/points2of4' is a PointSet, displayed with icon: PointSet # >>> '/scrapbook/other types/3d text' is a Text3D, displayed with icon: Text3D
Checking if an object is supported by SDK version
Maptek databases support hundreds of data types. Not all of these are available for creation and modification through the Maptek Python SDK, even if they can be seen, copied, renamed or deleted within the project contents. In some cases before attempting to work with data you may need to verify that it is fully supported by the version of the SDK you are using as well as the dependencies or application it is being used with.
from mapteksdk.project import Project from mapteksdk.data import ObjectID # As this SDK works across multiple products and a project may contain a # significant number of data types yet to be exposed via the SDK or # available in certain contexts. Therefore some objects that can be # found may not be supported directly for reading, writing or editing. # Via Project() functions these objects can be moved/renamed, etc, but # will be unsupported by read(), edit() and new() # Objects that are unsupported will raise TypeError when they are opened for # read or edit. There is no way to create a new object of an unsupported type # as there is is no type to refer to. def is_read_supported(project: Project, item: ObjectID) -> bool: """Check if reading the object is supported. This does not indicate whether editing the object is supported. And this does not indicate whether any useful information can be read from the object. Parameters ---------- project Project to use to check if the object is readable. item The ObjectID of the object to check if it is readable. Returns ------- bool True if the object can be opened for reading, False if it cannot. """ try: with project.read(item): return True except TypeError: return False with Project() as project: for oid in project.get_selected(): if is_read_supported(project, oid): print( f"{oid.path} is supported by the SDK and the current application." ) else: print( f"{oid.path} is either not supported for reading or editing by the SDK" " or the reference DLLs used in this context." )
Note: If you have a use case or need for additional data not yet supported, please contact support. There is ongoing development to add SDK support for more data types. The underlying architecture contains several hundred data types, however not all of them are generally applicable for this context.