-
Notifications
You must be signed in to change notification settings - Fork 1
Python bindings
Note that currently, as in GeoDms 20.5.0 d.d. 25/06/2026, the geodms bindings are a work in progress and only available for python versions 3.13.2.
This page describes the geodms module, which embeds the GeoDMS engine inside Python (load a configuration, find items, update them). This is a different mechanism from exchanging data files between a GeoDMS configuration and a separate Python script: for that, write/read tabular data as parquet (or csv) and, if needed, let the GeoDMS run the script on demand via exec_ec. See GeoDMS through Python for an overview of all three integration architectures.
Update, d.d. 12/03/2026: we currently compilie PyDms.pyd with Python 3.13 installed and the environment variables PYTHON3_INCLUDE_DIR and PYTHON3_LIBRARIES referring to that installation.
GeoDMS version 15.0.1 introduces the geodms module for python. This document describes through code examples how to use the currently exposed set of geodms functionalities.
Version note. The configuration-building and primary data access bindings — creating containers, units, attributes and parameters in memory (without a model script), setting parameter and attribute values, and reading results back — described in the sections Building a configuration in memory, Setting parameter values and Querying results (Primary Data Access) below are available in GeoDMS version 20.5.0 and later. The basic load-and-query bindings are available since 15.0.1.
In order to import the geodms module in python make sure the installation folder is added to your path so that the module can be found:
import sys
sys.path.append('C:/"Program Files"/ObjectVision/GeoDms14.15.2')
from geodms import *Retrieving the geodms version:
dms_version = version()Initializing the geodms module:
dms_engine = Engine()Loading a dms configuration:
dms_config = dms_engine.load_config('./prj/config.dms')Get the root item of a loaded dms configuration:
root = dms_config.root()Finding an item in a loaded dms configuration from the root item:
parameters = root.find("/parameters")Testing if the item is found by asserting that it is not null:
if (parameters.is_null()):
raise Exception(f"Cannot find output item: '/parameters'")Get the name (or full path) of a found item:
item_name = parameters.name()
item_full_name = parameters.full_name()Get the dms expression of a found item:
item_expr = parameters.expr()Iterating over the direct sub-items of a container (the kind of an item follows from
isUnitItem() / isDataItem()):
for child in root.sub_items():
kind = 'unit' if child.isUnitItem() else ('attr' if child.isDataItem() else 'container')
print(child.name(), kind)Inspecting an item that failed to calculate:
reason = some_item.fail_reason() # empty string when the item is validChange the expression of a found item:
out_dir = root.find("/parameters/input/OutDir")
out_dir.set_expr("path/to/new/out/dir")Update an item:
target_item_fullname = "dms/target/item"
target_item = root.find(target_item_fullname)
if target_item.is_null():
raise Exception(f"Cannot find output item: {target_item}")
target_item.update()(GeoDMS 20.5.0 and later.) Instead of loading a .dms model script, a configuration can be built from scratch in Python. Start from an empty configuration root:
engine = Engine()
config = engine.create_config_root('demo') # an empty in-memory configuration
root = config.root()Add sub-containers, units, attributes and parameters:
# a sub-container
data = root.add_container('data')
# a domain unit of a basic value type, sized by an expression. A domain's element
# count comes from its calculation rule; range(uint32, 0, n) defines an n-element domain.
entities = root.create_unit('Entity', 'uint32')
entities.set_expr('range(uint32, 0, 5)')
# an attribute over that domain, with a values unit of a basic value type
value = data.add_attribute('value', entities.asConst(), 'float64')
# an attribute with an explicit domain unit, values unit and value composition
geometry = data.add_data_item('geometry', point_domain, point_values, ValueComposition.Polygon)
# a parameter (Void domain) of a basic value type
nr_entries = root.add_param('nrEntries', 'uint32')Attach a storage manager (e.g. to read a source file), or force in-memory / calculator-only operation:
src = root.add_container('src')
src.set_storage_manager('path/to/source.gpkg', 'gdal.vect', read_only=True)
derived.disable_storage()Define derived items purely by an expression, exactly as in a model script:
doubled = data.add_attribute('doubled', entities.asConst(), 'float64')
doubled.set_expr('value * 2.0')
total = root.add_param('total', 'float64')
total.set_expr('sum(value)')The Engine also exposes the shared default unit of a basic value type (handy as a values unit) and the Void unit (the domain of every parameter):
f64 = engine.default_unit('float64')
void = engine.void_unit()(GeoDMS 20.5.0 and later.) Parameters (items with a Void domain) can be assigned a value directly:
nr_entries.set_param_int(5)
pi = root.add_param('pi', 'float64'); pi.set_param_float(3.14159)
label = root.add_param('label', 'string'); label.set_param_str('hello from python')
print(pi.get_param_float()) # 3.14159(GeoDMS 20.5.0 and later.) After updating an item, its values can be read back through the Primary Data Access functions. Cast a tree item to a DataItem (or use a MutableDataItem returned by the builders) and read scalar or bulk values:
result = root.find('/data/doubled')
result.update() # (re)calculate first
di = result.asDataItem()
print(di.size()) # number of values (= domain unit count)
print(di.get_value_as_float(0)) # a single value, by index
print(di.get_values_as_float_list()) # all values as a python list
# the same for integers and strings
print(di.get_values_as_int_list())
print(di.get_value_as_str(0))Writing primary data into a fresh in-memory attribute is done in bulk; the list length should equal the domain element count:
value.set_values_from_float_list([1.0, 2.0, 3.0, 4.0, 5.0])
value.set_values_from_int_list([1, 2, 3, 4, 5])A data item also exposes its domain and values unit, and the unit its entity count / numeric range:
dom = di.domain_unit()
print(dom.value_type_id(), dom.count()) # e.g. ValueTypeId.UInt32 5
print(di.values_unit().value_type_id()) # e.g. ValueTypeId.Float64
print(di.values_unit().value_type_id().name) # 'Float64'module geodms
-
version()→str— the GeoDMS version string -
ValueComposition— enum:Single,Polygon,Sequence,MultiPoint -
ValueTypeId(20.5.0+) — enum of value types:Float64,Float32,UInt32,Int32,UInt16,Int16,UInt8,Int8,UInt64,Int64,Bool,UInt4,SPoint,WPoint,IPoint,UPoint,FPoint,DPoint,String,Void,Unknown
class Engine — the single engine instance for the process. Constructing it also
registers a message callback that prints GeoDMS diagnostics (warnings, calculation errors)
to stderr, so failures are visible rather than silently yielding undefined values.
-
Engine()— construct (only once per process) -
load_config(config_file_name)→Config— load a.dmsconfiguration -
create_config_root(name)→Config(20.5.0+) — create an empty in-memory configuration -
default_unit(value_type)→UnitItem(20.5.0+) — shared default unit of a basic value type -
void_unit()→UnitItem(20.5.0+) — theVoidunit (domain of parameters)
class Config
-
root()→MutableTreeItem— the (mutable) root item -
const_root()→ConstTreeItem(20.5.0+) — a read-only root item
class ConstTreeItem / MutableTreeItem — an item in the tree
-
is_null()→bool -
find(item_path)→ tree item — look up an item by path -
name()→str,full_name()→str(20.5.0+),expr()→str,descr()→str(20.5.0+) -
sub_items()→list(20.5.0+),parent()→ tree item (20.5.0+),fail_reason()→str(20.5.0+) -
update()— calculate/update the item (and its storage, if configured) -
isDataItem()/asDataItem()— test / cast to aDataItem -
isUnitItem()/asUnitItem()— test / cast to a unit item
ConstTreeItem additionally exposes first_subitem() and next() for tree traversal.
MutableTreeItem additionally exposes (all building methods are 20.5.0+):
-
set_expr(str),set_descr(str),asConst() -
add_container(name)→MutableTreeItem -
create_unit(name, value_type)→MutableUnitItem -
add_data_item(name, domain, values, vc=ValueComposition.Single)→MutableDataItem -
add_attribute(name, domain, values_value_type)→MutableDataItem -
add_param(name, values_value_type)→MutableDataItem -
set_storage_manager(storage_name, storage_type, read_only=True),disable_storage()
class UnitItem / MutableUnitItem (20.5.0+)
-
is_null(),name(),full_name(),value_type_id()→ValueTypeId -
count()→int,get_range()→(begin, end) -
MutableUnitItem:set_expr(str)(e.g.'range(uint32, 0, n)'to size a domain),set_count(n),set_range(begin, end),asConst()
class DataItem
-
is_null()→bool -
name(),full_name()(20.5.0+) -
domain_unit()/values_unit()→UnitItem(20.5.0+),value_composition()(20.5.0+) -
size()→int(20.5.0+),update()(20.5.0+) -
get_value_as_float(i),get_value_as_int(i),get_value_as_str(i)(20.5.0+) -
get_values_as_float_list(),get_values_as_int_list()(20.5.0+) -
LockAndGetStringValue(i)→str— read the value at indexias a string
class MutableDataItem (20.5.0+)
-
asDataItem()— read-only view;domain_unit(),values_unit(),value_composition(),size(),name(),full_name(),update(),set_expr(str) -
set_values_from_float_list(list),set_values_from_int_list(list)— write primary data (list length = domain element count) -
set_param_float(v),set_param_int(v),set_param_str(v),get_param_float()
Adapted from python/tst/UnitTests.py:
import os
import sys
# make the geodms module and its dependencies (e.g. gdal.dll) findable
geodms_path = os.path.abspath('../../bin/Release/x64')
sys.path.append(geodms_path)
os.environ['PATH'] += os.pathsep + geodms_path
from geodms import *
# initialise the engine and load a configuration
engine = Engine()
config = engine.load_config('basic_data_test.dms')
# navigate the item tree from the root
root = config.root()
param_item = root.find("/parameters/test_param")
print(param_item.is_null()) # False if found
# change an expression and (re)calculate a dependent result
param_item.set_expr("3b")
result_item = root.find("/export/IntegerAtt")
result_item.update() # updates the item and writes its storage, if configuredA complete in-memory example (build a configuration without a model script and read
results back) is available in python/tst/InMemoryConfig.py.
GeoDMS ©Object Vision BV. Source code distributed under GNU GPL-3. Documentation distributed under CC BY-SA 4.0.