This is the tutorial and example workspace for PyAutoFit. These are the canonical, agent-agnostic instructions for this repo. PyAutoFit is a general-purpose Python framework for Bayesian model fitting and inference — model composition, priors, non-linear searches, samples, the aggregator, and graphical models. It is not tied to any science domain; the examples here are deliberately domain-agnostic toy problems (fitting 1D profiles such as Gaussians).
scripts/— Runnable Python scripts, organised by PyAutoFit feature:overview/— Concise tour of the core features (overview_1_the_basics.pyfirst).searches/— Every non-linear search:nest.py(dynesty, nautilus),mcmc.py(emcee, zeus),mle.py(drawer, LBFGS),start_point.py.model/— Model composition (priors, collections, custom model objects).features/— Advanced features: graphical models, model comparison, search chaining, search grid search, sensitivity mapping, interpolation, shared analysis state.cookbooks/— Focused API cookbooks (model, result, samples, latent variables, …).plot/— Plotting search results (dynesty, emcee, nautilus, zeus, GetDist).simulators/— Scripts that simulate the example datasets fitted throughout.
notebooks/— Jupyter notebook versions, generated fromscripts/(do not edit directly).config/— PyAutoFit configuration YAML files (config/general.yamlcontrols search update intervals, output, logging, profiling, parallel warnings).dataset/— Example 1D datasets.output/— Non-linear search results (generated at runtime, not committed).
There is no projects/ directory.
Scripts are run from the repository root so relative paths to dataset/, config/, and
output/ resolve correctly:
python scripts/overview/overview_1_the_basics.pyThere is currently no start_here.py in this workspace — scripts/overview/overview_1_the_basics.py
is the canonical entry point and the always-current end-to-end reference. (The runner still honours
the convention: if a folder contains a start_here.py, it executes that first, before other
scripts and subfolders, since some scripts depend on results it produces.)
import autofit as af
import autofit.plot as apltFor the canonical workflow (compose a model → configure a search → define an analysis → fit →
inspect results), read scripts/overview/overview_1_the_basics.py — it is kept current with the API.
On CI, every PR is gated by three workflows on Python 3.12 and 3.13: smoke_tests.yml (the
smoke runner below — the definition of green), navigator_check.yml (PyAutoHands's reusable
navigator-catalogue check; see Notebooks vs Scripts), and url_check.yml (link checking). The
smoke and navigator jobs check out PyAutoHands as a sibling and run the PyAuto* libraries from
the same-named branch of each source repo, so a workspace PR is validated against matching
library branches.
Scripts are tested with the smoke runner, run from the repo root — it executes the curated subset:
python .github/scripts/run_smoke.pyIt is driven by smoke_tests.txt (scripts) and smoke_notebooks.txt (notebooks) in the workspace
root, with per-entry environment from config/build/env_vars.yaml. It prints a [PASS] /
[FAIL (exit N)] line per entry, ends with a === Smoke test summary: P/T passed === line, and
exits non-zero if any entry failed.
PYAUTO_TEST_MODE is PyAutoFit's own environment variable: it tells the non-linear search to skip
its actual sampling, turning a run into a fast structural / end-to-end check that the model composes
and the script runs to completion — without paying for inference. A script that fails under it
signals a real problem (broken import, renamed API, etc.). PYAUTO_TEST_MODE_SAMPLES=<N> (default 4)
additionally sets how many fake samples the bypassed search writes — raise it (e.g. 10000) when a
run's samples.csv must be size-representative of real sampling, e.g. for resume/load profiling.
If numba or matplotlib cannot write to their default cache locations, point them at writable
directories:
NUMBA_CACHE_DIR=/tmp/numba_cache MPLCONFIGDIR=/tmp/matplotlib python scripts/overview/overview_1_the_basics.pyNotebooks in notebooks/ are generated from the .py files in scripts/. Always edit the
.py scripts, never the .ipynb notebooks directly. The # %% markers alternate between code
and markdown cells.
After updating scripts, regenerate the notebooks using the PyAutoHands tool (run from the workspace root):
pip install ipynb-py-convert
git clone https://github.com/PyAutoLabs/PyAutoHands.git ../PyAutoHands
PYTHONPATH=../PyAutoHands/autobuild python3 ../PyAutoHands/autobuild/generate.py autofitCommit the regenerated notebooks alongside the script changes. The /generate_and_merge skill
automates build + commit + PR + merge.
When editing the same region across many scripts in one pass (adding a section, renaming a symbol, updating an import block), only rewrite the targeted region. Never produce a whole-file write unless you have read the entire current contents of that file — a whole-file write based on a header skim silently deletes every section below the header. Prefer targeted edits.
PyAutoFit is domain-agnostic, so there is no single science field to reference. Any "context" for its examples is statistical / methodological — Bayesian inference, priors, non-linear search, model comparison — not a scientific subject. Do not graft lensing, galaxy, or other domain concepts onto this workspace.
PyAutoFit sits near the base of the PyAuto stack (all on the PyAutoLabs GitHub org):
- https://github.com/PyAutoLabs/PyAutoNerves — configuration handling (the
autonervesdependency). - https://github.com/PyAutoLabs/PyAutoFit — this library: model composition + non-linear search.
- https://github.com/PyAutoLabs/PyAutoHands — notebook generation + CI.
- https://github.com/PyAutoLabs/PyAutoGalaxy — downstream science library built on PyAutoFit.
- https://github.com/PyAutoLabs/PyAutoLens — downstream science library built on PyAutoFit.
- https://github.com/PyAutoLabs/HowToFit — tutorial lecture series that teaches statistical model-fitting and Bayesian inference with PyAutoFit from first principles; the starting point for beginners new to the framework.
For local development these are typically cloned as siblings of this repo (../PyAutoFit,
../PyAutoNerves, ../PyAutoHands, …).
When assigned an issue titled [API Update]:
- Read the PR diff in the issue body. Identify every renamed, moved, removed, or changed public API (functions, classes, method signatures, parameter names, import paths).
- Search all
.pyfiles inscripts/for usages of the old API. - Update each file to the new API, preserving existing behaviour, docstrings, and comments.
- Run
python .github/scripts/run_smoke.pyfrom the repo root to test the curated subset. - Read the
[FAIL (exit N)]output and fix the affected scripts. - Repeat 4–5 until the suite is clean.
- If a script cannot be fixed (ambiguous change, missing dependency), leave it unchanged and list it in the PR description under "Could not update" with the reason.
- After all scripts pass, regenerate the notebooks (see "Generating notebooks").
When assigned a general (non-API) issue:
- Read the issue description and any linked plan or AI prompt.
- Identify which scripts need to be created or modified.
- Only edit files in
scripts/. Never editnotebooks/directly. - Preserve all docstrings, comments, and tutorial explanations.
- Test with
python .github/scripts/run_smoke.pyafter changes. - Regenerate notebooks after all scripts pass.
When opening your PR, include:
- A summary of what changed and why.
- A list of all scripts you updated or created.
- Confirmation that notebooks were regenerated.
- A "Could not update" section for any scripts that still fail, with the error and your assessment.
Never rewrite pushed history on any repo with a remote — no git init over a
tracked repo, no force-push to main, no fresh-start "Initial commit", no
filter-repo / filter-branch / rebase -i on pushed branches. To get a
clean tree: git fetch origin && git reset --hard origin/main && git clean -fd.