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
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,5 @@ jobs:
run: make test-quiet PYTHON=python
env:
MPLBACKEND: Agg
# Optional repo secret; live-brain tests skip when it is empty.
NEUPRINT_APPLICATION_CREDENTIALS: ${{ secrets.NEUPRINT_TOKEN }}
5 changes: 4 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
examples example-basic example-connectome example-navigation example-gui \
example-gui-smoke figures \
cli-list cli-simulate cli-simulate-offline cli-train cli-train-offline \
test-neuprint test-all
test-neuprint test-live test-all

PYTHON := .venv/bin/python
PIP := .venv/bin/pip
Expand Down Expand Up @@ -118,6 +118,9 @@ cli-train-offline: ## Train with synthetic brain (no token needed)

# ── neuPrint (requires token) ─────────────────────────────────────────────

test-live: ## End-to-end pytest against the real brain (needs token)
$(PYTEST) tests/test_live_brain.py -q

test-neuprint: ## Test real neuPrint mini brain fetch + simulate
ifndef NEUPRINT_APPLICATION_CREDENTIALS
$(error NEUPRINT_APPLICATION_CREDENTIALS not set. Create .env or export it)
Expand Down
4 changes: 2 additions & 2 deletions src/flynet/jax_trainer.py
Original file line number Diff line number Diff line change
Expand Up @@ -613,7 +613,7 @@ def train_navigation(
total = time.time() - t0
print(
f"\nTraining complete: {episodes} episodes in {total:.1f}s "
f"({total / episodes:.2f}s/ep)"
f"({total / max(episodes, 1):.2f}s/ep)"
)
final_sr = log.episode_success_rate[-1] if log.episode_success_rate else 0.0
print(f"Final success rate (10-ep window): {final_sr:.0%}")
Expand Down Expand Up @@ -1259,7 +1259,7 @@ def train_navigation(
total = time.time() - t0
print(
f"\nTraining complete: {episodes} episodes in {total:.1f}s "
f"({total / episodes:.2f}s/ep)"
f"({total / max(episodes, 1):.2f}s/ep)"
)
final_sr = log.episode_success_rate[-1] if log.episode_success_rate else 0.0
print(f"Final success rate (10-ep window): {final_sr:.0%}")
Expand Down
37 changes: 37 additions & 0 deletions tests/test_live_brain.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
"""End-to-end check against the real neuPrint hemibrain/CNS data.

Skipped unless NEUPRINT_APPLICATION_CREDENTIALS is set, so offline CI stays
hermetic. Run with ``make test-live``.
"""

import os

import numpy as np
import pytest

from flynet import ConnectomeLoader, SpikingNetwork

pytestmark = pytest.mark.skipif(
not os.environ.get("NEUPRINT_APPLICATION_CREDENTIALS"),
reason="needs a neuPrint token",
)


@pytest.fixture(scope="module")
def real_net(tmp_path_factory):
# Fresh cache dir so this really hits the server rather than a stale file.
loader = ConnectomeLoader(cache_dir=str(tmp_path_factory.mktemp("cache")))
ids, edges, motors = loader.load_or_fetch_mini(neuron_type="DNge104")
assert loader.last_source == "neuprint"
return SpikingNetwork(ids, edges, motor_ids=motors)


def test_real_brain_loads(real_net):
assert len(real_net.ids) > 10
assert len(real_net.motors) == 2


def test_real_brain_settles_to_finite_motor_output(real_net):
real_net.settle(z_right=2.0, z_left=0.5)
drv, _ = real_net.turn(rho_right=2.0, rho_left=0.5)
assert np.all(np.isfinite(drv))
Loading