flybrain 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- flybrain-0.1.0/LICENSE +21 -0
- flybrain-0.1.0/PACKAGE.md +60 -0
- flybrain-0.1.0/PKG-INFO +87 -0
- flybrain-0.1.0/README.md +371 -0
- flybrain-0.1.0/flybrain/__init__.py +18 -0
- flybrain-0.1.0/flybrain/__main__.py +51 -0
- flybrain-0.1.0/flybrain/brain.py +201 -0
- flybrain-0.1.0/flybrain/build.py +204 -0
- flybrain-0.1.0/flybrain/data.py +80 -0
- flybrain-0.1.0/flybrain/eyes.py +124 -0
- flybrain-0.1.0/flybrain/reservoir.py +275 -0
- flybrain-0.1.0/flybrain.egg-info/PKG-INFO +87 -0
- flybrain-0.1.0/flybrain.egg-info/SOURCES.txt +17 -0
- flybrain-0.1.0/flybrain.egg-info/dependency_links.txt +1 -0
- flybrain-0.1.0/flybrain.egg-info/entry_points.txt +2 -0
- flybrain-0.1.0/flybrain.egg-info/requires.txt +10 -0
- flybrain-0.1.0/flybrain.egg-info/top_level.txt +1 -0
- flybrain-0.1.0/pyproject.toml +40 -0
- flybrain-0.1.0/setup.cfg +4 -0
flybrain-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 alextitonis
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# flybrain
|
|
2
|
+
|
|
3
|
+
The complete central nervous system of an adult male fruit fly, *Drosophila melanogaster*, as a
|
|
4
|
+
spiking network you can run on your own computer: **166,700 neurons and 25.6 million
|
|
5
|
+
connections** from the [MaleCNS v1.0 connectome](https://male-cns.janelia.org), wired as
|
|
6
|
+
electron microscopy found them.
|
|
7
|
+
|
|
8
|
+
Nothing inside the brain is trained. You drive some of the fly's own neurons, step the network
|
|
9
|
+
forward, and read out what its descending neurons (the brain's commands to the body) do.
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
pip install flybrain # CPU (numba)
|
|
13
|
+
pip install "flybrain[gpu]" # plus CuPy for an NVIDIA GPU (CUDA 12)
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
```python
|
|
17
|
+
from flybrain import FlyBrain
|
|
18
|
+
|
|
19
|
+
brain = FlyBrain(device="auto") # first run downloads the brain files (~260 MB) to ~/fly-data
|
|
20
|
+
left_loom = brain.cells(["LC4", "LPLC2"], side="L") # looming detectors, left eye
|
|
21
|
+
giant_fiber = brain.cells(["DNp01"], side="L") # the escape command neuron
|
|
22
|
+
|
|
23
|
+
for step in range(50): # one second at 20 ms per step
|
|
24
|
+
fired = brain.step(inject=[(left_loom, 0.8)])
|
|
25
|
+
if set(giant_fiber) & set(fired):
|
|
26
|
+
print(f"left giant fiber fired at {step * brain.dt:.2f} s")
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## What's in it
|
|
30
|
+
|
|
31
|
+
* `FlyBrain`: leaky integrate-and-fire over the whole connectome. `device="cpu" | "cuda" | "auto"`,
|
|
32
|
+
`batch=8` runs 8 independent flies at once, plus `dt`, `sensory_input` and `refractory` options.
|
|
33
|
+
`brain.cells([...])` finds neurons by cell type or superclass (`"descending_neuron"`).
|
|
34
|
+
* `Trace`, `run`, `Readout`: reservoir computing. Collect a spike trace of any neuron population
|
|
35
|
+
over your task, then fit a cross-validated linear or logistic PCA readout to your labels.
|
|
36
|
+
* `Eyes`, `FeatureDetectors`: a visual encoder that drives the fly's visual projection neurons.
|
|
37
|
+
|
|
38
|
+
## Data
|
|
39
|
+
|
|
40
|
+
The brain files live in `$FLY_DATA` (default `~/fly-data`). The first `FlyBrain()` downloads them;
|
|
41
|
+
you can also run it ahead of time:
|
|
42
|
+
|
|
43
|
+
```sh
|
|
44
|
+
flybrain download # prebuilt files, sha256-checked
|
|
45
|
+
flybrain build # or build them from the MaleCNS release (~1.1 GB; pip install "flybrain[build]")
|
|
46
|
+
flybrain info # data folder and GPU status
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
The first step on CPU is slow while numba compiles; later steps take about 12–15 ms on 24 threads.
|
|
50
|
+
On an RTX 4060 a step takes 1.4 ms.
|
|
51
|
+
|
|
52
|
+
## Credits and license
|
|
53
|
+
|
|
54
|
+
Code: MIT. The connectome data is MaleCNS v1.0 by FlyEM (HHMI Janelia), the University of
|
|
55
|
+
Cambridge, the MRC Laboratory of Molecular Biology and Google Research, used under
|
|
56
|
+
[CC BY 4.0](https://male-cns.janelia.org/download/). If you use it, cite Berg, S. et al. (2026),
|
|
57
|
+
*Sexual dimorphism in the complete connectome of the Drosophila male central nervous system*, *Cell*.
|
|
58
|
+
The neuron model follows [Fly64](https://github.com/ornata/fly) by Jessica Paquette.
|
|
59
|
+
|
|
60
|
+
Source, experiments and results: [github.com/alextitonis/fly.ai](https://github.com/alextitonis/fly.ai)
|
flybrain-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: flybrain
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: The complete fruit fly nervous system (MaleCNS connectome, 166,700 neurons) as a spiking network, on CPU or GPU.
|
|
5
|
+
Author: alextitonis
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://flyaiworld.com
|
|
8
|
+
Project-URL: Source, https://github.com/alextitonis/fly.ai
|
|
9
|
+
Keywords: connectome,drosophila,spiking neural network,neuroscience,reservoir computing
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
Classifier: Intended Audience :: Science/Research
|
|
13
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
14
|
+
Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
|
|
15
|
+
Requires-Python: >=3.10
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
License-File: LICENSE
|
|
18
|
+
Requires-Dist: numpy>=2.0
|
|
19
|
+
Requires-Dist: scipy>=1.13
|
|
20
|
+
Requires-Dist: numba>=0.61
|
|
21
|
+
Provides-Extra: gpu
|
|
22
|
+
Requires-Dist: cupy-cuda12x[ctk]>=13; extra == "gpu"
|
|
23
|
+
Provides-Extra: build
|
|
24
|
+
Requires-Dist: pandas>=2.2; extra == "build"
|
|
25
|
+
Requires-Dist: pyarrow>=15; extra == "build"
|
|
26
|
+
Dynamic: license-file
|
|
27
|
+
|
|
28
|
+
# flybrain
|
|
29
|
+
|
|
30
|
+
The complete central nervous system of an adult male fruit fly, *Drosophila melanogaster*, as a
|
|
31
|
+
spiking network you can run on your own computer: **166,700 neurons and 25.6 million
|
|
32
|
+
connections** from the [MaleCNS v1.0 connectome](https://male-cns.janelia.org), wired as
|
|
33
|
+
electron microscopy found them.
|
|
34
|
+
|
|
35
|
+
Nothing inside the brain is trained. You drive some of the fly's own neurons, step the network
|
|
36
|
+
forward, and read out what its descending neurons (the brain's commands to the body) do.
|
|
37
|
+
|
|
38
|
+
```sh
|
|
39
|
+
pip install flybrain # CPU (numba)
|
|
40
|
+
pip install "flybrain[gpu]" # plus CuPy for an NVIDIA GPU (CUDA 12)
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
```python
|
|
44
|
+
from flybrain import FlyBrain
|
|
45
|
+
|
|
46
|
+
brain = FlyBrain(device="auto") # first run downloads the brain files (~260 MB) to ~/fly-data
|
|
47
|
+
left_loom = brain.cells(["LC4", "LPLC2"], side="L") # looming detectors, left eye
|
|
48
|
+
giant_fiber = brain.cells(["DNp01"], side="L") # the escape command neuron
|
|
49
|
+
|
|
50
|
+
for step in range(50): # one second at 20 ms per step
|
|
51
|
+
fired = brain.step(inject=[(left_loom, 0.8)])
|
|
52
|
+
if set(giant_fiber) & set(fired):
|
|
53
|
+
print(f"left giant fiber fired at {step * brain.dt:.2f} s")
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## What's in it
|
|
57
|
+
|
|
58
|
+
* `FlyBrain`: leaky integrate-and-fire over the whole connectome. `device="cpu" | "cuda" | "auto"`,
|
|
59
|
+
`batch=8` runs 8 independent flies at once, plus `dt`, `sensory_input` and `refractory` options.
|
|
60
|
+
`brain.cells([...])` finds neurons by cell type or superclass (`"descending_neuron"`).
|
|
61
|
+
* `Trace`, `run`, `Readout`: reservoir computing. Collect a spike trace of any neuron population
|
|
62
|
+
over your task, then fit a cross-validated linear or logistic PCA readout to your labels.
|
|
63
|
+
* `Eyes`, `FeatureDetectors`: a visual encoder that drives the fly's visual projection neurons.
|
|
64
|
+
|
|
65
|
+
## Data
|
|
66
|
+
|
|
67
|
+
The brain files live in `$FLY_DATA` (default `~/fly-data`). The first `FlyBrain()` downloads them;
|
|
68
|
+
you can also run it ahead of time:
|
|
69
|
+
|
|
70
|
+
```sh
|
|
71
|
+
flybrain download # prebuilt files, sha256-checked
|
|
72
|
+
flybrain build # or build them from the MaleCNS release (~1.1 GB; pip install "flybrain[build]")
|
|
73
|
+
flybrain info # data folder and GPU status
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
The first step on CPU is slow while numba compiles; later steps take about 12–15 ms on 24 threads.
|
|
77
|
+
On an RTX 4060 a step takes 1.4 ms.
|
|
78
|
+
|
|
79
|
+
## Credits and license
|
|
80
|
+
|
|
81
|
+
Code: MIT. The connectome data is MaleCNS v1.0 by FlyEM (HHMI Janelia), the University of
|
|
82
|
+
Cambridge, the MRC Laboratory of Molecular Biology and Google Research, used under
|
|
83
|
+
[CC BY 4.0](https://male-cns.janelia.org/download/). If you use it, cite Berg, S. et al. (2026),
|
|
84
|
+
*Sexual dimorphism in the complete connectome of the Drosophila male central nervous system*, *Cell*.
|
|
85
|
+
The neuron model follows [Fly64](https://github.com/ornata/fly) by Jessica Paquette.
|
|
86
|
+
|
|
87
|
+
Source, experiments and results: [github.com/alextitonis/fly.ai](https://github.com/alextitonis/fly.ai)
|
flybrain-0.1.0/README.md
ADDED
|
@@ -0,0 +1,371 @@
|
|
|
1
|
+
<p align="center"><img src="logo.webp" alt="fly.ai" width="440"></p>
|
|
2
|
+
|
|
3
|
+
# fly.ai: a real fruit fly brain, running on your computer
|
|
4
|
+
|
|
5
|
+
https://github.com/user-attachments/assets/7c3b91e5-9b50-4017-a03a-123aedd4d7b4
|
|
6
|
+
|
|
7
|
+
*The fly brain playing an online fighting game. See [sshfighter/](sshfighter/).*
|
|
8
|
+
|
|
9
|
+
fly.ai is a simulation of the **complete central nervous system of an adult male fruit fly**
|
|
10
|
+
(*Drosophila melanogaster*): **166,700 neurons and 25.6 million connections** from the
|
|
11
|
+
[MaleCNS v1.0 connectome](https://male-cns.janelia.org), wired exactly as electron microscopy
|
|
12
|
+
found them in a real fly.
|
|
13
|
+
|
|
14
|
+
There is **no training and no learned policy inside the brain**. You connect a task to it at a few
|
|
15
|
+
neuron types known from the literature, one side for input (what the fly senses) and one for
|
|
16
|
+
output (the commands its brain sends to the body). Everything in between is the connectome.
|
|
17
|
+
|
|
18
|
+
The goal is a general-purpose "fly reservoir": plug any task into the same frozen brain, read
|
|
19
|
+
out what it does, and find out what a real nervous system's wiring is good for.
|
|
20
|
+
|
|
21
|
+
**$FLYAI** is live on Robinhood Chain (launched on Pons):
|
|
22
|
+
`0x0088CE7905025c4B5ea1d49aB6179B6aaADB3B9C`. The address is posted only here, on the
|
|
23
|
+
[site](https://flyaiworld.com) and on [@flydotai](https://x.com/flydotai); any other address is a
|
|
24
|
+
scam. Details: [TOKEN.md](TOKEN.md).
|
|
25
|
+
|
|
26
|
+
## How it works
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
task input
|
|
30
|
+
└─> encoder: drives the fly's own sensory / feature-detector neurons
|
|
31
|
+
└─> 166,700-neuron connectome, leaky integrate-and-fire, 50 steps/s (500 with `dt=0.002`)
|
|
32
|
+
└─> descending neurons (the brain's 1,314 output cables to the body)
|
|
33
|
+
└─> decoder or trained linear readout
|
|
34
|
+
└─> task output
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
* **Network** (`flybrain/build.py`, `flybrain/brain.py`): every neuron with a MaleCNS superclass
|
|
38
|
+
annotation, and every connection between them. The weight is the synapse count, made negative
|
|
39
|
+
when the presynaptic neuron's predicted transmitter is GABA, glutamate or histamine, then scaled
|
|
40
|
+
so each neuron's inputs add up to 1. Each neuron is a simple leaky integrate-and-fire unit
|
|
41
|
+
(`v ← e^(-dt/τ)·v + gain·W·spikes + tonic + noise`; it spikes and resets at 1). This recipe
|
|
42
|
+
follows [Fly64](https://github.com/ornata/fly). The simulation is multi-threaded with numba.
|
|
43
|
+
* **Visual encoder** (`flybrain/eyes.py`): two routes into the brain.
|
|
44
|
+
* *Eyes*: a 1-D panorama projected onto the 6,006 photoreceptors, each placed by its eye column.
|
|
45
|
+
* *Feature detectors*: drive the fly's own visual projection neurons directly, on the side
|
|
46
|
+
where things are:
|
|
47
|
+
|
|
48
|
+
| Neuron type | Responds to (in a real fly) |
|
|
49
|
+
|---|---|
|
|
50
|
+
| LPLC2 | looming: something getting bigger as it approaches |
|
|
51
|
+
| LC4 | fast looming, escape |
|
|
52
|
+
| LPLC1 | small approaching objects |
|
|
53
|
+
| LC10a | a moving target the male chases |
|
|
54
|
+
|
|
55
|
+
* **Outputs**: the brain's descending neurons, including identified command neurons such as
|
|
56
|
+
DNa02 (steering), DNp01 (the giant fiber, escape take-off), DNg100 (forward walking) and
|
|
57
|
+
MDN (backward walking). A task either decodes these by hand or trains a linear readout on all
|
|
58
|
+
of them (reservoir computing).
|
|
59
|
+
|
|
60
|
+
## What we found
|
|
61
|
+
|
|
62
|
+
These are small experiments, run on a desktop. They are not peer-reviewed science.
|
|
63
|
+
|
|
64
|
+
1. **With Fly64's settings, vision does nothing.** Fly64 uses tonic 0.18 and decay e^(-0.2).
|
|
65
|
+
That puts every neuron's resting voltage at 0.18 / (1 − 0.82) ≈ 1.0, exactly the firing
|
|
66
|
+
threshold. The whole network ticks along by itself at about 4 Hz, and the motor neurons fire
|
|
67
|
+
at the same rate whatever the fly is shown (`experiment.py`).
|
|
68
|
+
2. **The signal from the photoreceptors dies at the first relay.** Photoreceptors release
|
|
69
|
+
histamine, which is inhibitory, onto lamina neurons. Real lamina neurons use smooth, graded
|
|
70
|
+
signals rather than spikes, which this simple model can't reproduce. In every setting we
|
|
71
|
+
tried, looming stimuli never reached the looming detectors (`sweep.py`).
|
|
72
|
+
3. **Past the eye, the wiring does the right thing on the correct side** (`inject.py`,
|
|
73
|
+
tonic 0.14 and gain 3.0, 6 noise seeds):
|
|
74
|
+
|
|
75
|
+
| Stimulate (left side only) | Result |
|
|
76
|
+
|---|---|
|
|
77
|
+
| LC4 + LPLC2 looming detectors | left giant fiber DNp01 **+17 to +25 spikes/s**; right side unchanged |
|
|
78
|
+
| LC10a courtship-tracking neurons | left DNa02 steering neuron **+1.4 to +3.7 spikes/s**; right side unchanged |
|
|
79
|
+
|
|
80
|
+
None of the other readout neurons changed. These are the known looming → escape and
|
|
81
|
+
courtship pursuit → steering pathways, and they come out of the wiring alone.
|
|
82
|
+
4. **Smell neurons ran away until sensory neurons stopped receiving synapses.** In the original
|
|
83
|
+
model, olfactory receptor neurons get 0.43 of their 0.45 net input from each other
|
|
84
|
+
(ORN-to-ORN connections). At gain 3.0 that loop pins them near maximum rate, so the
|
|
85
|
+
food-odour projection neurons (DM1/DM2) sat at 50 Hz, the model's ceiling, with or without an
|
|
86
|
+
odour. `FlyBrain(sensory_input=False)` removes every synapse onto sensory neurons, as
|
|
87
|
+
whole-brain spiking models of the fly do. The same odour then drives DM1/DM2 from 16 to 28 Hz
|
|
88
|
+
while other projection neurons stay where they were. The default is unchanged, so every earlier
|
|
89
|
+
result still holds.
|
|
90
|
+
5. **Two brains can signal to each other** (`flytalk.py`, [flyaiworld.com/flybook](https://flyaiworld.com/flybook)).
|
|
91
|
+
Fly A lives through a situation (a looming threat, a mate in view, a food smell, or nothing),
|
|
92
|
+
its wing motor neurons "sing", and fly B hears the song through its Johnston's-organ neurons.
|
|
93
|
+
Three runs, with the tests fixed before running and 50-shuffle permutation nulls:
|
|
94
|
+
|
|
95
|
+
| | Run 1: original, 20 ms | Run 2: smell fixed, 20 ms | Run 3: smell fixed, 2 ms |
|
|
96
|
+
|---|---|---|---|
|
|
97
|
+
| song → what happened to the singer | 0.30 bits | 0.63 bits | 0.83 bits |
|
|
98
|
+
| same test, degree-preserving scrambled wiring | 0.01 bits | 0.01 bits | **0.87 bits** |
|
|
99
|
+
| listener reacts to a threat song (vs silence) | 23% vs 17% | 21% vs 14% | **77.5% vs 17.5%** (p < 0.001) |
|
|
100
|
+
|
|
101
|
+
Threat is the clear word in every run, and "mate" becomes partly readable at 2 ms. In every
|
|
102
|
+
run the listener's descending neurons carry the singer's situation and stay at chance in
|
|
103
|
+
silence, but the listener only uses loudness: a time-shuffled song works as well. The "real
|
|
104
|
+
wiring matters" test **fails at 2 ms**, where the scrambled brain's song carries as many bits,
|
|
105
|
+
although it groups the situations differently. Food reaches the brain but never the wings,
|
|
106
|
+
and hearing a song never makes a fly sing back. `flybook.py` turns the 2 ms brain into a feed
|
|
107
|
+
of posts, each with the neurons behind it.
|
|
108
|
+
|
|
109
|
+
## Applications
|
|
110
|
+
|
|
111
|
+
| Folder | What the fly does |
|
|
112
|
+
|---|---|
|
|
113
|
+
| [`sshfighter/`](sshfighter/) | plays [SSH Fighter](https://sshfighter.com), an online terminal fighting game, as a registered bot, with a live dashboard of every neuron firing and a trained punch readout |
|
|
114
|
+
| [`flytalk.py`](flytalk.py), [`flybook.py`](flybook.py) | two copies of the brain signal to each other through wing song and hearing; the posts they produce make up the feed at [flyaiworld.com/flybook](https://flyaiworld.com/flybook) |
|
|
115
|
+
|
|
116
|
+

|
|
117
|
+
|
|
118
|
+
New applications go in their own folder and import the core from the `flybrain` package
|
|
119
|
+
(`from flybrain import FlyBrain`), either from the repository root or after `pip install flybrain`.
|
|
120
|
+
|
|
121
|
+
## Use it on your own task
|
|
122
|
+
|
|
123
|
+
`flybrain/reservoir.py` is the reusable half of the SSH Fighter bot's reservoir readout, pulled out so
|
|
124
|
+
any task can use it, not just the game:
|
|
125
|
+
|
|
126
|
+
```
|
|
127
|
+
input -> encoder -> fly brain (frozen) -> trace -> trained readout -> output
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
The brain never trains, on any task: `FlyBrain`'s weights are the connectome, fixed at load
|
|
131
|
+
time. Only two things ever get fit:
|
|
132
|
+
|
|
133
|
+
* **An encoder**, which you write: pick the neuron types your input should drive with
|
|
134
|
+
`brain.cells([...types], side=...)` and pass `(indices, amount)` pairs to
|
|
135
|
+
`brain.step(inject=...)`. `flybrain/eyes.py` is a worked example for SSH Fighter's visual input;
|
|
136
|
+
the neuron types available are whatever the MaleCNS connectome names (look one up on
|
|
137
|
+
[neuPrint](https://neuprint.janelia.org)).
|
|
138
|
+
* **A readout**, which `flybrain.Readout.fit` trains for you: a linear (`kind="ridge"`) or
|
|
139
|
+
logistic (`kind="logistic"`) fit on the top principal components of neural activity, with the
|
|
140
|
+
PCA rank and L2 strength picked by cross-validation. This is the exact method
|
|
141
|
+
`sshfighter/reservoir.py` uses for the punch and movement readouts, generalised off SSH
|
|
142
|
+
Fighter's game state.
|
|
143
|
+
|
|
144
|
+
`flybrain.Trace` collects a decaying spike trace of any neuron population (a cell type, a
|
|
145
|
+
`brain.groups[...]` set, or your own index array) step by step; `flybrain.run` steps the
|
|
146
|
+
brain over a sequence of encoded inputs and returns the trace stacked over time, so the whole
|
|
147
|
+
loop is one call from a notebook:
|
|
148
|
+
|
|
149
|
+
```python
|
|
150
|
+
from flybrain import FlyBrain
|
|
151
|
+
from flybrain.reservoir import Trace, Readout, run
|
|
152
|
+
|
|
153
|
+
brain = FlyBrain(device="auto")
|
|
154
|
+
trace = Trace(brain, types=["descending_neuron"]) # or group=..., or idx=your_own_array
|
|
155
|
+
|
|
156
|
+
def encode(t):
|
|
157
|
+
return [(brain.cells(["LC10a"], side="L"), my_inputs[t])] # your task's encoder
|
|
158
|
+
|
|
159
|
+
activity = run(brain, len(my_inputs), encode=encode, trace=trace)
|
|
160
|
+
readout = Readout.fit(activity, my_labels, kind="ridge") # or "logistic" for 0/1 labels
|
|
161
|
+
prediction = readout.predict(activity[-1])
|
|
162
|
+
readout.save("readout.npz") # Readout.load(...) later
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
`flyreservoir_example.py` runs this end to end on a synthetic task (classify and measure the
|
|
166
|
+
strength of a left/right stimulus) with no game or recordings needed:
|
|
167
|
+
`python flyreservoir_example.py`. Its held-out numbers are printed as they come out, not curated
|
|
168
|
+
— on the fixed seed it ships with, the classifier does better than chance and the strength
|
|
169
|
+
regression is close to just predicting the average; that is the honest state of a two-line
|
|
170
|
+
encoder on an invented task, not a claim about what the connectome can do in general (see
|
|
171
|
+
"What's next" and `ROADMAP.md` for the open question of how much the real wiring helps versus
|
|
172
|
+
a random network of the same size).
|
|
173
|
+
|
|
174
|
+
Batching and the GPU option work the same way they do in `flybrain/brain.py`: `FlyBrain(batch=8)` or
|
|
175
|
+
`FlyBrain(device="cuda")` (or `FLY_DEVICE=cuda`); `Trace(..., aggregate="mean")` (the default)
|
|
176
|
+
gives one feature vector averaged across the batch, `aggregate="batch"` keeps one per fly.
|
|
177
|
+
|
|
178
|
+
### Brain options
|
|
179
|
+
|
|
180
|
+
`FlyBrain` takes three options. The defaults are the model every earlier result used.
|
|
181
|
+
|
|
182
|
+
* `dt` (default `0.020`): the step length. `tonic` is rescaled so a silent neuron settles at the
|
|
183
|
+
same voltage. At `dt=0.002` the network runs far hotter unless you also set a refractory
|
|
184
|
+
period; `refractory=0.004` matched the 20 ms brain's resting descending-neuron rate with no
|
|
185
|
+
neurons above 100 Hz.
|
|
186
|
+
* `sensory_input` (default `True`): `False` removes every synapse onto sensory neurons, which
|
|
187
|
+
fixes the olfactory runaway loop (finding 4).
|
|
188
|
+
* `refractory` (default `0`): seconds a neuron is held at 0 after it spikes.
|
|
189
|
+
|
|
190
|
+
`brain.cells([...])` accepts superclass names such as `"descending_neuron"` as well as cell types.
|
|
191
|
+
|
|
192
|
+
### Limitations
|
|
193
|
+
|
|
194
|
+
* Point neurons with one global set of parameters. There are no dendrites, no graded neurons,
|
|
195
|
+
no neuromodulators and no plasticity.
|
|
196
|
+
* Transmitter sign is a rough rule (GABA, glutamate and histamine inhibitory; everything else
|
|
197
|
+
excitatory). Real effects depend on the receptor.
|
|
198
|
+
* The visual front end is a shortcut, like [Eon's embodied fly](https://eon.systems/updates/embodied-brain-emulation).
|
|
199
|
+
We inject input into feature-detector neurons instead of simulating the eye.
|
|
200
|
+
* None of this is validated against recordings from real flies. It's a demo, not an emulation.
|
|
201
|
+
|
|
202
|
+
## Run it
|
|
203
|
+
|
|
204
|
+
A multi-core CPU helps: one brain step takes about 12–15 ms on 24 threads, and real time needs
|
|
205
|
+
under 20 ms.
|
|
206
|
+
|
|
207
|
+
**Just the brain, as a library** (Python 3.10+):
|
|
208
|
+
|
|
209
|
+
```sh
|
|
210
|
+
pip install flybrain # or "flybrain[gpu]" for an NVIDIA GPU
|
|
211
|
+
flybrain download # optional: the first FlyBrain() does this itself (~260 MB, once)
|
|
212
|
+
flybrain info # where the data lives, and whether CUDA works
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
**This repository** (experiments, the SSH Fighter bot, flytalk): the `flybrain/` package sits at
|
|
216
|
+
the root, so scripts run from a clone without installing it.
|
|
217
|
+
|
|
218
|
+
```sh
|
|
219
|
+
python -m venv .venv
|
|
220
|
+
# Windows: .venv\Scripts\activate macOS/Linux: source .venv/bin/activate
|
|
221
|
+
pip install -r requirements.txt
|
|
222
|
+
|
|
223
|
+
python -m flybrain download # prebuilt brain (~260 MB) into ~/fly-data
|
|
224
|
+
# or: python -m flybrain build # download MaleCNS v1.0 (~1.1 GB) and build the network yourself
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
Set `FLY_DATA=/some/path` to store the data somewhere else.
|
|
228
|
+
|
|
229
|
+
**Quickstart notebook:** [`notebooks/quickstart.ipynb`](notebooks/quickstart.ipynb) loads the
|
|
230
|
+
brain, stimulates the left looming detectors and shows the left giant fiber fire, maps where
|
|
231
|
+
the activity goes, and tests the chase pathway. It needs `pip install matplotlib jupyter`.
|
|
232
|
+
|
|
233
|
+
```python
|
|
234
|
+
from flybrain import FlyBrain
|
|
235
|
+
brain = FlyBrain(device="auto") # GPU if available, else CPU
|
|
236
|
+
brain.stimulate(brain.cells(["LC4", "LPLC2"], side="L"), 0.8)
|
|
237
|
+
fired = brain.step() # advance 20 ms; indices of neurons that spiked
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
**GPU:** on an NVIDIA card, `pip install -r requirements-gpu.txt` and set `FLY_DEVICE=cuda` (or
|
|
241
|
+
pass `device="cuda"`, or `--device cuda` to the bot). The whole connectome fits in about 210 MB of
|
|
242
|
+
GPU memory. On an RTX 4060 laptop GPU a step takes **1.4 ms, against 8.9 ms on a 24-thread CPU**.
|
|
243
|
+
Both devices run the same model and give the same results. Only the random noise differs, so
|
|
244
|
+
individual spikes differ between them.
|
|
245
|
+
|
|
246
|
+
**Many flies at once:** `FlyBrain(batch=8)` runs 8 independent copies of the brain with the
|
|
247
|
+
same wiring, each with its own voltages and noise. On a GPU they share one sparse multiply, at
|
|
248
|
+
about 1.2 ms per fly per step. Inputs can be the same for every fly or differ per fly, which is
|
|
249
|
+
how `sshfighter/` runs voting flies and compares encoders side by side.
|
|
250
|
+
|
|
251
|
+
**Experiments:** `python experiment.py`, `python sweep.py`, `python inject.py`.
|
|
252
|
+
|
|
253
|
+
**Watch it play:** `python sshfighter/fly_fighter.py --offline --seconds 120 --dashboard`
|
|
254
|
+
(fake opponent, opens http://127.0.0.1:8777). See [sshfighter/README.md](sshfighter/README.md).
|
|
255
|
+
|
|
256
|
+
### Getting the data (the "model")
|
|
257
|
+
|
|
258
|
+
There are no trained weights. The "model" is the fly's wiring diagram. `flybrain download` fetches
|
|
259
|
+
a prebuilt copy (checked against its sha256); `flybrain build` (needs `pip install "flybrain[build]"`,
|
|
260
|
+
already in `requirements.txt`) builds the same files from the public MaleCNS v1.0 release. It downloads these files into
|
|
261
|
+
`$FLY_DATA/raw/` and skips any that are already there. An interrupted download starts over on
|
|
262
|
+
the next run:
|
|
263
|
+
|
|
264
|
+
| File | Size | What it is | Source |
|
|
265
|
+
|---|---|---|---|
|
|
266
|
+
| `connectome-weights-male-cns-v1.0-minconf-0.5.feather` | 1.05 GB | every neuron-to-neuron connection, with synapse counts | [MaleCNS bucket](https://storage.googleapis.com/flyem-male-cns/v1.0/connectome-data/flat-connectome/connectome-weights-male-cns-v1.0-minconf-0.5.feather) |
|
|
267
|
+
| `body-annotations-male-cns-v1.0-minconf-0.5.feather` | 14 MB | cell types, sides, classes, soma positions | [MaleCNS bucket](https://storage.googleapis.com/flyem-male-cns/v1.0/connectome-data/flat-connectome/body-annotations-male-cns-v1.0-minconf-0.5.feather) |
|
|
268
|
+
| `body-neurotransmitters-male-cns-v1.0.feather` | 43 MB | predicted neurotransmitter for each neuron | [MaleCNS bucket](https://storage.googleapis.com/flyem-male-cns/v1.0/connectome-data/flat-connectome/body-neurotransmitters-male-cns-v1.0.feather) |
|
|
269
|
+
| `optic-columns.xlsx` | 0.1 MB | which eye column each photoreceptor belongs to | [flyconnectome/2025malecns](https://github.com/flyconnectome/2025malecns/blob/67767d2233657983993ff6c2be48e836a935863c/supplemental_data/optic-column-type-assignments-v1.0.xlsx) |
|
|
270
|
+
|
|
271
|
+
To download by hand instead (for example on a slow connection, or with `curl -C -` to resume):
|
|
272
|
+
|
|
273
|
+
```sh
|
|
274
|
+
mkdir -p ~/fly-data/raw && cd ~/fly-data/raw
|
|
275
|
+
B=https://storage.googleapis.com/flyem-male-cns/v1.0/connectome-data/flat-connectome
|
|
276
|
+
curl -LO -C - $B/connectome-weights-male-cns-v1.0-minconf-0.5.feather
|
|
277
|
+
curl -LO -C - $B/body-annotations-male-cns-v1.0-minconf-0.5.feather
|
|
278
|
+
curl -LO -C - $B/body-neurotransmitters-male-cns-v1.0.feather
|
|
279
|
+
curl -L -o optic-columns.xlsx https://raw.githubusercontent.com/flyconnectome/2025malecns/67767d2233657983993ff6c2be48e836a935863c/supplemental_data/optic-column-type-assignments-v1.0.xlsx
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
Then `python -m flybrain build` builds the network in about a minute. It writes
|
|
283
|
+
`weights.npz` (205 MB, the signed and normalized connection matrix) and `brain.npz` (neuron
|
|
284
|
+
types, sides, positions, readout groups, eye layout) into `$FLY_DATA`. Expect exactly
|
|
285
|
+
**166,700 neurons and 25,582,938 connections**. If you get different numbers, the data changed.
|
|
286
|
+
|
|
287
|
+
**Other ways to explore the same data**, without downloading anything:
|
|
288
|
+
|
|
289
|
+
* [neuPrint](https://neuprint.janelia.org) (dataset `male-cns:v1.0`): look up any neuron's inputs and
|
|
290
|
+
outputs in the browser, for example `DNp01`, the giant fiber. Its top inputs are LC4 and LPLC2.
|
|
291
|
+
For code, use `pip install neuprint-python` with an API token from your neuPrint account page.
|
|
292
|
+
* The [MaleCNS site](https://male-cns.janelia.org): cell type and dimorphism explorers, 3D viewers,
|
|
293
|
+
and the full download list (synapse positions, skeletons, EM images; far larger and not needed
|
|
294
|
+
here).
|
|
295
|
+
|
|
296
|
+
## Files
|
|
297
|
+
|
|
298
|
+
| File | What it does |
|
|
299
|
+
|---|---|
|
|
300
|
+
| `flybrain/` | the pip package (`pyproject.toml`); `flybrain download/build/info` is its command line |
|
|
301
|
+
| `flybrain/data.py` | where the brain files live (`$FLY_DATA`), and downloading the prebuilt copy |
|
|
302
|
+
| `flybrain/build.py` | downloads MaleCNS v1.0 and builds the weight matrix, readout groups, eye layout and neuron positions |
|
|
303
|
+
| `flybrain/brain.py` | integrate-and-fire simulation: CPU (numba) or NVIDIA GPU (CuPy), one fly or a batch |
|
|
304
|
+
| `flybrain/eyes.py` | photoreceptor rendering plus the looming/chase feature-detector input, with tunable encoder parameters (`ENCODER`) |
|
|
305
|
+
| `flybrain/reservoir.py` | generic reservoir readout: spike trace of any neuron population, PCA + linear/logistic readout, cross-validated |
|
|
306
|
+
| `flyreservoir_example.py` | the module above, end to end, on a synthetic task |
|
|
307
|
+
| `experiment.py`, `sweep.py`, `inject.py` | the experiments above |
|
|
308
|
+
| `flytalk.py` | the talking-flies experiment: two brains coupled through wing song and hearing, a scrambled-wiring control, permutation tests (`pilot`, `run`, `report`, `followup`) |
|
|
309
|
+
| `flybook.py` | turns a `flytalk.py` run into the Flybook feed (`docs/assets/flybook.json`) |
|
|
310
|
+
| `talk/`, `talk-fix/`, `talk-2ms/` | results of the three talking-flies runs (`results.json`; the raw `.npz` recordings are not committed) |
|
|
311
|
+
| `sshfighter/` | the SSH Fighter bot, dashboard and trained readout ([README](sshfighter/README.md)), built on `flybrain/reservoir.py` |
|
|
312
|
+
|
|
313
|
+
## What's next
|
|
314
|
+
|
|
315
|
+
* ~~A generic readout interface~~ done: `flybrain/reservoir.py`. Encoders (mapping images, sound,
|
|
316
|
+
odour-like patterns, sensor readings onto neuron groups) are still written per task -- see
|
|
317
|
+
ROADMAP.md for candidate tasks to try it on next.
|
|
318
|
+
* A benchmark: does the real wiring beat randomly rewired copies of itself on the same tasks?
|
|
319
|
+
The talking-flies control is the first data point, and it points both ways: scrambled wiring
|
|
320
|
+
carries nothing at 20 ms and as much as the real brain at 2 ms.
|
|
321
|
+
* Learning inside the brain through the mushroom body's dopamine rule, the way real flies learn.
|
|
322
|
+
* ~~A 3-D world~~ built as a prototype in [`world/`](world/)
|
|
323
|
+
([flyaiworld.com/simulation](https://flyaiworld.com/simulation/)). It runs a separate,
|
|
324
|
+
612-neuron model per fly, not the connectome.
|
|
325
|
+
* **Flybook:** people create their own fly (its senses, its temperament, which neuron types are
|
|
326
|
+
boosted or muted), and the flies post, react and set off chains of reactions from their real
|
|
327
|
+
signals.
|
|
328
|
+
* The same brain in a different body: driving a [Smol](https://opensea.io/collection/smols-752105135)
|
|
329
|
+
inside that world. The connectome stays frozen; only the encoder and the readout change.
|
|
330
|
+
|
|
331
|
+
## Credits
|
|
332
|
+
|
|
333
|
+
* **Connectome:** MaleCNS v1.0 by FlyEM (HHMI Janelia), the University of Cambridge, the MRC
|
|
334
|
+
Laboratory of Molecular Biology and Google Research. Data used under
|
|
335
|
+
[CC BY 4.0](https://male-cns.janelia.org/download/).
|
|
336
|
+
* **[Fly64](https://github.com/ornata/fly)** by Jessica Paquette, who got the MaleCNS brain
|
|
337
|
+
to play Super Mario 64. The neuron model, weight normalization and optic-column handling here
|
|
338
|
+
are adapted from it.
|
|
339
|
+
* **[Eon Systems](https://eon.systems/updates/embodied-brain-emulation)**, for the idea of
|
|
340
|
+
feeding a visual front end into an embodied connectome.
|
|
341
|
+
* Written with [Claude Code](https://claude.com/claude-code).
|
|
342
|
+
|
|
343
|
+
## References
|
|
344
|
+
|
|
345
|
+
1. Berg, S. et al. (2026). Sexual dimorphism in the complete connectome of the *Drosophila* male central nervous system. *Cell*. Data: [male-cns.janelia.org](https://male-cns.janelia.org)
|
|
346
|
+
2. Google Research (2026). [A connectomics milestone: mapping the complete male fruit fly brain](https://research.google/blog/a-connectomics-milestone-mapping-the-complete-male-fruit-fly-brain/)
|
|
347
|
+
3. flyconnectome/2025malecns: [optic column type assignments v1.0](https://github.com/flyconnectome/2025malecns)
|
|
348
|
+
4. Plaza, S. M. et al. (2022). neuPrint: an open access tool for EM connectomics. *Frontiers in Neuroinformatics* 16.
|
|
349
|
+
5. Dorkenwald, S. et al. (2024). Neuronal wiring diagram of an adult brain. *Nature* 634.
|
|
350
|
+
6. Shiu, P. K. et al. (2024). A *Drosophila* computational brain model reveals sensorimotor processing. *Nature* 634.
|
|
351
|
+
7. Wang-Chen, S. et al. (2024). NeuroMechFly v2: simulating embodied sensorimotor control in adult *Drosophila*. *Nature Methods* 21, 2353–2362.
|
|
352
|
+
8. von Reyn, C. R. et al. (2014). A spike-timing mechanism for action selection. *Nature Neuroscience* 17, 962–970.
|
|
353
|
+
9. Ache, J. M. et al. (2019). Neural basis for looming size and velocity encoding in the *Drosophila* giant fiber escape pathway. *Current Biology* 29, 1073–1081.
|
|
354
|
+
10. Ribeiro, I. M. A. et al. (2018). Visual projection neurons mediating directed courtship in *Drosophila*. *Cell* 174, 607–621.
|
|
355
|
+
11. Rayshubskiy, A. et al. (2020). Neural control of steering in walking *Drosophila*. *bioRxiv*.
|
|
356
|
+
12. Bidaye, S. S. et al. (2014). Neuronal control of *Drosophila* walking direction. *Science* 344, 97–101.
|
|
357
|
+
13. von Philipsborn, A. C. et al. (2011). Neuronal control of *Drosophila* courtship song. *Neuron* 69, 509–522.
|
|
358
|
+
14. Paquette, J. (2026). [Fly64: a fly brain model plays Super Mario 64](https://github.com/ornata/fly).
|
|
359
|
+
15. Eon Systems (2026). [How the Eon team produced a virtual embodied fly](https://eon.systems/updates/embodied-brain-emulation).
|
|
360
|
+
|
|
361
|
+
If you use the connectome data, cite reference 1 and follow the
|
|
362
|
+
[MaleCNS attribution terms](https://male-cns.janelia.org/download/).
|
|
363
|
+
|
|
364
|
+
## License
|
|
365
|
+
|
|
366
|
+
The code in this repository is released under the [MIT License](LICENSE).
|
|
367
|
+
|
|
368
|
+
The MaleCNS connectome data is **not** in the repository or the pip package. `flybrain build`
|
|
369
|
+
downloads it from its source; `flybrain download` fetches files derived from it (the normalized
|
|
370
|
+
weight matrix and neuron annotations). Both stay under the data's own [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/) license from
|
|
371
|
+
FlyEM (HHMI Janelia) and collaborators.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"""flybrain: the complete fruit fly nervous system (MaleCNS v1.0 connectome, 166,700 neurons)
|
|
2
|
+
as a spiking network you can stimulate, read out and train readouts on.
|
|
3
|
+
|
|
4
|
+
from flybrain import FlyBrain
|
|
5
|
+
brain = FlyBrain(device="auto") # downloads the brain files on first use
|
|
6
|
+
brain.stimulate(brain.cells(["LC4", "LPLC2"], side="L"), 0.8)
|
|
7
|
+
fired = brain.step() # indices of the neurons that spiked this 20 ms step
|
|
8
|
+
"""
|
|
9
|
+
from .brain import FlyBrain, cuda_available
|
|
10
|
+
from .data import DATA, download, ensure_data, has_data
|
|
11
|
+
from .eyes import ENCODER, Blob, Eyes, FeatureDetectors, blob_for
|
|
12
|
+
from .reservoir import Readout, Trace, auc, bases_for, fit_logistic, fit_ridge, folds, project, run
|
|
13
|
+
|
|
14
|
+
__version__ = "0.1.0"
|
|
15
|
+
|
|
16
|
+
__all__ = ["FlyBrain", "cuda_available", "DATA", "download", "ensure_data", "has_data",
|
|
17
|
+
"ENCODER", "Blob", "Eyes", "FeatureDetectors", "blob_for",
|
|
18
|
+
"Readout", "Trace", "auc", "bases_for", "fit_logistic", "fit_ridge", "folds", "project", "run"]
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"""Command line: `flybrain download`, `flybrain build`, `flybrain info` (or `python -m flybrain ...`)."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import argparse
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
from . import __version__
|
|
8
|
+
from .data import DATA, FILES, RELEASE_URL, download, has_data
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def main(argv: list[str] | None = None) -> None:
|
|
12
|
+
parser = argparse.ArgumentParser(prog="flybrain", description="The MaleCNS fruit fly connectome as a spiking network.")
|
|
13
|
+
parser.add_argument("--version", action="version", version=f"flybrain {__version__}")
|
|
14
|
+
sub = parser.add_subparsers(dest="command", required=True)
|
|
15
|
+
|
|
16
|
+
fetch = sub.add_parser("download", help="fetch the prebuilt brain files (~260 MB)")
|
|
17
|
+
fetch.add_argument("--data", type=Path, default=DATA, help=f"where to put them (default {DATA}, or $FLY_DATA)")
|
|
18
|
+
fetch.add_argument("--url", default=RELEASE_URL, help="base URL of the files (or $FLYBRAIN_DATA_URL)")
|
|
19
|
+
fetch.add_argument("--force", action="store_true", help="download again even if the files are there")
|
|
20
|
+
|
|
21
|
+
build = sub.add_parser("build", help="download MaleCNS v1.0 (~1.1 GB) and build the brain files from it")
|
|
22
|
+
build.add_argument("--data", type=Path, default=DATA, help=f"data folder (default {DATA}, or $FLY_DATA)")
|
|
23
|
+
|
|
24
|
+
info = sub.add_parser("info", help="show the data folder and whether a GPU is usable")
|
|
25
|
+
info.add_argument("--data", type=Path, default=DATA)
|
|
26
|
+
|
|
27
|
+
args = parser.parse_args(argv)
|
|
28
|
+
if args.command == "download":
|
|
29
|
+
download(args.data, args.url, force=args.force)
|
|
30
|
+
print(f"brain files in {args.data}")
|
|
31
|
+
elif args.command == "build":
|
|
32
|
+
try:
|
|
33
|
+
from .build import build as build_brain
|
|
34
|
+
except ImportError as e:
|
|
35
|
+
raise SystemExit(f"building needs pandas and pyarrow ({e}): pip install \"flybrain[build]\"")
|
|
36
|
+
build_brain(args.data)
|
|
37
|
+
else:
|
|
38
|
+
from .brain import cuda_available
|
|
39
|
+
print(f"flybrain {__version__}")
|
|
40
|
+
print(f"data folder: {args.data}")
|
|
41
|
+
for name in FILES:
|
|
42
|
+
path = args.data / name
|
|
43
|
+
print(f" {name}: {f'{path.stat().st_size / 1e6:,.0f} MB' if path.exists() else 'missing'}")
|
|
44
|
+
if not has_data(args.data):
|
|
45
|
+
print(" run `flybrain download` (or just create a FlyBrain) to fetch them")
|
|
46
|
+
gpu = "available" if cuda_available() else 'not available (pip install "flybrain[gpu]")'
|
|
47
|
+
print(f"cuda: {gpu}")
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
if __name__ == "__main__":
|
|
51
|
+
main()
|