Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ extensions/cmake-build-debug
BrainPyExamples/
BrainModels/
book/
docs/examples
# Maintained examples are source; only their generated outputs are ignored.
/docs/examples/**/generated/
/docs/examples/**/artifacts/
docs/apis/jaxsetting.rst
docs/quickstart/data
examples/recurrent_neural_network/neurogym
Expand Down
46 changes: 38 additions & 8 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,7 @@ Biologically detailed brain cell modeling in BrainX.
5. Every correction: reflect on the mistake, plan to avoid repeating it.
6. All updates must be happened on the worktree branch, not main.
7. Use `brainstate.random` instead of `jax.random` directly for all random number generation.
8. **All durable prose lives under `docs/`; never leave a stray `.md` inside `braincell/`.** Two homes, each with a filename rule:
- `docs/specs/YYYY-MM-DD-<slug>.md` — the spec and plan for one change, written *before* implementation. The date prefix is the creation date, so the directory reads chronologically.
- `docs/design/<topic>.md` — durable design notes, invariants, and architecture maps that outlive any single change. Group a multi-document topic in its own subdirectory (`docs/design/network/`).

Name a file for what it documents, not where the code happens to sit: `io-swc-reader-invariants.md`, never `README.md` or `notes.md`. Give it an `# H1` that matches.
- Explicit exception: an unstable experiment directory under `examples/experimental/` may contain one local `README.md` that maps the files, status, commands, and historical context for that directory. It must not define public API or duplicate durable design/results prose; link to `docs/` and generated artifacts for those.
8. **Check design, implementation, and relevant examples before each commit.** Review only the scope of that commit across `docs/design/`, implementation and tests, and the actual related examples (including root `examples/`). Routine development does not require synchronizing these three after every edit or task. `docs/examples/` is not a mandatory parallel maintenance destination. `docs/specs/` is a chronological historical archive, not the current contract or a required pre-implementation deliverable. Follow [Design, code, and examples](#design-code-and-examples) below.
9. Tests should >90% coverage, but focus on meaningful tests that cover edge cases and critical paths, not just trivial lines.
10. Co-locate tests with the code under test: each module `foo.py` has its tests in a sibling `foo_test.py` (suffix style — never a separate `tests/` directory, never the `test_*.py` prefix). See [Testing](#testing) for the full rule.
11. **Never drive a model with a bare Python `for`/`while` loop when it runs repeatedly.** Python loops execute op-by-op (dispatch overhead, no fusion) and trace fresh each step; the `brainstate.transform` primitives lower the whole loop into one compiled XLA program, tracing the body only once. Pick by shape of the work:
Expand All @@ -30,18 +25,53 @@ Biologically detailed brain cell modeling in BrainX.
13. **Every tracked `.py` file opens with the Apache-2.0 license header — add it when you create the file.** It goes at the very top, above the module docstring, below only a shebang or PEP 263 encoding line. See [License header](#license-header) for the verbatim block.


## Design, code, and examples

All paths below are relative to the repository root (`/home/swl/braincell` in the current workspace).

| Location | Maintained responsibility |
| --- | --- |
| `docs/design/` | Current design, interface contracts, module discussions, and implementation direction. |
| `braincell/` | Implementation and co-located tests. |
| Actual related examples, including root `examples/` | Usage examples relevant to the commit, kept at their existing locations. No duplicate or migration to `docs/examples/` is required. |

Before each commit, review the relevant design, implementation and tests, and actual related examples once for the scope being committed. Routine development may leave these temporarily out of sync; no cross-document synchronization check is required after each edit or task. At the commit check, update affected interfaces, behavior descriptions, and example usage as needed. No-impact files need no edits. For behavior changes being committed, run the relevant code tests and affected examples; report what was checked and any unverified gaps. A discovered mismatch must be fixed within scope or recorded in the module document with a concrete follow-up; do not claim full consistency while a gap remains. This is a review requirement, not a new automatic Git hook.

Design may lead implementation. Clearly distinguish implemented, partially implemented, planned, and research content. Executable examples must use implemented interfaces; proposed syntax belongs in explicitly marked design discussions. A documentation-only proposal does not require implementing the feature or adding an example of an unavailable API.

### Module documents and project progress

Human contributors start with [CONTRIBUTING.md](CONTRIBUTING.md) and the
[Developer Guide](docs/developer/index.rst). Developer pages explain contribution
steps and link to Design for module contracts, formulas, and architecture.

See the [Repository organization guide](docs/repository.md) for directory responsibilities,
content placement, and the proposed layout awaiting migration confirmation.

Follow [Design documentation rules](docs/design/AGENTS.md) when writing or updating `docs/design/`.
That directory-level guide owns writing style, module layout, document roles, and task status definitions.
Keep durable design prose under `docs/design/`, with implementation references linking to the relevant document.

### History and deferred documentation

- `docs/specs/YYYY-MM-DD-<slug>.md` preserves historical decisions and change records in creation-date order. Add a record when the history is useful; no new spec is required before every implementation.
- Current decisions and active plans live in `docs/design/`. Do not continually rewrite old specs to match new interfaces or use historical requirements to override current module documents. Old paths in historical records can remain historical references.
- Other documentation trees under `docs/`, including `docs/examples/`, are not mandatory parallel maintenance destinations. Select examples by their relevance to the commit, not by a required directory. Do not create duplicate examples, migrate them into `docs/examples/`, or bulk-refresh unrelated documentation or examples unless requested. This does not claim that all existing files are already consistent.
- Example-specific import progress, comparison settings, and validation work belong alongside the relevant examples (for example, `examples/neuron_compare/cerebellum-import-progress.md`). Reusable API and architecture contracts stay under `docs/design/` and are linked from the example record.
- The existing exception for an unstable `examples/experimental/` directory remains: one local `README.md` may map files, commands, status, and history, but must link to durable design/results prose under `docs/` rather than define public API or duplicate it.

## Quick Reference

```bash
# Install (dev)
pip install -e ".[testing]"
pip install -e ".[dev]"

# Run tests (tests are co-located with source code)
pytest braincell/

# Pre-commit
pre-commit install
pre-commit run --all
pre-commit run --all-files
```


Expand Down
213 changes: 14 additions & 199 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,206 +1,21 @@
# Contributing to `braincell`
# 参与贡献

Thank you for contributing to `braincell`.
BrainCell 接受问题报告、错误修复、新模型、文档和示例贡献。

This project provides biologically detailed brain cell modeling tools built on top of JAX and the BrainX ecosystem. Contributions are welcome across code, tests, documentation, examples, bug reports, and design discussions.
- **报告问题**:在 [Issues](https://github.com/chaobrain/braincell/issues) 提供最小复现、预期与实际结果,以及环境版本。
- **提出功能或设计改进**:先查看对应 [模块 TODO](docs/design/TODO.md),在 Issue 或 PR 中说明使用场景和方案取舍。
- **提交修改**:按照 [贡献流程](docs/developer/contributing.md) 配置环境、修改代码、验证结果并提交 PR。

By participating in this project, you agree to follow the guidance in [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md).
详细指南:

## Table of contents

- [Ways to contribute](#ways-to-contribute)
- [Development setup](#development-setup)
- [Running tests](#running-tests)
- [Code style](#code-style)
- [Project conventions](#project-conventions)
- [Building documentation](#building-documentation)
- [Pull requests](#pull-requests)
- [Reporting bugs and security issues](#reporting-bugs-and-security-issues)
- [License](#license)

## Ways to contribute

You can help by:

- reporting bugs or unclear behavior
- proposing new features or API improvements
- improving documentation and tutorials
- adding tests for uncovered behavior
- contributing bug fixes or new functionality
- improving examples under `examples/`

If you are planning a larger change, open an issue first so the scope and API impact can be discussed before implementation.

`docs/design/TODO.md` is the project design document. It tracks the architectural intent and the current implementation state of every subsystem, using `[x]` shipped / `[~]` partial / `[ ]` planned markers. Read the relevant section before starting substantial work, and update it when your change moves a subsystem forward.

## Development setup

`braincell` requires Python 3.11 or newer. Continuous integration currently tests Python 3.13 on Linux, macOS, and Windows, and a nightly matrix exercises JAX 0.8.0 through the latest release.

Create an isolated environment and install the package in editable mode with the development extras:

```bash
python -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip setuptools
python -m pip install -e ".[dev]"
```

On Windows PowerShell, activate the environment with:

```powershell
.venv\Scripts\Activate.ps1
```

Dependency groups are declared in `pyproject.toml` under `[project.optional-dependencies]`:

| Extra | Contents |
| 要做什么 | 阅读入口 |
| --- | --- |
| `vis` | `matplotlib`, `networkx`, `pyvista`, `plotly` — 2D and 3D visualization backends |
| `io` | `requests` — the NeuroMorpho.Org client |
| `all` | `vis` + `io`; everything a user-facing install might need |
| `testing` | `all` + `pytest`, `pytest-benchmark`, `hypothesis`, `absl-py` |
| `doc` | `all` + the Sphinx toolchain |
| `dev` | `testing` + `doc` + `pre-commit` |
| `cpu` / `cuda12` / `cuda13` / `tpu` | the matching JAX backend build; pick exactly one |

The `requirements*.txt` files are thin pointers to these extras and exist only for tooling that expects them (CI and Read the Docs). Add new dependencies to `pyproject.toml`, never to the `requirements*.txt` files.

Finally, install the git hooks:

```bash
pre-commit install
```

## Running tests

Run the test suite from the repository root:

```bash
pytest braincell/
```

Test discovery is configured in `pyproject.toml` under `[tool.pytest]`; it points at the `braincell` package and collects only `*_test.py` modules.

To run a single module or a single test:

```bash
pytest braincell/io/swc/reader_test.py
pytest braincell/io/swc/reader_test.py::SwcReaderTest::test_single_point_soma_expands_to_three_points_and_connects_at_midpoint
```

With coverage (configuration lives in `[tool.coverage]`):

```bash
pytest braincell/ --cov=braincell --cov-report=term-missing
```

On Windows, CI disables the fault handler. If you hit platform-specific issues locally, this is the closest CI-equivalent command:

```bash
pytest braincell/ -p no:faulthandler
```

Some suites skip themselves when an optional dependency is absent — `pytest-benchmark` for the performance baselines, `hypothesis` for the layout property tests, and `pyvista` / `plotly` for the 3D backends. Install the `testing` extra to run them.

When you change behavior, add or update tests in the same area of the codebase.

## Code style

Formatting and linting are handled by [ruff](https://docs.astral.sh/ruff/), configured in `pyproject.toml` under `[tool.ruff]` and run through pre-commit:

```bash
pre-commit run --all-files
```

The line length is 120. Quote style is set to `preserve`, so the existing mix of single and double quotes is left alone — do not reformat strings gratuitously.

The lint rule set is currently minimal on purpose. `[tool.ruff]`'s `lint.ignore` list enumerates the rules the tree still violates, each with its violation count and the reason it is deferred rather than fixed. If your change cleans up one of those categories, delete the corresponding entry in the same pull request.

## Project conventions

These are the conventions that reviewers will look for. `AGENTS.md` holds the full version; the essentials are:

**Units are mandatory.** Every public API that takes a physical quantity routes through `normalize_param()` in `braincell/_misc.py`, which rejects bare numerics with `TypeError`. Accept `python number / numpy array / jax array * brainunit unit`, store canonical SI internally, and hand values back with units attached — never raw floats.

```python
import brainunit as u

v_rest = -65.0 * u.mV # correct
v_rest = -65.0 # rejected with TypeError
```

**Tests are co-located and suffix-named.** Every module `foo.py` has its tests in a sibling `foo_test.py`. Never a separate `tests/` directory, and never the `test_*.py` prefix — `python_files` is set to `*_test.py` only, so a misnamed file is silently never run. Shared test helpers that are not themselves tests go in a leading-underscore module such as `_testing.py`.

**Docstrings are NumPy-style.** See `AGENTS.md` for the canonical section order. Examples must be `.. code-block:: python` blocks that are doctest-compatible and self-contained.

**Use `brainstate.random`,** not `jax.random` directly.

**Do not drive a model with a bare Python loop.** Use `brainstate.transform.for_loop` / `scan` (or the `checkpointed_` variants under autograd) so the loop lowers into a single compiled XLA program.

**Keep optional dependencies lazy.** `matplotlib`, `pyvista`, and `plotly` must be imported inside the backend that uses them, gated on `importlib.util.find_spec`, so that `import braincell` stays cheap.

**Support JAX >= 0.8.0.** Prefer feature or shape detection over hard version checks.

Write a spec under `docs/specs` before implementing a substantial change, so the design is available for reference during review.

## Building documentation

The documentation lives in `docs/` and uses Sphinx.

```bash
python -m pip install -e ".[doc]"
cd docs
make html
```

On Windows:

```powershell
cd docs
.\make.bat html
```

If you regenerate notebooks that contain interactive `vis3d(...)` output, also install the PyVista HTML export dependencies before running and saving those notebooks:

```bash
python -m pip install ipywidgets trame trame-vtk trame-vuetify "jupyterlab>=3"
```

Documentation includes Markdown, reStructuredText, and notebooks. Notebook execution is disabled in the Sphinx configuration, so documentation changes should focus on content correctness and importability. For static interactive PyVista output, use `vis3d(notebook=True, jupyter_backend="html")`; the PyVista backend exports raw iframe HTML for this backend so the published docs page does not need to load the Jupyter widget manager.

## Pull requests

Before opening a pull request:

1. make sure your branch is based on the latest target branch state
2. run `pre-commit run --all-files`
3. run the relevant tests locally
4. update documentation, examples, `docs/design/TODO.md`, or `changelog.md` if your change is user-facing
5. review the pull request template in `.github/PULL_REQUEST_TEMPLATE.md`

When opening a pull request, include:

- a clear description of the problem and the change
- links to any related issues
- the local test commands you ran
- notes about API changes, breaking changes, or follow-up work

Keep pull requests small and focused. Please keep the following in mind:

- keep public APIs and examples stable unless the change intentionally updates them
- avoid adding new dependencies unless they are clearly justified
- preserve compatibility with the supported Python versions declared in `pyproject.toml`

Draft pull requests are welcome for early feedback.

## Reporting bugs and security issues

- For general bugs, feature requests, and usability issues, open a GitHub issue: <https://github.com/chaobrain/braincell/issues>
- For security-related concerns, **do not open a public issue** — see [SECURITY.md](SECURITY.md) for the private reporting channels.

Please include enough detail to reproduce the problem: operating system, Python version, package versions, a minimal example, and the observed error or unexpected behavior.
| 找到相关代码与设计 | [代码与设计导航](docs/developer/project_layout.md) |
| 编写和运行测试 | [测试指南](docs/developer/testing.md) |
| 添加通道、离子、突触或积分器 | [扩展指南](docs/developer/extending.md) |
| 排查开发环境与构建问题 | [开发排错](docs/developer/troubleshooting.md) |

## License
Developer 说明贡献步骤,Design 维护模块的接口、架构和方案。仓库规则见 [AGENTS.md](AGENTS.md)。

By contributing to this repository, you agree that your contributions will be distributed under the same license as the project — Apache License 2.0. See [LICENSE](LICENSE).
参与协作请遵守 [行为准则](CODE_OF_CONDUCT.md)。安全问题通过 [安全报告渠道](SECURITY.md) 私下提交。
贡献采用项目的 [Apache-2.0 许可证](LICENSE)。
29 changes: 28 additions & 1 deletion braincell/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
hidden_state,
state_grouping,
)
from . import quad, mech, channel, synapse, ion, filter, morph, trainable
from . import quad, mech, channel, synapse, ion, filter, morph, reduction, trainable
from ._base_channel import (
Channel,
IonInfo,
Expand Down Expand Up @@ -78,6 +78,20 @@
VoltageCrossingSource,
)
from .network.recording import EventSeries, RecordingSchema, RecordingSpec, SampleBlock, observe
from .reduction import (
EventAccumulatorReduction,
PayloadAccumulatorReduction,
ReductionContext,
ReductionInputGroup,
ReductionInputGroupSchema,
ReductionInputs,
ReductionModel,
ReductionOutput,
ReductionSynapse,
ReductionView,
ReductionViewCollection,
SynapticKernelAccumulatorReduction,
)
from ._version import (
__version__,
__version_info__,
Expand Down Expand Up @@ -133,6 +147,7 @@
"DiffEqModule",
"DiffEqSingleState",
"DiffEqState",
"EventAccumulatorReduction",
"EventSequence",
"EventSeries",
"EventSource",
Expand All @@ -155,16 +170,27 @@
"NetworkResult",
"Node",
"NodeTree",
"PayloadAccumulatorReduction",
"PointPlacement",
"RecordingSchema",
"RecordingSpec",
"ReductionContext",
"ReductionInputGroup",
"ReductionInputGroupSchema",
"ReductionInputs",
"ReductionModel",
"ReductionOutput",
"ReductionSynapse",
"ReductionView",
"ReductionViewCollection",
"RunResult",
"SampleBlock",
"SineClamp",
"SingleCompartment",
"Soma",
"Synapse",
"SynapseView",
"SynapticKernelAccumulatorReduction",
"VoltageCrossingSource",
"__version__",
"__version_info__",
Expand All @@ -180,6 +206,7 @@
"network",
"observe",
"quad",
"reduction",
"state",
"state_grouping",
"synapse",
Expand Down
1 change: 1 addition & 0 deletions braincell/__init___test.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
"morph",
"network",
"quad",
"reduction",
"synapse",
"trainable",
"vis",
Expand Down
Loading