rna
The abstractions you keep rewriting, written once. rna packages the design patterns and polymorphism helpers every grown codebase re-invents — strategy, backend, composite, decorator, singleton, switch, attribute links, and Storable/Plottable mixins that turn one _save_<ext> method into full save/load dispatch. On top of that base it ships the proof the patterns carry weight: one plotting API over matplotlib and pyvista, and configuration that layers. The core has no required dependencies at all.
import numpy as np
import rna.plotting
vertices = np.array([[0.0, 0, 0], [1, 0, 0], [1, 1, 0], [0, 1, 0]])
faces = np.array([[0, 1, 2], [0, 2, 3]])
axes = rna.plotting.add_subplot(dim=3) # matplotlib, pyvista, ...
artist = rna.plotting.plot_mesh(axes, vertices, faces, color=[0.2, 0.8], cmap="plasma")
rna.plotting.set_colorbar(axes, artist)
rna.plotting.save("mesh.png")
That is the whole program on either backend, and it is rna’s own patterns at work: the renderer behind those verbs is a strategy, so rna.plotting.use("pyvista") swaps it without touching a line, and the default — "auto" — makes the choice itself once a mesh gets big enough to need a GPU.
Why rna
Patterns, tested once. Strategy, backend, composite, decorator, singleton, switch and symlink-like attribute links. The classic design patterns live in books and blog posts — as code you are expected to retype — and rna is the package that ships them instead: base classes with doctests, in place of the fourth hand-rolled registry in your codebase.
Polymorphism you declare in one method. Subclass Storable, implement _save_json, and your object has save/load with extension dispatch, path expansion and in-memory buffers; the same move gives any class a backend-agnostic plot. Try finding that on PyPI — this is the piece rna exists for.
One plotting API is the patterns’ proof. matplotlib is right until a mesh has a hundred thousand faces, and then it is very wrong. Built on the strategy pattern above, rna puts both it and pyvista behind fifteen verbs (add_subplot, plot_mesh, set_colorbar, save, …), so switching is a one-line decision instead of a rewrite. Those fifteen names are the package’s semver promise — see the plotting guide.
Nothing you did not ask for. The core installs zero dependencies. numpy, matplotlib, pydantic, hydra and pyvista each live behind an extra, so a library that only wants rna.path and rna.log pays for neither a plotting stack nor a settings framework.
Configuration that actually layers. Packaged defaults, then a user file, then environment variables, validated by pydantic, with ${...} references resolved across all three. And, deliberately, without pinning antlr4 the way hydra does.
Features
rna.pattern — reusable design-pattern implementations: strategy, backend, composite, decorator, singleton, switch, attribute links
rna.polymorphism — Storable and Plottable mixins: implement _save_<ext> and get extension dispatch, save/load and buffers for free
rna.plotting — a multi-backend plotting facade: matplotlib, pyvista, or an automatic choice between them behind one API
rna.config — layered, typed package settings on pydantic-settings, plus composed application config for hydra-based CLIs (rna.config.app)
rna.log — colour-formatted logging with an optional tqdm progress bar
rna.path — pathlib-based path utilities that resolve ~, symlinks and ..
rna.parsing — argparse parent parser that wires up logging from the command line
rna.process — run a shell command with its output streamed into a logger
Installation
pip install rna
The core is dependency-free; each subpackage that needs more declares an extra:
Extra |
Pulls in |
Needed for |
|---|---|---|
rna[plotting] |
numpy, matplotlib, more-itertools |
rna.plotting |
rna[pyvista] |
pyvista (and VTK, ~68 MB) |
the GPU plotting backend |
rna[config] |
pydantic, pydantic-settings |
rna.config |
rna[app] |
hydra-core, omegaconf |
rna.config.app |
rna[categorical] |
scikit-learn |
categorical plot colours |
rna[full] |
all of the above |
everything |
Usage
import json
import rna.polymorphism
class Run(rna.polymorphism.Storable):
def __init__(self, samples):
self.samples = samples
def _save_json(self, path, **kwargs):
with open(path, "w") as file_:
json.dump(self.samples, file_)
@classmethod
def _load_json(cls, path, **kwargs):
with open(path) as file_:
return cls(json.load(file_))
Run([1, 2, 3]).save("~/runs", "2026-08", "latest.json") # dispatch on the extension,
run = Run.load("~/runs/2026-08/latest.json") # "~" resolved, parents created
One method per format is all you write; save/load grow extension dispatch, path resolution, buffers and a NotImplementedError that names the method missing for a format you did not implement.
The usage guide walks through every subpackage with runnable examples; the API reference has the details.
Resources
Documentation: https://dboe.gitlab.io/rna
Source code: https://gitlab.com/dboe/rna
Bug reports: https://gitlab.com/dboe/rna/-/issues/
Changelog: https://gitlab.com/dboe/rna/-/blob/master/CHANGELOG.md
Contributing
pixi run help lists every task in the repository; pixi run test runs the suite and pixi run docs builds and opens these pages. The contributing guide covers the branching model, how a release is cut, and what the pipeline checks before a merge.
License
MIT — see LICENSE.rst.
Metadata
Release files for rna 1.0.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 | Provenance | |
|---|---|---|---|---|
| rna-1.0.1.tar.gz | 531.4 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| rna-1.0.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 626.0 kB
Release files / rna-1.0.1.tar.gz
| Download URL | rna-1.0.1.tar.gz |
|---|---|
| Size | 531.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
86bf1ad6de91bf02d6797e5142da81123b998cd1c896be33ff81d78fb8cda580
|
|
BLAKE2b-256 checksum How to use checksums |
82194b53cf19211553db6140027529f028cbfdb039521f822839cfa8c234fc22
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.0 {"installer":{"name":"uv","version":"0.11.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"12","id":"bookworm","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / rna-1.0.1-py3-none-any.whl
| Download URL | rna-1.0.1-py3-none-any.whl |
|---|---|
| Size | 94.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ea3740471aa5093f9b3c0f3175ddbfa03e05c4830434c9ce7cde51d1d836be4c
|
|
BLAKE2b-256 checksum How to use checksums |
4bfc4328124eddbb2706397a468063ed00c9a31fa244d60ada4034c4114cbcfc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.0 {"installer":{"name":"uv","version":"0.11.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"12","id":"bookworm","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Security for rna 1.0.1
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.
No provenance found
None of the files in this release were uploaded with provenance metadata.
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.