Skip to main content

rebolt-cgm

Load a CGM figure from an aircraft maintenance manual in Python, and get its SVG, hotspots, text and PNG crops with sidecars.

rebolt_cgm reads a CGM (ISO/IEC 8632) file in the WebCGM 2.0 or 2.1, S1000D or ATA iSpec 2200 profile, binary or clear text, plain or gzip-compressed, and applies its ATA CMP companion. It gives the SVG, the sheet, the hotspots, the text runs and the diagnostics. It renders any region to PNG with a sidecar that maps the pixels back to the sheet, and splits a sheet into tiles. Use it to convert manuals in bulk, or to crop figures for a vision model and map the model's answer back to the hotspots.

The package is a thin layer over the cgm-tools Rust library, so it draws exactly what the cgm command line and the browser viewer draw. A Figure is immutable. Loading and rendering release the GIL, so threads that share one figure render in parallel. Results are frozen dataclasses generated from the Rust types, and the package ships type hints. Failures raise cgm.LoadError, cgm.RegionError or cgm.RenderError, each with a typed kind.

Install

pip install rebolt-cgm
pip install "rebolt-cgm[pil]"   # with Pillow, for Rendered.to_pil()

There is a wheel for CPython 3.10 and later on macOS (arm64 and x86_64), Linux (x86_64 and aarch64, glibc 2.17 or later) and Windows (x86_64). It has no required dependencies. The import package is rebolt_cgm, and the examples import it as cgm.

Quick start

import rebolt_cgm as cgm

figure = cgm.Figure.load("figure.cgm", companion=cgm.DISCOVER)
print([hotspot.id for hotspot in figure.hotspots])
with open("figure.svg", "w") as file:
    file.write(figure.svg)
rendered = figure.render(cgm.RegionSheet(), cgm.OutputSizeDpi(dpi=150.0))
with open("figure.png", "wb") as file:
    file.write(rendered.png)

companion=cgm.DISCOVER looks for the companion beside the CGM file, as cgm convert --discover-companion does. To name it, pass its path or its bytes: companion="figure.cmp". Figure.load also takes the CGM as bytes.

Convert a folder to SVG and PNG

For large batches, use the CLI: cgm convert DIR --out OUT --svg --png --discover-companion converts in parallel, resumes after an interruption, and writes a report. For a few hundred files, or to keep the work in Python:

import pathlib
from concurrent.futures import ThreadPoolExecutor

import rebolt_cgm as cgm

source, out = pathlib.Path("figures"), pathlib.Path("out")
out.mkdir(exist_ok=True)


def convert(path: pathlib.Path) -> str | None:
    try:
        figure = cgm.Figure.load(path, companion=cgm.DISCOVER)
        png = figure.render(cgm.RegionSheet(), cgm.OutputSizeDpi(dpi=150.0)).png
    except (cgm.LoadError, cgm.RenderError) as error:
        return f"{path.name}: {error.kind}"
    (out / f"{path.stem}.svg").write_text(figure.svg)
    (out / f"{path.stem}.png").write_bytes(png)
    return None


with ThreadPoolExecutor() as pool:
    failures = [f for f in pool.map(convert, sorted(source.glob("*.cgm"))) if f]
print("\n".join(failures))

Crop a hotspot for a vision model, with its sidecar

The sidecar lists every hotspot and text run that shows in the image, with its box in image pixels, so a model's answer about the image maps back to the figure.

import dataclasses
import json

import rebolt_cgm as cgm

figure = cgm.Figure.load("figures/pump.cgm", companion=cgm.DISCOVER)
crop = figure.render(
    cgm.RegionHotspot(id=cgm.HotspotId("VALVE_1"), margin=cgm.MarginMillimetres(5.0)),
    cgm.OutputSizeFit(width=1568, height=1568),
)
image = crop.png                                    # PNG bytes for the model request
for hotspot in crop.sidecar.hotspots:
    print(hotspot.id, hotspot.bizdesc, hotspot.pixels)
sidecar_json = json.dumps(dataclasses.asdict(crop.sidecar))

try:
    figure.render(cgm.RegionHotspot(id=cgm.HotspotId("NOPE"), margin=cgm.MarginFraction(0.0)),
                  cgm.OutputSizeWidth(px=800))
except cgm.RenderError as error:
    assert isinstance(error.kind, cgm.RenderErrorUnknownHotspot)

The same crop from the shell is cgm render FIG.cgm --discover-companion --region hotspot:ID:5mm --fit 1568x1568 --out crop.png --sidecar crop.json, and the PNG is byte-identical. In both, the size is the size of the image you get, after rotation or --rotate turns it.

Tile a sheet at 300 DPI

from concurrent.futures import ThreadPoolExecutor

import rebolt_cgm as cgm

figure = cgm.Figure.load("figures/schematic.cgm")
tiles = figure.tiles(3, 2, cgm.MarginMillimetres(10.0))   # neighbours share 10 mm


def render(tile: cgm.Tile) -> cgm.Rendered:
    return figure.render(cgm.RegionUnits(rect=tile.rect), cgm.OutputSizeDpi(dpi=300.0))


with ThreadPoolExecutor() as pool:
    for tile, rendered in zip(tiles, pool.map(render, tiles)):
        with open(f"r{tile.row}c{tile.column}.png", "wb") as file:
            file.write(rendered.png)

A CGM with several pictures

ISO/IEC 8632-1 lets a metafile hold any number of pictures, and each is its own image. WebCGM, S1000D and ATA GREXCHANGE files hold one, so most callers never select. Figure.pictures lists them without writing any SVG, picture= selects one, cgm.PictureIndex(1) by zero-based index or cgm.PictureName("Detail A") by its BEGIN PICTURE identifier, and Figure.load_all loads every picture from one decode. A companion applies to the first picture only; the others report companion-picture.

import rebolt_cgm as cgm

for info in cgm.Figure.pictures("deck.cgm"):
    print(info.index, info.name)
detail = cgm.Figure.load("deck.cgm", picture=cgm.PictureIndex(1))
by_name = cgm.Figure.load("deck.cgm", picture=cgm.PictureName("Detail A"))  # exactly one picture has this name
for figure in cgm.Figure.load_all("deck.cgm"):
    with open(f"deck~p{figure.picture.index}.svg", "w") as file:
        file.write(figure.svg)

Without picture=, a CGM with several pictures raises LoadError with kind LoadErrorPictureCount.

A metafile may also hold no picture (ISO/IEC 8632-1 B.3.1). Figure.pictures then returns (), Figure.load_all returns (), and Figure.load raises LoadError with kind LoadErrorPictureCount(found=0), whose message says there is nothing to write. Its .diagnostics hold the information no-picture.

Checking a profile

Loading checks no profile rule. profile= on Figure.load and Figure.load_all checks the CGM against the rules of a profile: cgm.ProfileCheck.DETECT for the one its METAFILE DESCRIPTION declares, or WEBCGM, S1000D or GREXCHANGE whatever it declares. What the check finds joins .diagnostics with source cgm.DiagnosticSource.PROFILE; it never fails the load, and the SVG is the same with and without it.

checked = cgm.Figure.load("fig.cgm", profile=cgm.ProfileCheck.DETECT)
findings = [d for d in checked.diagnostics if d.source is cgm.DiagnosticSource.PROFILE]

Errors

Exception When kind
LoadError the CGM has an error, holds several pictures and none is selected or holds none, the selection names no single picture, or the picture cannot be written as SVG LoadErrorDecode, LoadErrorPictureCount, LoadErrorPictureOutOfRange, LoadErrorUnknownPictureName, LoadErrorAmbiguousPictureName, LoadErrorUnrepresentable; .diagnostics holds every diagnostic
RenderError the region or size cannot be placed on the sheet, the hotspot is unknown or has no box, or the image is above 64 Mpx RenderErrorUnknownHotspot, RenderErrorNoPhysicalSize, RenderErrorTooLarge, ...
RegionError tiles with a negative overlap, or a millimetre overlap on a sheet with abstract scaling RegionErrorInvalidRegion, RegionErrorNoPhysicalSize
ValueError a request value outside its Rust type: a negative rectangle, a non-finite number, a negative pixel count, zero tiles, a picture index outside 0 to 2^32 - 1
OSError a file cannot be read

All three typed exceptions subclass cgm.CgmError. Branch on the class and its kind, not on the message.

Development

The classes in python/rebolt_cgm/_types.py are generated from schema/cgm.schema.json, which is generated from the Rust types. After changing a Rust type, regenerate both:

cargo run -p cgm-schema -- write

The test generated_files_are_fresh (cargo test -p cgm-schema) fails while either file is stale. To build and test the wheel:

cargo build --release -p cgm-cli                 # the parity test compares with `cgm render`
cd crates/cgm-python
python3 -I ../../tools/release/licenses.py write python .   # LICENSE.md, COMMERCIAL.md, licenses/
maturin build --release -o dist
pip install dist/rebolt_cgm-*.whl pytest mypy Pillow
pytest tests                                     # includes mypy --strict and stubtest

Licence

rebolt-cgm is free for research, education, personal and non-profit use under the PolyForm Noncommercial License 1.0.0, in LICENSE.md among the wheel's licence files.

Any use by a company needs a commercial licence. That includes evaluation, internal tools and pipelines, and running the package on a server or behind an API. To get a commercial licence, write to founders@rebolt.ai. COMMERCIAL.md lists the uses that need one.

Copyright (c) 2026 Tieki Inc (Rebolt AI). The wheel also carries third-party components under their own licences, which licenses/THIRD-PARTY-NOTICES.md lists.

Metadata

Release files for rebolt-cgm 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Built distributions (wheels)

Table of built distributions (wheels) for rebolt-cgm 0.1.0
File Actions
rebolt_cgm-0.1.0-cp310-abi3-win_amd64.whl CPython 3.10 abi3 Windows x86-64 Details for rebolt_cgm-0.1.0-cp310-abi3-win_amd64.whl
rebolt_cgm-0.1.0-cp310-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl CPython 3.10 abi3 Linux glibc 2.17+ x86-64 Details for rebolt_cgm-0.1.0-cp310-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
rebolt_cgm-0.1.0-cp310-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl CPython 3.10 abi3 Linux glibc 2.17+ ARM64 Details for rebolt_cgm-0.1.0-cp310-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
rebolt_cgm-0.1.0-cp310-abi3-macosx_11_0_arm64.whl CPython 3.10 abi3 macOS 11.0+ ARM64 Details for rebolt_cgm-0.1.0-cp310-abi3-macosx_11_0_arm64.whl
rebolt_cgm-0.1.0-cp310-abi3-macosx_10_12_x86_64.whl CPython 3.10 abi3 macOS 10.12+ x86-64 Details for rebolt_cgm-0.1.0-cp310-abi3-macosx_10_12_x86_64.whl

Total release size: 17.9 MB

Release files / rebolt_cgm-0.1.0-cp310-abi3-win_amd64.whl

Download URL rebolt_cgm-0.1.0-cp310-abi3-win_amd64.whl
Size 3.6 MB
Tags CPython 3.10 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
1fbbb99da585391a3fc23b58aa7886fb2d06fc13b4a7c788799b563a2c1ca30b
BLAKE2b-256 checksum
How to use checksums
8e59e523acee67459fb528c427c5cc4c8ebae3392614461c30c26285f0692cbf
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 11, 2026.

Transparency log

Release files / rebolt_cgm-0.1.0-cp310-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl

Download URL rebolt_cgm-0.1.0-cp310-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Size 3.7 MB
Tags CPython 3.10 Linux glibc 2.17+ x86-64 abi3
SHA-256 checksum
How to use checksums
100cd8df80025358f98b13d0ec44d16b7af7fa8236c68dd427c66c9457781309
BLAKE2b-256 checksum
How to use checksums
8b8a0f82c9c2e5b4f1560a0c39b00616ec1e8321dd08c5ea2a99deaae0706133
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 11, 2026.

Transparency log

Release files / rebolt_cgm-0.1.0-cp310-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl

Download URL rebolt_cgm-0.1.0-cp310-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
Size 3.5 MB
Tags CPython 3.10 Linux glibc 2.17+ ARM64 abi3
SHA-256 checksum
How to use checksums
a42228019cceda210bdb3175868f0198280047ad3c2d1d4d03a0cefa226a0200
BLAKE2b-256 checksum
How to use checksums
e142e1cd57f620d62210c5c65b707b3638477be11b3260d920b027c214b3e752
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 11, 2026.

Transparency log

Release files / rebolt_cgm-0.1.0-cp310-abi3-macosx_11_0_arm64.whl

Download URL rebolt_cgm-0.1.0-cp310-abi3-macosx_11_0_arm64.whl
Size 3.5 MB
Tags CPython 3.10 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
471a8fa6e12fcdce768898fb8afc3948003d334d1d877901a32fdf552e52a0df
BLAKE2b-256 checksum
How to use checksums
70f2acb4ff8a915716a920edb2f91888744fa9fff268647a5dea549902e043ad
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 11, 2026.

Transparency log

Release files / rebolt_cgm-0.1.0-cp310-abi3-macosx_10_12_x86_64.whl

Download URL rebolt_cgm-0.1.0-cp310-abi3-macosx_10_12_x86_64.whl
Size 3.7 MB
Tags CPython 3.10 abi3 macOS 10.12+ x86-64
SHA-256 checksum
How to use checksums
b15744abe6077df041f86b4d17726db8fa4a1b7461957434e42aee45b47aa264
BLAKE2b-256 checksum
How to use checksums
606862c3afda418746aafd71fcca79334ac57279e18e20b4adb3bd20a378ba6a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 11, 2026.

Transparency log

Security for rebolt-cgm 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 5 files in this release have been uploaded with provenance metadata.

Select from 5 files

Attestation for rebolt_cgm-0.1.0-cp310-abi3-win_amd64.whl

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 11, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

5 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page