Metadata-Version: 2.4
Name: autonerves
Version: 2026.10.4.1
Summary: PyAuto Configration
Author-email: James Nightingale <James.Nightingale@newcastle.ac.uk>, Richard Hayes <richard@rghsoftware.co.uk>
License: MIT
Project-URL: Homepage, https://github.com/PyAutoLabs/PyAutoNerves
Keywords: cli
Classifier: Intended Audience :: Science/Research
Classifier: Topic :: Scientific/Engineering :: Physics
Classifier: Natural Language :: English
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Requires-Python: >=3.12
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: typing-inspect>=0.4.0
Requires-Dist: PyYAML>=6.0.1
Requires-Dist: numpy<3.0.0,>=1.24.0
Requires-Dist: jax<0.12.0,>=0.7.0; sys_platform != "darwin" or platform_machine == "arm64"
Requires-Dist: jaxlib<0.12.0,>=0.7.0; sys_platform != "darwin" or platform_machine == "arm64"
Requires-Dist: jaxnnls==1.0.1; sys_platform != "darwin" or platform_machine == "arm64"
Provides-Extra: jax
Provides-Extra: optional
Requires-Dist: autonerves[jax]; extra == "optional"
Requires-Dist: astropy>=5.0; extra == "optional"
Provides-Extra: test
Requires-Dist: pytest; extra == "test"
Provides-Extra: dev
Requires-Dist: pytest; extra == "dev"
Requires-Dist: black; extra == "dev"
Dynamic: license-file

<p align="center">
  <img src="logo.png" alt="PyAutoNerves" width="400">
</p>

# PyAutoNerves

[![PyAutoScientist GitHub](https://img.shields.io/badge/%E2%9A%97%EF%B8%8F%20PyAutoScientist-GitHub-181717?style=flat-square)](https://github.com/PyAutoLabs/PyAutoScientist) [![PyAutoScientist ReadTheDocs](https://img.shields.io/badge/%F0%9F%93%96%20PyAutoScientist-ReadTheDocs-8CA1AF?style=flat-square)](https://pyautoscientist.readthedocs.io)

**PyAutoNerves is the Nerves of the PyAutoScientist** — the configuration,
serialization, and I/O foundation (package `autonerves`) connecting the
workspace's conventions to every library. It provides a layered configuration
system with workspace overrides, dict / JSON / CSV serialization of arbitrary
objects, and FITS I/O.

`PyAutoFit`, `PyAutoArray`, `PyAutoGalaxy`, and `PyAutoLens` all depend on
autonerves: it supplies their packaged default config, the object-serialization
used to persist models and results, and shared utilities (`test_mode`,
`jax_wrapper`). Centralising these here keeps a single, consistent config and
I/O layer beneath every library. As a released library it ships with every
nightly train — see the
[PyAutoHands release board](https://pyautolabs.github.io/PyAutoHands/) for the
current version.

## Install

```bash
pip install autonerves
```

## Examples

Layered config — read a directory of YAML into a queryable `Config`:

```python
from autonerves.conf import Config

config = Config("path/to/config")          # directory of YAML files
value = config["general"]["model"]["section"]["value"]
```

JSON serialization — round-trip arbitrary Python objects:

```python
from autonerves.dictable import output_to_json, from_json

data = {"sersic_index": 4.0, "centre": [0.0, 0.0]}
output_to_json(data, "model.json")
restored = from_json("model.json")         # == data
```

FITS I/O — write and read a NumPy array:

```python
import numpy as np
from autonerves.fitsable import output_to_fits, ndarray_via_fits_from

arr = np.arange(12.0).reshape(3, 4)
output_to_fits(values=arr, file_path="demo.fits", overwrite=True)
loaded = ndarray_via_fits_from(file_path="demo.fits", hdu=0)   # np.allclose(arr, loaded)
```

## Nerves board

**<https://pyautolabs.github.io/PyAutoNerves/>** — a read-only browser of every
config file and option across the organism: each library's `<package>/config/`
(PyAutoFit, PyAutoArray, PyAutoGalaxy, PyAutoLens, PyAutoCTI) and each
workspace's `config/` that overrides them.

- **Per repo** (`repos/<Repo>.html`): every YAML file with its top-level keys,
  its source line-numbered with the comments kept (the comments *are* the
  option docs) and a GitHub link; prior files render as a table
  (Class · param · type · mean/σ or bounds · width modifier · limits).
- **Search**: the index page's box searches every key, file and comment
  across all repos and jumps to the line.
- **Override map**: autonerves resolves a key workspace → last-imported
  library → … → PyAutoFit (`Config.push(keep_first=True)`, keys lowercased),
  so each workspace file is compared, by relative path, against the same file
  across its library stack in that order (lens → galaxy → array → fit; cti →
  array → fit). Keys whose value differs, keys no library defines (*orphans*)
  and keys that fall through to the libraries are listed per file.
  `build/*.yaml` is workspace tooling and is grouped apart.
- **Possibly unused config keys**: each library's Python (and autonerves'
  own) is scanned for `conf.instance[...]` lookups, and every key of a
  library settings file is classed *used* (a lookup reads it, or reads a key
  under it — PyAutoLens reading a PyAutoFit key counts, since autonerves
  merges every layer), *section-read* (a lookup reads an ancestor section
  whole, or a non-literal subscript such as `["plots"][section][name]` ends
  the chain above it) or *unused* (nothing references it). Unused keys get a
  chip on the repo page, per-file counts and an index section grouped by
  library with GitHub links. Prior files are exempt (looked up by class name).
  **Limits:** the scan is static — it follows literal subscript chains
  (including multi-line ones and `.get("k")`), sections bound to a local and
  indexed later in the same function or a closure, and the `should_output`
  helper; a key read any other way (built key strings, `getattr`, a section
  passed to another function and indexed there) shows as section-read at
  best and may show as unused. Treat the list as candidates, not a verdict.
- **Environment variables**: the `PYAUTO_*` switches autonerves reads.
- **Cockpit feed** (`state.json`): green when every file parses and no
  workspace key is orphaned; yellow with one item per unparseable file or
  orphan-carrying workspace file; grey when nothing was collected. Never red.
  Possibly unused keys add one *info* item per library — never yellow, until
  the scan is trusted.

Rendered daily by [`.github/workflows/nerves_board.yml`](.github/workflows/nerves_board.yml)
from sparse checkouts of the config folders (plus each library's package
`.py` files, for the lookup scan); the renderer is
[`scripts/board.py`](scripts/board.py) (not part of the `autonerves` package).
Nothing on the board edits config.

## Links

- Source & tests: [`autonerves/`](autonerves), [`test_autonerves/`](test_autonerves)
- Agent/contributor instructions: [`AGENTS.md`](AGENTS.md)
- The organism this repo is the Nerves of:
  [PyAutoBrain/ORGANISM.md](https://github.com/PyAutoLabs/PyAutoBrain/blob/main/ORGANISM.md),
  documented in full at <https://pyautoscientist.readthedocs.io>
- Ecosystem: [PyAutoLabs on GitHub](https://github.com/PyAutoLabs)
