Developer’s corner
NRV is a framework designed by and for the scientific corner. Behind the open source license, we are also more than welcome anyone that would genuinely contribute to our effort of gathering in-silico models for the nervous system in general.
Here are some guidelines for clean implementation of novel functionalities and contributions.
- We welcome different types of contributions:
- Report Bugs: Report bugs here:. When reporting a bug, please include:
Your operating system name and version.
Any details about your local setup that might be helpful in troubleshooting.
Detailed steps to reproduce the bug.
Fix Bug: Look through the GitHub issues for bugs. Anything tagged with “bug” and “help wanted” is open to whoever wants to implement it.
Implement Feature: Look through the GitHub issues for features. Anything tagged with “enhancement” and “help wanted” is open to whoever wants to implement it. Those that are tagged with “first-timers-only” is suitable for those getting started in open-source software.
Contribution - forking and Pull-Requests
Here is how to setup NRV for local development:
Fork the NRV repo on GitHub. If you want to be part of the NRV team contact us on the forum NRV or Github
Clone your fork locally:
git clone git@github.com:your_name_here/NRV.git
We recommend using a conda environment, to ease the installation of FenicsX. However, a virtualenv should be possible. Assuming you are using a conda environment this is how you set up you development configuration:
conda activate nrv-env
cd NRV
source bash_nrv
Create a branch for local development:
git checkout -b name-of-your-contribution
You should be able to make changes locally
Once changes are made, you should use the test interface (see bellow for details) to lint and test your code.
The historical scientific test launcher remains available:
cd tests
./NRV_test --syntax
./NRV_test --all
In parallel, the automation-friendly pytest suite can be used from the repository root:
pytest test
pytest test/unit
pytest test/e2e
pytest test/deployment
If you add a new functionality, you should add one or several tests, showing that your method works. The test should not raise any exception and should verify known, recognized or easily understable values to demonstrate the scientific reasoning. If it refers to a scientific publication, the citation should be included in the test file as python comment.
Please do not forget to update the documentation if your changes imply knowledge from the end user. The requirements for documentation compilation are listed in the following section.
Commit your changes and push your branch to GitHub:
git add -A
git commit -m "Your message containing a description of contribution and changes"
git push origin name-of-your-contribution
- In brief, commit messages should follow these conventions:
Always contain a subject line which briefly describes the changes made. For example “Update CONTRIBUTING.rst”.
Subject lines should not exceed 50 characters.
The commit body should contain context about the change - how the code worked before, how it works now and why you decided to solve the issue in the way you did.
Submit a pull request through the GitHub website.
NRV documentation
Important
To ensure the usability of NRV, it is important to make sure that all changes made to the source code are documented before any merge.
- NRV documentation is built using Sphinx. For consistent documentation, three main parts must be updated:
Generic explanations: .rst files gathered in
NRV/docs.Tutorials and Examples: .py files stored in
NRV/tutorialsandNRV/examples. Generated with sphinx_galleryAPI documentation: Docstrings in all source files, classes, and functions. Generated with autodoc
To compile the full documentation (1, 2, and 3), use a conda/mamba environment where you can import nrv.
See also
- Two method can be used to install such environment:
Additionally, a few dependencies must be installed:
pip install sphinx sphinx-rtd-theme furo Pygments sphinx-mdinclude sphinx_copybutton sphinx_gallery sphinx_codeautolink
Once installed, you can build the documentation with the following command from the base repository NRV/:
python3 -m sphinx.cmd.build -b html docs/ docs/_build/
Warning
Building the full documentation can take a long time, mainly due to 2. Tutorials and Examples and 3. API documentation.
If you want to rebuild the full documentation, you should first manually remove the generated files. This can be done by deleting the folders NRV/docs/_build/, NRV/docs/_nrv/, NRV/docs/exemple/, and NRV/docs/tutorial/.
Tip
- You can considerably speed up documentation generation by only rebuilding the required parts.
To skip rebuilding 2. Tutorials and Examples, keep the folders
NRV/docs/exemple/andNRV/docs/tutorial/.To skip rebuilding 3. API documentation, keep the folder
NRV/docs/_nrv/.
Note
NRV/docs/exemple/ and NRV/docs/tutorial/ are included by default in the git repository. If you want to rebuild 2. Tutorials and Examples, you need to manually remove these folders before compiling.
If your change does not involve tutorials or examples, you do not need to be in an environment able to import nrv. You only need the pip-installable dependencies listed in NRV/docs/requirements.txt:
pip install sphinx sphinx_rtd_theme furo Pygments sphinx_mdinclude sphinx_copybutton sphinx_gallery ipython sphinx_codeautolink numpy matplotlib
NRV testing
NRV currently relies on two complementary testing systems.
Tip
The legacy tests/ folder remains the scientific reference suite used during model development and validation.
The newer test/ folder contains the pytest-based suite designed for automation, selective execution, and CI/CD integration.
These two systems have different goals and must coexist.
In the sources of NRV, both testing folders are present:
NRV/
├── docker/
├── docs/
├── examples/
├── nrv/
├── test/
│ ├── deployment/
│ ├── e2e/
│ └── unit/
├── tests/
│ ├── deprecated_tests/
│ ├── dev_tests/
│ ├── unitary_tests/
│ └── NRV_test
Scientific testing
NRV is build with its own custom system for testing and validating new functionalities. This choice was made during the early development of the framework and is kept to ensure scientific reproducibility of results.
The tests/NRV_test file is a script that acts as a test launcher. It should be called from the command line using:
cd tests
./NRV_test
- This script can test the installation and dependencies, test the syntax and trigger linters or launch unitary tests. The following options are possible:
“-d”, “–dependances”: Check NEURON and COMSOL installation
“-l”, “–list”: Print the name of all unitary tests, an optional integer can be added to arguments to specify the number of columns used to print
“-f”, “–find”: Select only tests containing one or multiple substrings
“-u”, “–unitary_tests”: Launch all unitary tests, test result figures are saved in ‘./unitary_test/figures’ folder, all the tests should be True, numerical values for debug only
“-s”, “–syntax”: Lint nrv syntax source code
“-a”, “–all”: launches even potentially failing tests due to third party softwares such as COMSOL
“-t”, “–target”: ID of the tests to simulate, if a digit is replaced by ‘_’ all the tests
“-F”, “–fenics”: Launch all and only FEniCS related tests
“-C”, “–comsol”: Launch all and only COMSOL related tests
Note that running all scripts without errors and with all prints set to ‘True’ (no ‘False’) is a necessary condition for a PR to be accepted. If errors occurred, the list of failed tests will be saved in the file tests/unitary_tests/log_NRV_test.txt.
All code sources for the unitary tests can be found in the tests/unitary_tests/ folder. Additional development scripts are stored in tests/dev_tests/ and deprecated scripts are kept in tests/deprecated_tests/. Tests are organized in groups and subgroups as follows:
Starting Number |
Ending Number |
Function tested |
|---|---|---|
001 |
001 |
General architecture |
002 |
041 |
Basic functionalities: axon models simulation intracellular contextual and analytical extracellular context |
050 |
059 |
Fascicular related functions and basic multiprocessing functionalities |
060 |
065 |
COMSOL FEM model |
066 |
071 |
Various |
072 |
079 |
Save and load functionalities: electrode footprints, axon, fascicle |
080 |
083 |
Analytical recorders |
084 |
087 |
Save and load contexts and recorders |
088 |
089 |
Various functions |
090 |
099 |
Conductivity recorders |
100 |
145 |
FEniCS FEM models and GMSH meshes creator functions |
150 |
151 |
Compare FEniCS and COMSOL FEM models |
200 |
225 |
Optimization functions |
250 |
275 |
Wrappers and decorators |
300 |
349 |
Nerve functions |
350 |
399 |
Geometries and axon population |
500 |
550 |
Various functions |
900 |
950 |
Machine and autoconfig |
Pytest testing for CI/CD
In parallel with the scientific validation suite, NRV now includes a pytest-based structure in test/.
This second suite is intended for automation and continuous integration. Its role is to check that representative workflows run without error and produce results, while keeping the computational cost moderate enough for repeated execution.
The pytest suite is organized into three families:
unit: short API-focused tests, object construction checks, save/load smoke tests, and lightweight helper validation
e2e: strategic end-to-end workflows such as axon, fascicle, nerve, stimulation, threshold, FEniCS, and EIT smoke simulations
deployment: runtime, import, backend, and multiprocessing sanity checks
This suite intentionally excludes COMSOL and focuses on NEURON- and FEniCS-compatible workflows.
Typical commands are:
pytest test
pytest test/unit
pytest test/e2e
pytest test/deployment
Tests can also be selected with markers:
pytest -m unit
pytest -m e2e
pytest -m deployment
pytest -m fenics
pytest -m "not slow"
The pytest markers are registered in test/conftest.py. This makes it possible to select one family of tests in isolation, which is especially useful for future CI/CD workflows and local debugging.
At the current stage, the pytest suite is meant to complement the legacy scientific tests rather than replace them:
the
tests/folder remains the reference for detailed scientific validationthe
test/folder provides a maintainable and automation-friendly entry point for quick regression checks
CI/CD delivery pipeline
The NRV repository now uses a branch-driven delivery model designed to keep day-to-day development simple while making releases repeatable and auditable.
The target flow is the following:
feature branch
|
v
dev --PR--> staging --auto promotion PR--> master
|
v
TestPyPI + deployment test
The three long-lived branches have distinct roles:
dev: integration branch used by developers and feature pull requestsstaging: release-candidate branch used to validate a build before public publicationmaster: publication branch used only for official releases and deployment artefacts
This organization reflects the intended process previously summarized in the internal workflow diagrams:
on
dev: version bump, linting, and routine development validationon
staging: unit tests, end-to-end tests, TestPyPI publication, and deployment validationon
master: PyPI publication, documentation publication, Docker image build, and GitHub release creation
Workflow architecture
The pipeline is split into two categories of GitHub Actions workflows.
Reusable step workflows
Reusable workflows perform one technical operation and are called through workflow_call. They are meant to stay small and focused.
Current reusable steps are:
step_linter.ymlstep_bump_version.ymlstep_pytest-unit.ymlstep_pytest-e2e.ymlstep_testpypi_release.ymlstep_pytest-deployment.ymlstep_pypi_release.ymlstep_prebuild_docs.ymlstep_publish_staging_docs.ymlstep_docker-image.ymlstep_create_release.yml
Branch orchestration workflows
Coordination workflows are the only workflows directly triggered by GitHub events at branch level. They call the reusable steps in the correct order.
The coordination workflows are:
coordination_dev.ymlcoordination_staging.ymlcoordination_master.yml
This split has two benefits:
the delivery logic stays readable
each technical step can be reused or tested independently
Pipeline behavior by branch
dev
The dev branch is the integration branch for everyday development.
Expected usage:
each developer works on a short-lived feature branch
a pull request is opened toward
devthe
coordination_devworkflow runslinting and unit tests must pass before merge
A manual version bump can also be triggered on dev through workflow_dispatch when the team decides that the next integration cycle should target a new semantic version.
Typical checks on dev:
black formatting check
pytest unit suite
optional manual semantic version bump
staging
The staging branch is the release-candidate qualification branch.
Expected usage:
once the team considers
devready, open a PR fromdevtostagingthe PR to
stagingruns the qualification checksafter merge to
staging, the full release-candidate pipeline is triggered automatically
The post-merge pipeline on staging is:
run the pytest unit suite
run the pytest e2e suite
build and publish the package to TestPyPI
install that candidate package from TestPyPI
run deployment tests against the published candidate
create or update a promotion PR from
stagingtomasterenable auto-merge on that promotion PR if repository policy allows it
This branch is intentionally protected but still allows intervention from a core maintainer if the pipeline stops after publication to TestPyPI and a fix is needed.
master
The master branch is the publication branch. Humans should not work there directly.
Expected usage:
stagingis promoted intomasterthe
coordination_masterworkflow computes the release tag frompyproject.tomlthe release tag is created if missing
the package is published to PyPI
the documentation for
latestis rebuilt and publisheda GitHub release is created
the Read the Docs
stagingand tagged versions are activated and builtDocker images are built and pushed
This means that all public artefacts originate from the same validated code state.
How to use the pipeline as a developer
For most contributors, the expected process is straightforward:
create a branch from
devimplement the change
add or update tests in
test/and, when relevant, intests/update the documentation
open a PR to
devfix lint or unit failures if the workflow reports any problem
Only release managers or core maintainers usually need to interact with staging and master.
For a release cycle, the team should:
decide that
devis readyopen a PR from
devtostaginglet the
stagingpipeline publish and validate the candidatereview the automatically created promotion PR to
masterallow the publication pipeline to complete
Local reproduction of CI steps
The CI workflows mirror commands that can also be run locally.
Linting:
black --check --verbose ./nrv
Unit tests:
pytest test/unit -q
End-to-end tests:
pytest test/e2e -q
Deployment tests:
pytest test/deployment -q
Documentation build:
python -m sphinx.cmd.build -b html docs/ docs/html/
A release manager may also inspect the package locally before publication:
python -m pip install --upgrade build
python -m build
Rulesets and protections
The repository should define GitHub rulesets consistent with the branch model.
Recommended protections are:
dev:pull request required
at least one approval
required checks:
lintandunitno force push
no direct human push
staging:pull request required
one or two approvals depending on team policy
required checks on PR:
unitande2erestricted direct push for release managers only
no force push
no branch deletion
master:pull request required
no direct human push
linear history
no force push
release and deployment only
- tags
v*: protected creation
no deletion
no retagging
- tags
Secrets, environments, and runners
The pipeline depends on a small set of external credentials:
TEST_PYPI_API_TOKENPYPI_API_TOKENRTD_TOKENDOCKER_USERNAMEDOCKER_PASSWORD
Recommended GitHub environments are:
testpypipypidockerhub
The e2e and documentation steps rely on a self-hosted runner because they are heavier and depend on the NRV scientific stack.
That runner must remain healthy, updated, and able to provision the conda environments used by the workflows.
Operational notes
A few practical points are important for maintainers:
stagingmust exist as a long-lived branch before enabling the pipelineall
step_*workflows are reusable and should remain event-agnosticbranch logic belongs in
coordination_*workflows onlythe package version in
pyproject.tomlis the source of truth for release tagsa failed promotion from
stagingtomastershould be fixed onstagingand rerun, not patched onmaster
This architecture is intentionally conservative: it favors reproducibility, explicit promotion steps, and clean traceability of release artefacts.
Make a release
The release process is now branch-driven and largely automated.
For maintainers, the practical sequence is:
Make sure
devcontains the intended changes.Trigger a version bump on
devif a new semantic version is required.Open and merge a PR from
devtostaging.Let the
stagingpipeline qualify the candidate through unit tests, e2e tests, TestPyPI publication, and deployment checks.Review the automatically created promotion PR from
stagingtomaster.Let the
masterpipeline publish the final artefacts.
The public artefacts generated from master are:
a release tag
vX.Y.Za package on PyPI
a GitHub release
updated Read the Docs versions
Docker images tagged with
latestandvX.Y.Z
Public roadmap
NRV is developed for the research and education community. We hope to provide a tool for biomedical engineering, and provide a framework that is as open as possible, to ensure scientific communication and reproducibility.
NRV is certainly not perfect, and we hope that the open-science approach can contribute to improve the framework, however ensuring retrocompatilibty. There is a continuous effort from the Bioelectronics group of the IMS Laboratory (U. Bordeaux, Bordeaux INP, CNRS UMR 5218) to continue to develop NRV, and some purely scientific objectives are linked to this project. Here is a list of non-scientific and mostly technical objectives, that we intend to develop and on which we are also extremely happy to get help or guiding if you want to contribute:
- Improving geometry:
Enable axon tortuosity for axons.
Enable elliptical shapes for fascicles and nerves (with automatized population filling and basic operations as already developed for round shapes fascicles/nerves).
Integrate mode complex shapes based on histology and image segmentation (with automatized population filling).
Extend FenicsX computation with curvilinear coordinates, to enable non-extruded 3D models of fascicles.
Add electrode daughter-classes for more specific electrode geometries.
Improving recordings: current recording simulation is based on analytical field computation, thus restricting to one material between fibers and recording points. Such computations have already been performed with FEM and should be integrated in NRV
Objects for fiber-populations: generation and packing are based on functions, we hope to change to objects to ease the way of script ex-novo population production
- Post-processing options:
provide automatic link between FEM computation results and Paraview
provide basic integration of Pyvista and Matplotlib to ease results exploration
design wrapper and decorators with simulations to ease systematic tasks in results post-processing
Compatibility and marking of results: provide automated tagging of objects with version and develop routines for versions checking.