plumb
Describe water and wastewater treatment plants as plain, typed Python and get RDF that conforms to the WATR water treatment ontology and ASHRAE 223P, which it builds on. No RDF in user code; real Turtle out.
Bundled ontologies: WATR v0.3.0.rc1 (a release candidate whose terms may still change before 0.3.0), ASHRAE 223P (v1.0.0-2026), and the QUDT units and quantity kinds they use. Domain packages for drinking water, activated sludge (ASM2d), and seawater reverse osmosis come compiled from SHACL.
from plumb import Model, connect, flowsheet
from plumb.qudt import quantity_kinds, units
from plumb.watr import Pump
from plumb.watr.drinking_water import ClarificationStage, CoagulationStage
with Model("urn:example:plant#") as model:
intake = Pump("intake-pump")
coagulation = CoagulationStage("coagulation")
clarifier = ClarificationStage("clarifier")
raw_water = connect(intake, coagulation.inlet, name="raw-water")
connect(coagulation.outlet, clarifier.inlet, name="coagulated-water")
raw_water.sensor("raw-water-flow", kind=quantity_kinds.VolumeFlowRate, unit=units.M3_PER_DAY)
model.save("plant.ttl") # connection points and pipes are worked out for you
print(model.validate()) # SHACL via shifty; errors name your objects
flowsheet(model).save("plant.svg")
The ontology classes are generated code, so editors and type checkers see everything: completion, ontology definitions on hover, and type errors when a link's range doesn't fit.
Saved models load back as the same objects, and can be searched by class, medium, or role, or walked along the flow:
from plumb.watr import enums
plant = Model.from_graph("plant.ttl")
plant["intake-pump"].find_all_next(through={"medium": enums.values.Fluid_Water})
Install and run the examples
Plumb requires Python 3.12 or newer. From a checkout of this repository, install the project and its dependencies with uv:
uv sync
Then run an example from the repository root:
uv run python examples/watr/treatment/watr_quickstart.py
uv run python examples/watr/asm2d/watertap_asm2d.py
uv run python examples/watr/seawater_ro/watertap_seawater_ro_full.py
Each example prints a short summary and writes its generated Turtle file next to the example script. See examples/ for more scenarios.
- Documentation: the learning book
(tutorials, how-to guides, explanations, and API reference; build it locally
with
make docs) - Start with modelling a treatment train and characterizing and instrumenting a plant; an S223 air path shows the same API on a 223P building system
- Contributor documentation: docs/index.md
- Design rationale and roadmap: DESIGN.md
- Release notes: CHANGELOG.md
- Examples organized by ontology: examples/
Domain configurations and quantities
Reusable equipment layouts and property metadata are defined in RDF and SHACL. The compiler generates typed configurations and immutable value schemas:
from plumb.qudt import QuantityAmount as Q, units
from plumb.watr.asm2d import AerobicStage, AerobicDesign, OxygenOutletState
with Model("urn:example:reactor#") as model:
reactor = AerobicStage("R5")
reactor.apply_properties(AerobicDesign(oxygen_transfer_coefficient=10.0))
reactor.outlet.apply_properties(
OxygenOutletState(oxygen_concentration=Q(1.91, units.GM_PER_M3))
)
Bare values use shape-declared units; explicit quantities preserve their units.
The same apply_properties(...) API works on equipment, points, and connections.
Use subject.quantity(...) for individual values. capability= selects static,
observable, or actuatable properties; has_aspect= supplies their interpretation.
See domain extensions, the
ASM2d tutorial, and the
extension compiler reference.
Regenerate the supplied domains with
uv run python scripts/generate_example_domains.py.
Development
The Makefile wraps the standard development commands:
make setup # install development and documentation dependencies
make check # lint, type checks, and tests
make docs # build the documentation and execute tutorials
make docs-open # build and open the HTML documentation
make docs-check # full documentation build; warnings are errors
make build # source distribution and wheel, replacing dist/
make dist-check # build, check metadata, and smoke-test the wheel
make regen # regenerate the supplied domain packages from local SHACL
make help # all available targets
Use make test TEST_ARGS="-q tests/test_named_points.py" to select tests.
make format formats source while excluding generated ontology output.
make clean removes documentation, build output, and tool caches.
To release, bump version in pyproject.toml, date the release in
CHANGELOG.md, tag the commit v<version>, and publish a GitHub release
from the tag. The release workflow runs the checks, builds the
distributions, publishes them to PyPI, and attaches them to the release.
To regenerate the committed ontology packages, see docs/codegen.md.
Metadata
Release files for plumb-rdf 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| plumb_rdf-0.1.0.tar.gz | 2.6 MB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| plumb_rdf-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 5.2 MB
Release files / plumb_rdf-0.1.0.tar.gz
| Download URL | plumb_rdf-0.1.0.tar.gz |
|---|---|
| Size | 2.6 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d8199ebeb0ffbb757485b10bb412e0e541e9c56a90159f2e868f6339e38225db
|
|
BLAKE2b-256 checksum How to use checksums |
b10f6c427eb7777d4f60aa547b0b32e06e68cada8fc19ce624b989897401c757
|
| 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 Oct 21, 2026.
Transparency logRelease files / plumb_rdf-0.1.0-py3-none-any.whl
| Download URL | plumb_rdf-0.1.0-py3-none-any.whl |
|---|---|
| Size | 2.6 MB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
baa37f9c6ca04965bfb257ecc9463686c3a6fa870a3a4989bea66c252d636184
|
|
BLAKE2b-256 checksum How to use checksums |
1826c7f72d55ec1d40f6a2e769a2b2e4ac290080f4594658dab6ca836153b9f8
|
| 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 Oct 21, 2026.
Transparency logSecurity for plumb-rdf 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 2 files in this release have been uploaded with provenance metadata.
Attestation for plumb_rdf-0.1.0.tar.gz
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 Oct 21, 2026.
Transparency logA 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.