Skip to content

Python guide

uLib has two complementary Python surfaces:

  1. The installed extension module, used by ordinary Python programs. It always exports uLib.Core and uLib.Math.
  2. The Python engine in gcompose, used by its console and Recipes. It adds a scene-aware ctx object and loads domain modules contributed by the libraries present in that application.

This distinction matters. A standalone script can create a uLib.Math.VoxImage; a Recipe can also create, name, connect, and save an object in the open scene. HEP bindings are extension modules loaded by gcompose when their shared library is present, so they are not guaranteed in a bare import uLib.

# Standalone Python: Core and Math are always the built-in modules.
from uLib import Core, Math

image = Math.VoxImage(Math.Vector3i([16, 16, 16]))
image.SetValue(0, 1.0)

payload = Core.DataSource("configuration")
payload.set_data(b'{"threshold": 0.2}')
assert payload.get_size() == 18

Start here

Goal Read
Install the extension or run it from a build tree Installation
Work with objects, properties, contexts, byte sources, and sinks Core, contexts and data I/O
Create vectors, grids, images, meshes, statistics, and filters Math
Use detector, tomography, or Geant bindings supplied by gcompose plugins HEP extension modules
Build a pull collection or a push producer/consumer pipeline Streaming
Drive a running gcompose remotely Property synchronization
Let an agent — or a script — discover what the session can be told to do Agent context (pyagent)
Chat with Claude, Gemini or OpenCode inside gcompose, acting on the scene Agent panel (agentchat)
See every currently exported Python name in one place Complete export inventory
Add a domain module and its documentation Plugin documentation

The three ways to work

Standalone extension

Use this for numerical processing, file and buffer data, or local objects whose lifetime is owned by Python.

import uLib

box = uLib.Math.ContainerBox()
box.SetSize([100.0, 50.0, 10.0])
print(box.GetSize())

The direct extension links Core and Math. It does not make every C++ library an automatic Python module.

A gcompose console or Recipe

Use this when an object belongs in the open scene. The ctx facade owns creation and makes properties act like normal Python attributes. This is also where streams and DataBuffer form visual, saved pipelines.

# Run in the gcompose console or in a Recipe.
box = ctx.create("ContainerBox", "absorber")
box.Size = [100.0, 50.0, 10.0]
box.update()

ctx.create() is intentionally different from constructing an object with Math.ContainerBox(): the former inserts it in the scene context, where it has an identity, a parent, undo/redo support, and a saved representation.

Remote client

Use uLib.connect() to control a running gcompose or ucontext-server process. The client discovers the classes and properties provided by that process, including classes from plugins. It presents them as ObjectProxy instances rather than pretending all remote objects are local pybind classes.

from uLib import connect

client = connect(port=50051)
scene_box = client.find("absorber")
scene_box.Size = [120.0, 50.0, 10.0]

A generated agent context

Use this when the code — or the model — driving the session should not have to be told what the session contains. uLib.pyagent asks the running application to describe itself, and what comes back is generated from the classes' own property declarations rather than written by hand, so it carries the real properties, ranges, enums, defaults and actions of this build.

from uLib.pyagent import connect

agent = connect(port=50051)

# As MCP tools, which is what an LLM agent is handed.
for tool in agent.tools():
    print(tool["name"], "-", tool["description"])

agent.call("ulib.ContainerBox.configure", {"object": "absorber", "Size": "2 2 2"})

# Or as Python objects generated from the same description.
agent.scene["absorber"].Size = [120.0, 50.0, 10.0]

The difference from the remote client above is what each knows. An ObjectProxy will let you write any property name and report the failure afterwards; a generated tool states beforehand which properties exist, what values are legal, and which of them may be written at all — so a wrong call is refused with the rule it broke. See Agent context (pyagent).

Module availability

Module Where it is available Purpose
uLib.Core Direct extension and gcompose objects, properties, algorithms, persistence, byte sources/sinks
uLib.Math Direct extension and gcompose Eigen/NumPy values, transforms, grids, images, meshes, statistics
uLib.Detectors gcompose when the Detectors library is loaded reconstructed muon events, collections, chambers
uLib.MuonTomography gcompose when the MuonTomography library is loaded tomography event wrappers and image algorithms
uLib.Geant gcompose when the Geant library is loaded selected Geant scene, geometry, emitter, and event types
uLib.pyagent pure Python; needs a session to describe the generated tool/resource context of a running application
uLib.mcp pure Python; run as python -m uLib.mcp an MCP server over stdio, offering both static and generated tools

The current pybind bindings do not export separate uLib.Root or uLib.Vtk modules. Their scene objects can still be created and edited through ctx or a remote client when the application catalogue contains them.

How this reference stays useful

The inventory documents the public names registered in the binding translation units:

  • src/Python/*_bindings.cpp for the built-in Core and Math modules;
  • src/HEP//python/Bindings.cpp for optional HEP modules; and
  • src/Python/uLib/ for the pure-Python Recipe, remote, agent and MCP helpers.

One part of the reference is not written at all. The agent context (uLib.pyagent) is generated by the running application from its own classes, so it needs no page listing its tools: whatever the build holds is what it reports. Agent context explains what is generated and how to read it.

When a plugin adds a binding, add its page under docs/python/plugins/ and a row to Plugin documentation. That keeps new modules discoverable without mixing plugin-specific concepts into the stable Core and Math pages.