Importing and Exporting Data

General

The Maptek Python SDK provides built-in functions for importing and exporting a wide variety of file formats. Most of the functions for common file formats are defined in mapteksdk.data.io, while a few functions specific to PointStudio are defined in mapteksdk.pointstudio.io.

Summary of import and export functions

The import and export support for various file formats is summarised in the table below.

Note:  There are two main types of import function in the SDK. Older SDK import functions such as import_maptekobj() return an ObjectID. Newer functions such as import_autocad_exchange_file() return either a single ImportedObject, or a sequence of ImportedObject , depending on whether the file format supports storing multiple objects. Refer to the table below for the return type of each import function, and see the examples on this page for usage.

Extension Format name Import function Import return type Export function
.* (Any supported file format)

import_any()

Sequence[ImportedObject]

-
.00t Vulcan triangulation

import_00t()

ObjectID

export_00t()

.3di Maptek 3DI scan

import_3di()

ImportedObject

-
.3dp Maptek 3DP scan

import_3dp()

ImportedObject

-
.3dr Maptek 3DR scan

import_3dr()

ImportedObject

-
.3dv Scan grid text

import_3dv()

ImportedObject

-
.arch_d Vulcan archive

import_arch_d()

Sequence[ImportedObject]

-
.asc ASCII scan file

import_ascii_mdl_scan()

ImportedObject

-
.bdf Vulcan block model definition

import_bdf()

ObjectID

export_bdf()

.bmf Vulcan block model

import_bmf()

ObjectID

export_bmf()

.dgd.isis Vulcan design database

import_dgd_isis()

Sequence[ImportedObject]

-
.dwg AutoCAD DWG

import_autocad_drawing_file()

Sequence[ImportedObject]

-
.dxb AutoCAD DXF

import_autocad_exchange_file()

Sequence[ImportedObject]

-
.e57 E57

import_e57_scan()

ImportedObject

-
.ecw Enhanced Compression Wavelet

import_ecw()

ImportedObject

-
.fls Faro scan

import_fls_scan()

ImportedObject

-
.hgt SRTM height file

import_hgt()

ImportedObject

-
.ixf Optech IXF

import_optech_ixf_scan()

Sequence[ImportedObject]

-
.jp2 JPEG 2000

import_jp2()

ImportedObject

-
.jpg JPEG image

import_image()

import_image_with_world_file()

ImportedObject

-
.kml Keyhole markup language

import_kml()

ImportedObject

-
.las LAS lidar data

import_las_scan()

ImportedObject

-
.laz Compressed LAS data

import_las_scan()

ImportedObject

-
.maptekobj Maptek object

import_maptekobj()

ObjectID

export_maptekobj()

.mpc, .toc Mantis MPC format

import_legacy_mantis_scan()

ImportedObject

-
.obj Wavefront OBJ

import_obj()

Sequence[ImportedObject]

-
.ply Polygon file format

import_ply()

ImportedObject

-
.png PNG image

import_image()

ImportedObject

-
.ptg Leica Cyclone PTG

import_cyclone_ptg_scan()

Sequence[ImportedObject]

-
.ptx Leica Cyclone PTX

import_cyclone_ptx_scan()

Sequence[ImportedObject]

-
.r3s Maptek R3 scan

import_r3s()

ImportedObject

-
.scd Vulcan legend

import_scd()

Sequence[ImportedObject]

-
.shp ESRI shapefile

import_shp()

ImportedObject

-
.zfs Z+F scan

import_zfs_scan()

ImportedObject

-

Import functions returning an ObjectID

Import functions that return an ObjectID import a single object into the project, but do not assign a path to it. After successfully importing the data, you need to call the Project.add_object() method to assign the imported object to a path. You need to explicitly name the object in the supplied path.

Note:  To run the example scripts provided in this section, first download and extract Maptek_PythonSDK_Sample_IO_Files_20200108.zip to a folder on your system. The example scripts reference the folder location F:\Python SDK Help\data\. You will need to update this location in the scripts to match the folder where you extracted the files.

Importing a .00t file

Use import_00t() to import a Vulcan triangulation file (.00t) as a surface object, as demonstrated in the following script:

from mapteksdk.project import Project
from mapteksdk.data import io
from mapteksdk.data.units import DistanceUnit

project = Project() # Connect to default project

# The file path you have exported the sample data to:
file_path = "F:\Python SDK Help\data\phase_1_topo.00t"
# Import the 00t:
imported_surface = io.import_00t(file_path, DistanceUnit.meter)

if imported_surface:
    # Successful imported, now assign a path
    # After add_object, set imported_surface as the new ObjectID:
    imported_surface = project.add_object(
        full_path="import/phase_1_topo",
        new_object=imported_surface,
        overwrite=True)
else:
    print("{} failed to import.".format(file_path))

Important:  You need to make sure that you specify the correct unit for the file in the import function.

See also:  Surfaces

Importing a .bmf file

Use import_bmf() to import a Vulcan block model file .bmf, as demonstrated in the following script:

from mapteksdk.project import Project
from mapteksdk.data import io
from mapteksdk.data.units import DistanceUnit

project = Project() # Connect to default project

# The file path you have exported the sample data to:
file_path = "F:\Python SDK Help\data\shawmodel_reg.bmf"
# Import the bmf:
imported_blockmodel = io.import_bmf(file_path, DistanceUnit.meter)

if imported_blockmodel:
    # Successful imported, now assign a path
    # After add_object, set imported_surface as the new ObjectID:
    imported_blockmodel = project.add_object(
        "import/shawmodel",
        imported_blockmodel,
        overwrite=True)
else:
    print("{} failed to import.".format(file_path))

Important:  You need to make sure that you specify the correct unit for the file in the import function.

See also:  Block Models

Importing a .maptekobj file

A Maptek object file (.maptekobj) is a binary file that stores objects exported from certain Maptek applications such as PointStudio, GeologyCore, and BlastLogic. See Exporting to a .maptekobj file on this page for more information on Maptek object files. Use import_maptekobj() to import Maptek object files, as demonstrated in the following script:

import os
from mapteksdk.project import Project
from mapteksdk.data import io
project = Project() # Connect to default project
# Use the folder you have stored example maptekobj files in:
maptekobj_path = "F:\\Python SDK Help\\data"
maptekobj_files = ["single_object.maptekobj", "multiple_objects.maptekobj", "objects_in_container.maptekobj"]

def assign_path(object_id, object_path):
    # Use the rename_object function to move it from nowhere into a path
    saved = project.rename_object(object_id, object_path, overwrite=True)
    print("Stored: {}".format(object_path)) if saved else print("Failed to store: {}".format(object_path))
    return object_path

def store_maptekobj_objects(maptekobj_id, parent_path = "scrapbook"):
    if "\\" in maptekobj_id.name:
        # multiple objects were exported, but not stored within a VisualContainer
        for item in project.get_children(maptekobj_id).ids():
            assign_path(item, "{}/{}".format(parent_path, item.name))
    else:
        # Single object exported, or VisualContainer with multiple objects
        assign_path(maptekobj_id, "{}/{}".format(parent_path, maptekobj_id.name))

if __name__ == "__main__":

    for file_name in maptekobj_files:
        file_name = os.path.join(maptekobj_path, file_name)
        # Import the maptekobj, providing an ObjectID as a result
        imported_data = io.import_maptekobj(file_name)
        if imported_data:
            store_maptekobj_objects(imported_data)
        else:
            print("Failed to import {}".format(file_name))

# Expected output:
# >> Stored: scrapbook/single_object
# >> Stored: scrapbook/multiple_objects(1st)
# >> Stored: scrapbook/multiple_objects(2nd)
# >> Stored: scrapbook/maptekobj_example

Note:  To account for nested objects, this script uses special handling to store imported objects in the project rather than using Project.add_object().

Running this script will result in several objects being imported, similar to what is shown in the image below.

Import functions returning an ImportedObject

mapteksdk 1.9+

Some import functions return an ImportedObject. An ImportedObject is a named tuple that includes the ObjectID of the imported object and a suggested name for it. After successfully importing data, you need to call the Project.add_object() method to assign the imported object to a path. To use the suggested object name, include the name field of the ImportedObject tuple as part of the path. See Importing a .3dp file below for an example.

If the file format supports containing multiple objects, the import will return a sequence of ImportedObject tuples, with each element representing a single imported object. You can pass the sequence directly into Project.add_objects() to add all imported objects into a specified container. See Importing an .obj file below for an example.

Note:  To run the example scripts provided in this section, download and extract io_examples.zip to a folder on your system. The extracted files include the example scripts and the required data files. The scripts will not work if they are moved without the accompanying data folder.

Importing a .3dp file

Maptek 3DP scan files (.3dp) are used to store lidar data. A single 3DP file will only ever contain a single scan. You can use the import_3dp() function to import a 3DP file as a scan object, as demonstrated in the following script:

import pathlib

from mapteksdk.data import io
from mapteksdk.operations import open_new_view
from mapteksdk.project import Project, OverwriteMode

SCRIPT_DIR = pathlib.Path(__file__).parent

def main(project: Project):
    imported_object = io.import_3dp(SCRIPT_DIR / "data" / "perlin_scan.3dp")
    project.add_object(
        f"scans/single import example/{imported_object.name}",
        imported_object.oid,
        overwrite=OverwriteMode.UNIQUE_NAME,
    )
    open_new_view([imported_object.oid])

if __name__ == "__main__":
    with Project() as main_project:
        main(main_project)

Running this script imports the scan from the file perlin_scan.3dp and adds it the container scans/single import example using the object name perlin_scan supplied by the ImportedObject. It will look like this in the project of the connected application:

See also:  Scans

Importing an .obj file

Wavefront OBJ files (.obj) can contain multiple objects. Use the import_obj() function to import .obj files, as demonstrated in the following script:

import pathlib

from mapteksdk.data import io
from mapteksdk.operations import open_new_view
from mapteksdk.project import Project, OverwriteMode

SCRIPT_DIR = pathlib.Path(__file__).parent

def main(project: Project):
    imported_objects = io.import_obj(SCRIPT_DIR / "data" / "cubes.obj")
    project.add_objects(
        "surfaces/many import example",
        imported_objects,
        overwrite=OverwriteMode.UNIQUE_NAME,
    )
    open_new_view([imported_object.oid for imported_object in imported_objects])

if __name__ == "__main__":
    with Project() as main_project:
        main(main_project)

After running this script, you will see this in the project of the connected application:

Each imported object receives its name from the .obj file.

Tip:  The import functions make no guarantees that the names of imported objects are unique. Therefore, it is recommended to always pass OverwriteMode.UNIQUE_NAME to Project.add_objects() to prevent objects with the same name overwriting each other.

Handling formats unsupported by the application

If the connected application does not support a file format, the import function will raise an ImportFormatNotSupportedError. This commonly occurs when using mapteksdk.pointstudio.io functions without a connection to PointStudio.

For example, the script below imports an E57 scan when connected to PointStudio but exits if connected to GeologyCore:

import pathlib

from mapteksdk.errors import ImportFormatNotSupportedError
from mapteksdk.pointstudio import io
from mapteksdk.operations import open_new_view
from mapteksdk.project import Project, OverwriteMode

SCRIPT_DIR = pathlib.Path(__file__).parent

def main(project: Project):
    try:
        imported_object = io.import_e57_scan(SCRIPT_DIR / "data" / "perlin_scan.e57")
    except ImportFormatNotSupportedError:
        print("Importing e57 scans is not supported by the connected application.")
        return
    project.add_object(
        f"scans/not supported example/{imported_object.name}",
        imported_object.oid,
        overwrite=OverwriteMode.UNIQUE_NAME,
    )
    open_new_view([imported_object.oid])

if __name__ == "__main__":
    with Project() as main_project:
        main(main_project)

Importing an image

You can use the import_image() function to import an image such as JPEG or PNG. Unlike other import functions, import_image() does not use the connected application’s import functionality. Instead, it relies on the Pillow library (installed with mapteksdk), allowing it to import any image format supported by Pillow rather than just those supported by the application.

Usage example:

imported_raster = io.import_image(image_path)

However, this imports the raster without associating it with an object, which is often not useful. Typically, the raster is immediately registered to a Surface. The script below demonstrates this, modifying the example Rasters > Creating a raster from an image file to use import_image() instead of the raster constructor:

import pathlib

from mapteksdk.project import Project, OverwriteMode
from mapteksdk.data import Raster, Surface, RasterRegistrationTwoPoint, io
from mapteksdk.operations import open_new_view, request_file

def get_image_path() -> pathlib.Path:
    return request_file(
        title="Pick an image", extensions={"image files": ("png", "jpg")}
    )

if __name__ == "__main__":
    with Project() as project:
        image_path = get_image_path()
        image_name = image_path.name

        imported_raster = io.import_image(image_path)

        with project.edit(imported_raster.oid, Raster) as raster:
            raster.title = image_name
            with project.new(
                f"surfaces/{image_name}", Surface, overwrite=OverwriteMode.UNIQUE_NAME
            ) as canvas:
                canvas.points = [
                    [0, 0, 0],
                    [raster.width, 0, 0],
                    [0, raster.height, 0],
                    [raster.width, raster.height, 0],
                ]
                canvas.facets = [[0, 1, 3], [0, 2, 3]]
                registration = RasterRegistrationTwoPoint(
                    image_points=[[0, 0], [raster.width, raster.height]],
                    world_points=[canvas.points[0], canvas.points[-1]],
                    orientation=[0, 0, 1],
                )
                canvas.associate_raster(raster, registration)

        open_new_view([canvas.id])

As with other import functions, import_image() imports the image into the project but does not give it a path. However, rather than adding it to the project using Project.add_object(), the image should be registered to an object such as Surface.

See also:  Rasters

Importing an image with a world file

Some images, such as satellite images or maps, can be linked to georeferencing information in a world file, which associates them with a specific location on the Earth's surface. The import_image_with_world_file() function imports an image file and applies it to a surface representing the extent defined by the world file. The following script demonstrates this using an image from NASA’s Blue Marble: Next Generation dataset with a corresponding world file (available on github):

import pathlib

from mapteksdk.data import io
from mapteksdk.operations import open_new_view
from mapteksdk.project import Project, OverwriteMode
from PIL import Image

SCRIPT_DIR = pathlib.Path(__file__).parent

def main(project: Project):
    # Disable the decompression bomb safety check because the image is very large.
    Image.MAX_IMAGE_PIXELS = None

    with project.progress_indicator(
        title="Importing", message="Importing image"
    ) as indicator:
        # Provide fake progress so that the user knows the import is in
        # progress.
        # This import can take several minutes, so run this script with care.
        indicator.fake_progress()
        imported_object = io.import_image_with_world_file(
            SCRIPT_DIR / "data" / "world.topo.bathy.200411.3x21600x21600.D2.jpg"
        )
        # The import is finished, set the progress indicator to be complete.
        indicator.set_progress(100)
    project.add_object(
        f"surfaces/image with world file/{imported_object.name}",
        imported_object.oid,
        overwrite=OverwriteMode.UNIQUE_NAME,
    )
    open_new_view([imported_object.oid])

if __name__ == "__main__":
    with Project() as main_project:
        main(main_project)

Running this script results in the following surface being created in the connected application:

Note:  In this example, the world file (.wld) was found automatically based on the name of the image. In this case, the name of the world file must be identical to the name of the image file, apart from its extension.

Importing any file type

In addition to the format-specific import functions, the SDK also provides the import_any() function, which can be used to import any file type supported by the connected application.

To use it, simply pass the file path:

imported_objects = io.import_any(
    SCRIPT_DIR / "data" / "cubes.maptekobj",
)

For file formats that require units or coordinate systems, these must be explicitly specified, even if set to default values:

imported_objects = io.import_any(
        SCRIPT_DIR / "data" / "cubes.obj",
        unit=DistanceUnit.METRE,
        coordinate_system=None
    )

Failing to pass required inputs will raise an ImportMissingInputError.

Tip:  In general, you should prefer to use format-specific import functions where possible, as their use is less error-prone. The use of import_any() is recommended when the format of the file to be imported is not known when the script is written.

Key points:

  • import_any() always returns a sequence of ImportedObject tuples, even if the file contains a single object.

  • It is possible to pass units or coordinate systems when importing formats that don't accept them (for example, a .maptekobj file). In this case, the unit or coordinate system will be ignored.

  • If the file format is unsupported by the connected application, an ImportFormatNotSupportedError will be raised.

Note:  Static type checking is limited with import_any()—it cannot deduce specific object types like it can with format-specific imports (e.g. import_e57_scan()), so auto-complete suggestions in IDEs may be less helpful.

Exporting data

The SDK provides several functions to export data to file.

Exporting to a .00t file

Use export_00t() to export a surface to a .00t file. The following script demonstrates re-exporting the surface imported from an earlier example as a .00t:

from mapteksdk.project import Project
from mapteksdk.data import io
from mapteksdk.data.units import DistanceUnit

project = Project() # Connect to default project

# The file path to export the surface to:
save_path = "F:\Python SDK Help\data\exported.00t"
# Locate ObjectID of surface to export
surface_to_export = project.find_object("import/phase_1_topo")
if surface_to_export:
    # Export to 00t:
    export_success = io.export_00t(surface_to_export, save_path, DistanceUnit.meter)
    if not export_success:
        print("Export failed")
else:
    print("Could not find surface to export in project")

Exporting to a .bmf file

Use export_bmf() to export a block model to a .bmf file. The following script demonstrates re-exporting the block model imported from an earlier example as a .bmf:

from mapteksdk.project import Project
from mapteksdk.data import io
from mapteksdk.data.units import DistanceUnit

project = Project() # Connect to default project

# The file path to export the block model to:
save_path = "F:\Python SDK Help\data\exported.bmf"
# Locate ObjectID of block model to export
blockmodel_to_export = project.find_object("import/shawmodel")
if blockmodel_to_export:
    # Export to bmf:
    export_success = io.export_bmf(blockmodel_to_export, save_path, DistanceUnit.meter)
    if not export_success:
        print("Export failed")
else:
    print("Could not find block model to export in project")

Exporting to a .maptekobj file

A Maptek object file (.maptekobj) is a binary file capable of storing a variety of object types including CAD data, surfaces, scans, block models, and more. Maptek object files are useful for the following:

  • Sharing data between Maptek projects and applications

  • Backing up project data

  • Archiving project data

Important:  Objects that depend on external storage or data systems (outside of the project) may encounter issues when exported as Maptek object files. The receiving application may import the data, but might not be able to fully interpret it, particularly across different software versions.

In certain Maptek applications, such as GeologyCore or PointStudio, you can open the Maptek object file as a secondary project. This functionality provides an explorer view where you can browse the contents of the object file, which may contain multiple objects within containers.

Exporting data to a .maptekobj is similar to exporting a triangulation to a .00t file. However, if you need to export multiple objects into a single file, do this by first placing them in a VisualContainer.

The following script exports the contents of the scrapbook container to a single .maptekobj file.

from mapteksdk.project import Project
from mapteksdk.data import io
project = Project() # Connect to default project

save_path = "F:\\Python SDK Help\\data\\export.maptekobj"

if __name__ == "__main__":
    scrapbook = project.find_object("scrapbook")
    # Export the scrapbook container and any children within it
    export_success = io.export_maptekobj(scrapbook, save_path)
    if export_success:
        print("Exported {} to {}".format(scrapbook.path, save_path))
    else:
        print("Failed to export {} to {}".format(scrapbook.path, save_path))