alicatlib
Python library for Alicat Scientific instruments
over serial — the full {flow, pressure} × {meter, controller} × {gas,
liquid} matrix, plus the CODA Coriolis line. Covered prefixes include
M- / MC- gas mass flow, P- / PC- gas pressure, L- / LC-
liquid flow, the K-family (K- / KM- / KC- / KF- / KG-) CODA
Coriolis prefixes, and all documented specialty variants (MCDW-,
PCD-, LCR-, BASIS-, SFF-, …). The Medium model is flexible
enough to handle devices configured for gas, liquid, or both — users
narrow to the specific unit configuration via assume_media= on
open_device.
alicatlib is focused on correctness, typed APIs, and reliable multi-device
acquisition.
Status: beta. Documentation and release prep in progress; see docs/design.md for the architecture and remaining future work.
Highlights
- Typed end to end.
Gas.N2,Unit.SCCM,Statistic.MASS_FLOW, frozen dataclass responses.py.typedshipped.mypy --strictpasses. - Declarative commands. One
Commandobject per Alicat command with encoding, decoding, firmware gating, device-kind gating, and medium gating (gas vs. liquid, for CODA and friends) as metadata — adding a new command is ~50 lines. - Typed errors. Distinct exception types for timeout, malformed response,
unsupported firmware, and device error markers — all carrying structured
ErrorContextfor debuggability. - Safety. Destructive operations (factory reset, baud change, exhaust)
require
confirm=True. Setpoints are range-checked before any I/O. - Multi-device, correctly.
AlicatManagerruns many devices concurrently; same-port requests serialize via a shared lock, different ports run in parallel, resources unwind cleanly on partial-open failures. - Acquisition built in.
record()drives one or more devices at an absolute-target cadence with no cumulative drift, andpipe()drains samples into anySampleSink. First-party sinks:InMemorySink,CsvSink,JsonlSink,SqliteSink(stdlib WAL), plusParquetSinkandPostgresSinkbehind extras. - Streaming mode.
dev.stream(...)opens a bounded-memoryStreamingSessionthat normalises the wire and fast-fails any concurrent request/response command on the same bus;NCSsets the device's continuous-stream rate on V10 firmware 10v05+. - Swappable transports.
SerialTransportfor hardware,FakeTransportfor tests; TCP / Modbus can land behind the same interface later. - Sync or async. The core is
async(built onanyio), and a sync facade (alicatlib.sync.Alicat) wraps it for scripts, notebooks, and REPLs. - Lean core.
pip install alicatlibpulls inanyioandanyserial— and nothing else. Parquet, Postgres, and docs live behind extras.
Install
pip install alicatlib
# optional sinks
pip install 'alicatlib[parquet]'
pip install 'alicatlib[postgres]'
Requires Python 3.13+.
Quickstart (sync)
from alicatlib.sync import Alicat
with Alicat.open("/dev/ttyUSB0") as dev:
frame = dev.poll()
print(frame.get_float("Mass_Flow"))
dev.setpoint(50.0, "SCCM")
Quickstart (async)
import anyio
from alicatlib import Gas, open_device
async def main():
async with await open_device("/dev/ttyUSB0") as dev:
frame = await dev.poll()
print(frame.get_float("Mass_Flow"))
await dev.gas(Gas.N2, save=True)
anyio.run(main)
Development
Uses uv for env and lock management, hatchling
for the build backend, ruff for format and lint, and mypy --strict for
types.
uv sync --all-extras --dev
uv run pytest
uv run ruff format --check .
uv run ruff check .
uv run mypy
See CONTRIBUTING.md for the full workflow, and docs/design.md for the architectural design.
License
MIT. See LICENSE.
Metadata
Release files for alicatlib 0.3.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| alicatlib-0.3.1.tar.gz | 482.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| alicatlib-0.3.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 776.3 kB
Release files / alicatlib-0.3.1.tar.gz
| Download URL | alicatlib-0.3.1.tar.gz |
|---|---|
| Size | 482.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
4262022b233deab2f6744acc523e73856cd8b7399224b50e15ce3f282b179564
|
|
BLAKE2b-256 checksum How to use checksums |
6f6d773e7f228bcc4071ed71776a80774d3af2acd50e88f24019f4ef126ab206
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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 1, 2026.
Transparency logRelease files / alicatlib-0.3.1-py3-none-any.whl
| Download URL | alicatlib-0.3.1-py3-none-any.whl |
|---|---|
| Size | 294.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
c0b0754c255c629232e355af4b9752a22b8efef0fb497c14316896e927b8fb63
|
|
BLAKE2b-256 checksum How to use checksums |
40e0a0f93e224e8044beadcda262e0a877eedd70d1146e7740e8bf7e71ccb238
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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 1, 2026.
Transparency log