Skip to main content

laterite — a Rust-backed AGS4 reader, writer and validator

laterite

A Rust-backed AGS4 toolchain for the AGS4 geotechnical data format — validate, read as typed data, query, build, fix, diff, certify, and convert ↔ Excel — with a modern, born-typed polars API.

Coming from python-ags4? laterite.compat is a faithful, faster stand-in for its AGS4, check, utils and data modules — one token changes: python_ags4laterite.compat. from python_ags4 import AGS4 becomes from laterite.compat import AGS4, and your code keeps working.

ci python cov PyPI Python versions License: MIT

Install

pip install laterite                     # base AGS4 (polars + duckdb, pyarrow-free)
pip install "laterite[compat]"           # + pandas (python-ags4 drop-in) — still pyarrow-free
pip install "laterite[compat,pyarrow]"   # + the optional pyarrow accelerator (or [all])

Requires Python ≥ 3.12. The wheel is abi3, so one binary covers 3.12 / 3.13 / 3.14. Installing it also puts the lat CLI on your PATH.

The [compat] drop-in is pyarrow-free and fast on its own; adding pyarrow swaps the pandas step for pyarrow's to_pandas and unlocks the Arrow-backed string dtype — an accelerator, never a requirement.

Use

import laterite

# Validate — errors + warnings by default (FYI is opt-in)
report = laterite.validate("delivery.ags")
report.is_valid
for rule, findings in report.by_rule().items():
    print(rule, len(findings))

# Read born-typed columns: a 2DP heading is a float, a DT a datetime
ags = laterite.read("delivery.ags")
ags.groups                       # ['PROJ', 'LOCA', 'SAMP', …]
ags["LOCA"]["LOCA_GL"][0]        # → 12.3  (a polars DataFrame per group)

# SQL across groups, no conversion step
ags.sql("SELECT loca_id, count(*) FROM SAMP GROUP BY 1")

# Repair a dirty file into a fresh handle, then keep working with it
fixed = ags.fix(risky=True)      # pads short rows, transliterates non-ASCII, …

# Typed graph: PROJ → LOCA → SAMP → …
from laterite.ags4 import read_typed
for loca in read_typed("delivery.ags").locas:
    print(loca.loca_id, loca.loca_gl)

# python-ags4 drop-in — swap the import, keep your code
from laterite import compat as AGS4
tables, headings = AGS4.AGS4_to_dataframe("delivery.ags")
AGS4.dataframe_to_AGS4(tables, headings, "round-trip.ags")

read returns born-typed polars frames by default (or pandas with read(..., backend="pandas")) — both pyarrow-free, read back from a Python-owned in-memory DuckDB engine.

More than a faster python-ags4

python-ags4 is the reference Python library for AGS4 — validation plus pandas read/write — and it inspired this project. laterite matches that surface and adds a toolchain on top:

laterite python-ags4
Validate — numbered AGS4 rules
Read → data frames ✅ born-typed polars or pandas pandas, all strings
Build / write AGS4 · Excel ↔ AGS4
Repair engine (fix)
SQL across groups · revision diff
Validity certificates (.ags.idx)
Transport — zstd compress + age encrypt
Typed PROJ → LOCA → SAMP graph
pyarrow required no (optional accelerator) via pandas' own deps

Performance

Synthetic, spec-valid AGS4 from ags4-forge — the wide scaffold: 123 groups, realistic type mix, zero findings. macOS arm64, hot files, mean of 5 warm runs, python-ags4 1.2.0 vs laterite 0.8.0. Both agree on the findings.

Validation

File python-ags4 check_file laterite.validate speedup
4.9 MB · 459 BH 1.5 s 50 ms 30.0×
24.9 MB · 2,219 BH 3.7 s 266 ms 13.9×
102.7 MB · 8,872 BH 12.3 s 1.1 s 11.7×
275.5 MB · 22,813 BH 34.1 s 2.6 s 13.0×
549.7 MB · 45,107 BH 70.0 s 5.4 s 12.9×

Read → typed — the honest comparison for real work. python-ags4 needs AGS4_to_dataframe + convert_to_numeric on every group to get numbers, and still leaves dates as text; laterite.read is born-typed, dates included.

File python-ags4 + convert_to_numeric laterite.read speedup
4.9 MB 187 ms 26 ms 7.2×
24.9 MB 811 ms 136 ms 6.0×
102.7 MB 3.4 s 541 ms 6.3×
275.5 MB 8.9 s 1.4 s 6.4×
549.7 MB 17.5 s 2.9 s 6.0×

Read → strings — like for like, both returning pandas frames of text.

File python-ags4 AGS4_to_dataframe laterite.compat speedup
4.9 MB 144 ms 49 ms 2.9×
24.9 MB 718 ms 206 ms 3.5×
102.7 MB 2.8 s 870 ms 3.2×
275.5 MB 7.3 s 2.2 s 3.3×
549.7 MB 15.2 s 4.6 s 3.3×

The ratio holds as files grow — the gap is a constant factor, not a head start that erodes. Reproduce any of this with uv run python tools/bench-vs-python-ags4.py in the repo: it generates the rungs, verifies each against a pinned SHA-256 so a change to the generator can't move the numbers unnoticed, and prints these exact tables.

Parity + clean-room

121 / 131 of python-ags4 1.2.0's own test suite passes through laterite.compat (92 %); the 10 remaining are deliberate non-closures, documented rule by rule. A weekly job compares the two public surfaces, so a function added upstream can't quietly go missing here.

compat is a package mirroring upstream's own layout, so upstream's import shapes work with one token changed:

from python_ags4 import AGS4          # becomes:
from laterite.compat import AGS4

from python_ags4.AGS4 import AGS4_to_dataframe   # becomes:
from laterite.compat.AGS4 import AGS4_to_dataframe

AGS4, check, utils and data are real, distinct submodules — so code that depends on module identity (monkeypatching check.X and expecting AGS4 not to see it) behaves as it does upstream. from laterite import compat as AGS4 also still works: the flat namespace is unchanged.

Two caveats before you swap. No top-level python_ags4 package ships, and that is deliberate and permanent — inside this wheel it would collide with the real distribution in site-packages. So the import token changes; the rest of the line does not. And compat mirrors the library API only: python-ags4's ags4_cli command is not mirrored, because laterite ships lat instead with its own JSON shapes.

The validator is clean-room from the published AGS4 specification, not adapted from another library's source — python-ags4 is LGPL-3.0, and that separation is what lets laterite ship under MIT. Details: COMPAT.md · OBSERVATIONS.md.

One engine, every stack

laterite on PyPI is the Python surface of one Rust AGS4 engine, shared across:

Surface Package Get it
Python laterite — PyPI pip install laterite
Node.js laterite — npm npm install laterite
CLI lat bundled with this wheel
DuckDB laterite_ags4 — community extension INSTALL laterite_ags4 FROM community;
Browser @laterite/ags4-wasm — npm, or the validator + data explorer npm install @laterite/ags4-wasm

Scriptable output is byte-identical across all of them, so a CI gate and a notebook can't disagree.

Docs

Full documentation — Learn, Cookbook, Concepts, and the Python API reference — at https://docs.laterite.dev/.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

laterite-0.11.0.tar.gz (677.2 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

laterite-0.11.0-cp312-abi3-win_amd64.whl (7.1 MB view details)

Uploaded CPython 3.12+Windows x86-64

laterite-0.11.0-cp312-abi3-manylinux2014_x86_64.whl (6.8 MB view details)

Uploaded CPython 3.12+

laterite-0.11.0-cp312-abi3-manylinux2014_aarch64.whl (6.4 MB view details)

Uploaded CPython 3.12+

laterite-0.11.0-cp312-abi3-macosx_11_0_arm64.whl (6.2 MB view details)

Uploaded CPython 3.12+macOS 11.0+ ARM64

File details

Details for the file laterite-0.11.0.tar.gz.

File metadata

  • Download URL: laterite-0.11.0.tar.gz
  • Upload date:
  • Size: 677.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for laterite-0.11.0.tar.gz
Algorithm Hash digest
SHA256 a74c5db66953de2a40e2ce3ddfad844e047797bd5135e09dc6501069bc0c0b50
MD5 20856ba21746ac6a3df4b9ad9315c6de
BLAKE2b-256 4f5f3004e9dfec369292fa58d4e2248aaf9c8394ed8a6d765de6529a97379a7e

See more details on using hashes here.

Provenance

The following attestation bundles were made for laterite-0.11.0.tar.gz:

Publisher: release.yml on niko86/laterite

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file laterite-0.11.0-cp312-abi3-win_amd64.whl.

File metadata

  • Download URL: laterite-0.11.0-cp312-abi3-win_amd64.whl
  • Upload date:
  • Size: 7.1 MB
  • Tags: CPython 3.12+, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for laterite-0.11.0-cp312-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 d4e68a13723d769f05a65858203824ca88d5c7264f0eb2d91cca3c32c3f87f9b
MD5 1d11e03722f51f0e96e232108a38db9a
BLAKE2b-256 6c97ef4b3a036ffb61203350aa278d808c1cbd143db8e7d1d05224592a9a9c92

See more details on using hashes here.

Provenance

The following attestation bundles were made for laterite-0.11.0-cp312-abi3-win_amd64.whl:

Publisher: release.yml on niko86/laterite

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file laterite-0.11.0-cp312-abi3-manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for laterite-0.11.0-cp312-abi3-manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 3cb3080d95a585b7e1a98f52a8a34d41d1d710c05183baab646432d9aec8540e
MD5 d4fa0dfdcb68203c9cc0074daf8079ab
BLAKE2b-256 38fd176411106e0eba9236b62b1f58ce6df7511b2d87e26a449c100de5d9516a

See more details on using hashes here.

Provenance

The following attestation bundles were made for laterite-0.11.0-cp312-abi3-manylinux2014_x86_64.whl:

Publisher: release.yml on niko86/laterite

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file laterite-0.11.0-cp312-abi3-manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for laterite-0.11.0-cp312-abi3-manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 1a0127ec52dfdb69304d98ec689cab2c256c6bc2787ef38c802653ecfcf4db22
MD5 31e5817e4e338e5c6e2ede409133a72c
BLAKE2b-256 b2bdc6c3218dc582ee38f038dcdf1cb6969143c0c558767d624e0a3bc054f28f

See more details on using hashes here.

Provenance

The following attestation bundles were made for laterite-0.11.0-cp312-abi3-manylinux2014_aarch64.whl:

Publisher: release.yml on niko86/laterite

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file laterite-0.11.0-cp312-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for laterite-0.11.0-cp312-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 135a973034a37c6bfd9d645dacba69ba6950ef551d4a08cdc6cb05fcff8ceb7a
MD5 d7c983434a7409a0e0092bd6ca95080f
BLAKE2b-256 90bf2e367f71de65c70e5e7e7ce761a7737e892a4e5cc6ab3a037c62f551fca0

See more details on using hashes here.

Provenance

The following attestation bundles were made for laterite-0.11.0-cp312-abi3-macosx_11_0_arm64.whl:

Publisher: release.yml on niko86/laterite

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.12.0

5 files

This release

0.11.0 This release

5 files

0.10.1

4 files

0.10.0

4 files

0.9.0

4 files

0.8.0

4 files

0.7.0

4 files

0.6.2

4 files

0.6.1

4 files

0.6.0

4 files

0.5.1

4 files

0.5.0

4 files

0.4.0

3 files

0.2.0

3 files

0.1.0

4 files

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