Добавил запуск конвейера офлайн, убрал хвосты про сборку
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
623cbb3843
commit
e4986d0c5d
3 changed files with 81 additions and 31 deletions
|
|
@ -147,36 +147,6 @@ T4 получает вход из ON-пути, T5 — из OFF-пути; каж
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 3.5. Атлас: те же клетки, видимые глазом
|
|
||||||
|
|
||||||
Проверить, что архитектура действительно собрана из заявленных схем, можно не на
|
|
||||||
словах. `tools/build_brain_atlas.py` берёт публичные выгрузки Codex (FAFB v783) и
|
|
||||||
сводит их в атлас: положение сомы каждого нейрона и номер стадии FlyGuard, которой
|
|
||||||
он соответствует. Привязка идёт по **имени типа клетки**, а не по догадке, и все
|
|
||||||
типы находятся поимённо:
|
|
||||||
|
|
||||||
| Тип | В коннектоме | Где используется |
|
|
||||||
|---|---|---|
|
|
||||||
| LC11 | 127 | `lobula.py` — кандидаты как компактные группы лучей |
|
|
||||||
| LPLC2 | 210 | `medulla.py` — надвигание как дивергенция потока |
|
|
||||||
| HS (HSE/HSN/HSS) | 6 | `medulla.py` — широкопольный поток |
|
|
||||||
| VS1…VS8 | 16 | там же, вертикальный канал |
|
|
||||||
| T4a–d / T5a–d | 6243 / 6002 | `medulla.py` — коррелятор Хассенштайна–Райхардта |
|
|
||||||
| L1 / L2 | 3503 | `lamina.py` — каналы ON и OFF |
|
|
||||||
| Клетки Кеньона | 5177 | `mushroom_body.py` — разрежённый код |
|
|
||||||
| MBON | 96 | там же, выход памяти |
|
|
||||||
| APL | 2 | там же, глобальное торможение |
|
|
||||||
| EPG | 47 | `central_complex.py` — кольцевой аттрактор |
|
|
||||||
| DNp01 | 2 | `descending.py` — гигантское волокно |
|
|
||||||
|
|
||||||
Совпадение с литературой полное: LC11 около 110–130 клеток, HS по три на сторону,
|
|
||||||
VS по восемь, APL и гигантское волокно — по одной на полушарие.
|
|
||||||
|
|
||||||
Вид `brain_style: cloud` рисует эти 139 255 нейронов на их анатомических местах и
|
|
||||||
подсвечивает активностью соответствующей стадии. Симуляции по-прежнему нет:
|
|
||||||
коннектом даёт анатомию, конвейер даёт активность, вид накладывает одно на другое
|
|
||||||
за 8 мс на кадр.
|
|
||||||
|
|
||||||
## 4. Источники
|
## 4. Источники
|
||||||
|
|
||||||
* Dorkenwald S. и др. **Neuronal wiring diagram of an adult brain.** Nature, 2024 —
|
* Dorkenwald S. и др. **Neuronal wiring diagram of an adult brain.** Nature, 2024 —
|
||||||
|
|
|
||||||
|
|
@ -339,7 +339,7 @@ numba являются ламина и оценка движения — вме
|
||||||
| Кадров с тревогой | **9.4 %** | 17.2 % |
|
| Кадров с тревогой | **9.4 %** | 17.2 % |
|
||||||
| Посторонних тревог на кадр (полигон) | **0.055** | 0.171 |
|
| Посторонних тревог на кадр (полигон) | **0.055** | 0.171 |
|
||||||
| Реальный объект на 55 м | 98.9 % | 98.9 % |
|
| Реальный объект на 55 м | 98.9 % | 98.9 % |
|
||||||
| Задержка, медиана в контейнере | 32 мс | 33 мс |
|
| Задержка, медиана | 32 мс | 33 мс |
|
||||||
|
|
||||||
**Включено по умолчанию.** Размен здесь принципиально лучше, чем у разделения фигуры
|
**Включено по умолчанию.** Размен здесь принципиально лучше, чем у разделения фигуры
|
||||||
и фона (п. 9.4): там было вчетверо больше ложных за +29 % дальности, здесь — в 1.75
|
и фона (п. 9.4): там было вчетверо больше ложных за +29 % дальности, здесь — в 1.75
|
||||||
|
|
|
||||||
80
tools/run_pipeline.py
Normal file
80
tools/run_pipeline.py
Normal file
|
|
@ -0,0 +1,80 @@
|
||||||
|
"""Сквозной прогон конвейера по бэгу: решения, треки, тайминги.
|
||||||
|
|
||||||
|
python tools/run_pipeline.py --bag data/for_hackathon/doubleT_obstacle --verbose
|
||||||
|
python tools/run_pipeline.py --all --memory artifacts/mushroom_body.npz
|
||||||
|
"""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
import _bootstrap as B # noqa: F401
|
||||||
|
from flyguard.bag import Bag, find_bags
|
||||||
|
from flyguard.mushroom_body import MushroomBody
|
||||||
|
from flyguard.pipeline import FlyGuard, Params
|
||||||
|
|
||||||
|
|
||||||
|
def run(bag_path, params: Params, memory, limit: int | None, verbose: bool) -> dict:
|
||||||
|
bag = Bag(bag_path)
|
||||||
|
fg = FlyGuard(params, memory=memory)
|
||||||
|
stages: dict[str, list[float]] = {}
|
||||||
|
n_det = n_frames = 0
|
||||||
|
dists, speeds, ncand = [], [], []
|
||||||
|
|
||||||
|
for _, pc in bag.frames(stop=limit):
|
||||||
|
res = fg.process(pc)
|
||||||
|
if res is None:
|
||||||
|
continue
|
||||||
|
n_frames += 1
|
||||||
|
for k, v in res.timings.items():
|
||||||
|
stages.setdefault(k, []).append(v)
|
||||||
|
ncand.append(len(res.candidates))
|
||||||
|
speeds.append(res.ego.speed if res.ego else 0.0)
|
||||||
|
d = res.decision
|
||||||
|
if d.detected:
|
||||||
|
n_det += 1
|
||||||
|
dists.append(d.distance)
|
||||||
|
if verbose and n_frames % 10 == 0:
|
||||||
|
obj = (f"{d.distance:6.1f} м conf={d.confidence:.2f} "
|
||||||
|
f"{'ЭКСТРЕННО' if d.emergency else 'предупр.'}"
|
||||||
|
if d.detected else "путь свободен")
|
||||||
|
print(f" кадр {n_frames:4d} v={res.ego.speed*3.6:5.1f} км/ч "
|
||||||
|
f"канд.={len(res.candidates):3d} треков={len(fg.cx.tracks):3d} | {obj} "
|
||||||
|
f"| {res.total_ms:5.1f} мс")
|
||||||
|
|
||||||
|
tot = np.array([sum(v[i] for v in stages.values()) for i in range(n_frames)]) \
|
||||||
|
if n_frames else np.zeros(1)
|
||||||
|
res = dict(name=bag.path.name, frames=n_frames, det_rate=n_det / max(n_frames, 1),
|
||||||
|
p50=float(np.median(tot)), p95=float(np.percentile(tot, 95)),
|
||||||
|
cands=float(np.mean(ncand)) if ncand else 0.0,
|
||||||
|
v=float(np.median(speeds) * 3.6) if speeds else 0.0,
|
||||||
|
d_med=float(np.median(dists)) if dists else float("nan"))
|
||||||
|
print(f"{res['name']:40s} кадров {res['frames']:4d} | тревога в {res['det_rate']:6.1%} "
|
||||||
|
f"кадров (медиана {res['d_med']:6.1f} м) | канд./кадр {res['cands']:5.1f} | "
|
||||||
|
f"v={res['v']:5.1f} км/ч | {res['p50']:5.1f}/{res['p95']:5.1f} мс (p50/p95)")
|
||||||
|
if verbose:
|
||||||
|
for k in sorted(stages, key=lambda k: -np.median(stages[k])):
|
||||||
|
print(f" {k:12s} {np.median(stages[k]):6.2f} мс")
|
||||||
|
return res
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
ap = argparse.ArgumentParser(description=__doc__)
|
||||||
|
ap.add_argument("--bag")
|
||||||
|
ap.add_argument("--all", action="store_true")
|
||||||
|
ap.add_argument("--limit", type=int, default=150)
|
||||||
|
ap.add_argument("--memory", default=None)
|
||||||
|
ap.add_argument("--fov", type=float, default=30.0)
|
||||||
|
ap.add_argument("--verbose", action="store_true")
|
||||||
|
args = ap.parse_args()
|
||||||
|
|
||||||
|
memory = MushroomBody.load(args.memory) if args.memory else None
|
||||||
|
params = Params(fov_deg=args.fov)
|
||||||
|
bags = find_bags(B.DATA / "for_hackathon") if args.all else [args.bag]
|
||||||
|
for b in bags:
|
||||||
|
run(b, params, memory, args.limit, args.verbose)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
Loading…
Reference in a new issue