Skip to main content

quenta

Analysis, figures, and reusable utilities for the towers evidence-accumulation task.

Layering

Imports should point down this list, never up:

notebooks/  # calls + prose, no logic
  plots/  # data -> Figure
  analysis/  # data -> numbers
    io/  # disk <-> data
      settings.py  # machine config, paths
        utils/  # standalone

Install

git clone <url> && cd quenta
pip install -e ".[dev]"        # or: uv pip install -e ".[dev]"

If some other project depends on quenta (e.g. the repo for a paper), install it there pinned to a specific version, never to the latest commit:

pip install quenta==0.1.0                                              # from PyPI
pip install "quenta @ git+ssh://git@github.com/ThomasMorvan/quenta@v0.1.0"  # from git

Pinning matters because anything that produced a figure in a paper must stay reproducible: a version is a permanent pointer to one commit, so the exact code can be recovered later even after defaults change.

Releasing a new version

Three steps, in this order. Do all three, or the version number stops meaning one specific state of the code.

1. Bump the version. Edit version in pyproject.toml, then commit:

git commit -am "release v0.1.1"

2. Tag it and push. This is what a git+ install resolves:

git tag v0.1.1
git push && git push --tags

3. Upload to PyPI. This is what pip install quenta resolves:

rm -rf dist/          # or old builds get uploaded too
python -m build       # writes dist/quenta-0.1.1.tar.gz + .whl
twine upload dist/*

Neither a pushed tag nor an uploaded PyPI version can be changed afterwards — that is the point of them, since other people's installs depend on them meaning the same thing forever. If a release is wrong, don't fix it in place: bump to 0.1.2 and release again.

One-time PyPI setup

Needed once per machine, before step 3 ever works:

pip install build twine

Create an API token at https://pypi.org/manage/account/token/ (scope it to this project once the first upload exists), and save it in ~/.pypirc:

[pypi]
  username = __token__
  password = pypi-AgEIcHlwaS5vcmc...

Then chmod 600 ~/.pypirc, since that file is a credential.

To rehearse without burning a real version number, upload to https://test.pypi.org instead: twine upload -r testpypi dist/* (separate account, separate token).

Updating an install

git pull                  # this clone; the editable install picks it up
pip install -e ".[dev]"   # only if pyproject.toml dependencies changed

In a consumer project, bump the pinned version and reinstall. For a git+ pin, add --force-reinstall: pip compares version strings, and two different commits can carry the same one.

Settings

Data should live outside the repo. Paths resolve in this order:

priority source scope
1 an explicit data_root= argument for tests where you need to change root
2 settings.local.toml this machine, gitignored
3 settings.toml committed defaults
4 built-in DEFAULTS so an installed package still works
cp settings.local.toml.example settings.local.toml

Never commit a personal path: a tracked machine-specific file means a merge conflict every time you change device.

Run the verification pipeline

python -m quenta.verify --data-root /path/to/data
# or open notebooks/demo.ipynb

Generates a synthetic per-session dataset, makes a fit and summary at group level, and writes overview.png/.pdf to the figures directory.

Notebook kernel (VS Code)

The system Python has no pip and no ipykernel, so install:

python3 -m venv .venv
.venv/bin/pip install -e ".[dev]" jupyter ipykernel

(or just run scripts/setup-venv.sh, which does the same thing and prints the next step below)

Then in notebooks/demo.ipynb: pick kernel (top-right of the notebook toolbar) --> Select Another Kernel --> Python Environments... --> .venv (Python 3.x). If not listed, use Enter interpreter path... and paste the full path to .venv/bin/python.

Only need to do that once per clone.

Commit notebooks with output, without the metadata noise

Inspired by https://gist.github.com/33eyes/431e3d432f73371509d176d0dfb95b6e Cell outputs (figures, printed numbers) are worth committing as a record of what the notebook produced. Kernelspec, language_info, and execution counts are not: they're machine-specific and churn the diff every run, even when nothing meaningful changed. A git filter strips just that, on the way in.

  1. Add the filter to git config by running the following command in bash inside the repo:
git config filter.strip-notebook-metadata.clean 'python3 scripts/nb_strip_metadata.py'

(or just run scripts/setup-git.sh, which does the same thing) 2. notebooks/.gitattributes already routes *.ipynb through it:

*.ipynb filter=strip-notebook-metadata

After that, commit to git as usual. Outputs stay in the committed notebook; kernelspec/language_info/execution counts don't. Your local file on disk is untouched either way.

To bypass the filter for one commit (e.g. you want the raw file, metadata and all), use git -c filter.strip-notebook-metadata.clean= add <path> instead of the usual git add.

Tests

From an activated environment:

pytest  # everything, quick params, good for a pre-commit hook
pytest --slow  # same tests, full params for statistical confidence
pytest --cov  # which lines the tests actually run; fails under 90%

Coverage is opt-in rather than always-on, so a plain pytest stays fast. CI runs it on the --slow pass. The floor exists to catch a module that stopped being tested at all, not to chase 100%.

if __name__ == "__main__": blocks are excluded outright (see [tool.coverage.report] in pyproject.toml).

From outside environment, prefix with the interpreter: .venv/bin/python -m pytest.

Linting is ruff (pycodestyle + pyflakes + import order, 79 cols; configured in pyproject.toml), and CI runs it before the tests:

ruff check .  # report
ruff check . --fix  # fix what's mechanically fixable

Tests that pick a value from the slow fixture run every time, just with reduced parameters (e.g. fewer iterations) by default and full ones under --slow, instead of being skipped outright.

The name

The two behavioral apparatuses are named Cirith Ungol and Orthanc, for together they make the Two Towers. The instrument of reckoning is Amon Hen, the Hill of the Eye, from which all things may be seen. And Quenta is the word in the High Speech signifying a tale or an account, as in Quenta Silmarillion, wherein the lore of many ages was gathered from scattered memories into a single history. Thus is this work likewise named; for out of much that was watched and set down is wrought one account, and out of that account are the figures drawn, and from those figures the tale is sung.

Release files for quenta 0.1.0

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

Source distribution (sdist)

Source distribution for quenta 0.1.0
File Size Uploaded
quenta-0.1.0.tar.gz 27.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for quenta 0.1.0
File Interpreter ABI Platform
quenta-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 47.5 kB

Release files / quenta-0.1.0.tar.gz

Download URL quenta-0.1.0.tar.gz
Size 27.0 kB
Tags Source
SHA-256 checksum
How to use checksums
c76b43aee99cef2dbed2ad4ad251b2f74e49c41efd5de8e37be18373f6447fd1
BLAKE2b-256 checksum
How to use checksums
b86cf3179ed121c66823734ad769e589cfd30274b0a0dce56de8835afcd9180c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.3

Release files / quenta-0.1.0-py3-none-any.whl

Download URL quenta-0.1.0-py3-none-any.whl
Size 20.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d009bcb9ea27bc9d91bcac2ab5441c493ff10ecc013e8358e85f13d6c9c30002
BLAKE2b-256 checksum
How to use checksums
310f430ad88bbe9831f89f23b000b24cf54d1064aa90302e7dfbc19db5fb4c04
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.3

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release 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