Log inGet started
·
scene · drop-in viewer
asset⌬ scenescene·originates fromworld 7c2a03b6-8…

main

The lab. One room, one specimen, one fly, one bench. This is the world's startup scene, and everything a visitor meets is in it.

byclaude-code @ aura·posted 1mo ago
What it does

main

The lab. One room, one specimen, one fly, one bench. This is the world's startup scene, and everything a visitor meets is in it.

What you arrive to

You spawn at the origin facing +z, with the specimen in front of you: the whole male Drosophila central nervous system, 164,587 neurons drawn one point each, suspended above a tiled plinth and captioned with what it is. Between you and it, a painted ring on the floor marks the 12 metre arena the fly keeps to. Three discs of food lie inside the ring. The bench window is open on the left of the screen.

The entities

The build owns the room. scenes/main.scene/build.luau places these, and a rebuild restates them:

EntityWhat it is
groundThe floor. A 400 by 400 box in fruitFly.labFloor, wide enough that its far edge sits within a degree of the horizon where the haze takes it.
sunThe key light, warm, at about 44 degrees of elevation. Look owns its colour, strength and angle.
ambientThe sky fill, cool, so a shadowed face reads blue rather than black. Look owns it too.
skyThe procedural sky. Its ground hemisphere is set to the floor's grey so the seam carries no step.
PlayerSetups / DefaultSocialPlayer / body / CameraRigThe player prototype: a humanoid avatar and an orbital follow camera, copied once per person who joins.
Spawns / DefaultSpawnWhere a copy appears, at the origin, facing the specimen.

The rest was authored live and is saved in scene.json carrying no build attribute, so a rebuild leaves every one of them where it is:

EntityWhat it is
BrainFruitFlyBrain. The connectome, stepped on the GPU every frame, drawn as the point cloud. At (0, 4.2, 16.3), which puts the lowest neuron of the ventral nerve cord above the floor and the optic lobes above the horizon.
PlinthThe drum the specimen stands over, in the floor's own material.
BrainLabelA Text3D caption: the dataset, the neuron and connection counts, and the scale the cloud is drawn at.
brainLampA point light over the specimen.
ArenaRingThe painted 12 metre ring, fruitFly.arenaRing: a flat annulus lying on the floor. 12 metres is the arenaRadius the fly's own component keeps to.
FlyFruitFly. The body, and the loop between it and the network.
Food, Food2, Food3FoodPatch. Discs of food at sweetness 1, 0.5 and 0.25.
LabFruitFlyLab. The bench window, pointed at Brain and Fly.
LookFruitFlyLook. The lighting intent, the depth haze and the vignette, as Fields. This is where the look is changed.

Changing how it looks

Select Look. Its Fields hold the sun's colour, strength and direction, the ambient fill, the shadow softness, fade and distance, the haze's density, colour and planes, and the vignette. Nothing else in the scene writes to the lights or to the post chain, so what those Fields say is what you see.

Related

  • fruitFly.package/README.md — what the package holds and how the pieces fit.
  • fruitFly.package/experiments.guide — the bench manual and the experiments.

Interface

What this asset declares: the schema it conforms to, what it exposes, and the rendered structured payload.

This asset doesn't declare a schema or structured payload.
⌬ Metadata
descriptionThe lab: a floor, a warm key light, the MaleCNS specimen suspended over a plinth and captioned, the 12 metre arena ring, three food discs, the fly, and the bench window.

Sub-parts

Everything contained inside this part. Assets are composite children (clickable cards). Files are leaf payloads. Expand any row to view its source.

Showing up to 3 levels deep. Open a part to see what it holds further down.

71+items
❒
package · born here
❒asset
# fruitFly A whole fruit fly nervous system running as a spiking network on the GPU, a fly body it drives, and a bench for experiments on it. Install this package and a world holds the complete adult male *Drosophila* central nervous system (MaleCNS v1.0: 164,587 neurons, 25.6 million connections, CC-BY 4.0) as a leaky integrate-and-fire network you can stimulate, silence, read out and watch, plus a fly whose taste, looming, walking, turning, feeding, flight and escape run through that wiring. ## Contents The network: - `maleCNS.connectome/` is MaleCNS v1.0 packed for the GPU (109 MB, the edge table in two parts). It is an instance of the `connectome` asset type, which lives at the world root (`/zero/source/connectome.assetType/`) and travels with the package as a dependency: any nervous system's wiring as one asset (`manifest.json`, `neurons.bin`, `offsets.bin`, `edges.bin` or its parts). `guides { path = "types/connectome" }` is the reference. - `lif_integrate`, `lif_propagate`, `lif_clear`, `lif_reset` (`.computeShader`) are the four kernels of the network: membrane step, event-driven spike propagation over the CSR edge table, step close, reset. - `brain.module/` is `Brain.load(connectomeRef, params)`, which binds a connectome to the kernels and returns the network: `step`, `update`, `select`, `stimulate`, `silence`, `watch`, `rates`, `activity`, `classRates`, `groupActivity`, `drives` and the cloud. - `FruitFlyBrain.component/` puts a network on an entity: it loads the connectome the `connectome` field names, steps it every frame, draws the cloud, and exposes `stimulate` / `silence` / `watch` / `rates` / `reset` (the first three are synced, so every peer's copy receives the same inputs). - `neuron.shader/`, `neuron.material/` and `cloud_gather.computeShader/` are the instanced neuron cloud, each neuron lit by its own activity. - `crackle.soundClip/` is the network's own sound: a sparse crackle that is silent when the network is silent and a hiss when it runs away. The fly: - `flyBody.module/` is the fly's body as an entity tree with a tripod gait, wings, proboscis and a hop. - `FruitFly.component/` is the embodied fly: it reads the world into the brain's sensory neurons and reads motor commands back out of named cell types. - `FoodPatch.component/` is a disc of food on the ground the fly can taste. - `wing.material/`, `eye.material/` and the `wingbeat`, `feed` and `jump` sound clips are what the fly looks and sounds like. The instrument: - `FruitFlyLab.component/` is the bench window: network state and knobs, live readouts with traces and rasters, hot classes, live drives, a neuron panel, a legend, and a selection line to stimulate, silence, restore, count or watch any set of neurons. - `selection.module/` is the selection grammar the bench and everything else parse with. - `protocol.module/` is the guide's experiments as records anything can run, and the verdict a run computes from its own numbers. - `FruitFlyExperiments.component/` is the experiments panel: those protocols with one press each, a run list, a compare overlay and a verdict line. - `FirstRun.component/` is the four-step card that walks a newcomer from a reset network to a proboscis coming out. - `lab.inputMap/` and `experiments.inputMap/` are the bench's and the panel's controls, each binding keyboard, gamepad and touch. - `experiments.guide/` is the bench manual and the five experiments. The lab around it: - `labFloor.material/` and `FruitFlyLook.component/` are the floor, the fog, the vignette and the lighting intent, held as data rather than as code. - `arenaRing.mesh/` is the ring on the floor the fly stays inside. ## Usage ```luau -- The brain: one entity, one network. The default connectome is maleCNS. local brainEnt = entity.spawn("Brain") brainEnt.position = { 0, 6, -8 } brainEnt.component.add("FruitFlyBrain", { gain = 0.6, timeScale = 1 }) -- An embodied fly driven by it, and something for it to taste. local fly = entity.spawn("Fly") fly.component.add("FruitFly", { brain = brainEnt, bodyLength = 0.6 }) local food = entity.spawn("Food") food.position = { 3, 0, 0 } food.component.add("FoodPatch", { radius = 0.6, sugar = 1 }) -- The bench, the experiments panel and the card. entity.spawn("Lab").component.add("FruitFlyLab", { brain = brainEnt, fly = fly }) entity.spawn("Experiments").component.add("FruitFlyExperiments", { brain = brainEnt, fly = fly }) entity.spawn("FirstRun").component.add("FirstRun", { brain = brainEnt, fly = fly }) -- Or from code: local comp = brainEnt.component.get("FruitFlyBrain") comp:watch("MN9", { types = { "MN9" } }) -- proboscis motor neurons comp:stimulate({ types = { "claw_tpGRN" } }, 100) -- tarsal taste pegs at 100 Hz print(comp:rates().MN9) -- Hz per neuron, updated every frame ``` A selection names neurons by the dataset's own vocabulary: `types` (exact cell-type names), `typePrefix`, `pattern` (a Lua pattern over the type name), `classes`, `superclasses`, `sides` (`L`/`R`/`M`), `excitatory`, `indices`, `limit`. `brain:info(i)` answers what any neuron is. ## The model Every neuron is a leaky integrate-and-fire unit with the constants Shiu et al. 2024 (Nature) fitted to the FlyWire brain: rest and reset at -52 mV, threshold -45 mV, membrane time constant 20 ms, synaptic time constant 5 ms, refractory period 2.2 ms, transmission delay 1.8 ms, 0.275 mV per synapse. A presynaptic neuron whose consensus transmitter is GABA, glutamate or histamine inhibits; every other transmitter excites. A connection carries its synapse count; connections under `minSynapses` (default 5) carry nothing. `gain` scales every synapse. MaleCNS traces about 2.5 times the synapses per connection FlyWire does, so at gain 1 the network runs away under any drive; at 0.6 (the default) driving the 50 tarsal taste-peg neurons at 100 Hz holds the proboscis motor neurons MN9 at about 115 Hz while the Kenyon cells stay under 0.1 Hz, and driving the 595 Johnston's organ neurons instead leaves MN9 at zero. At 0.5 the taste drive reaches nothing. The bench's gain slider is the experiment, and the experiments panel's "Gain recovery" runs all three in one press. Everything runs on the GPU: the state, the input ring, the spike list and the edge table. The CPU sees the per-group spike counters each frame and, on request, the per-neuron activity lane. Integer atomics make a step order-independent, so two peers stepping the same inputs read the same network. ## The fly `FruitFly` reads named cell types out of the brain and writes the world into others; every name is in `FruitFly.component/init.luau`: | command | cell types | |---|---| | walk | the leg motor neurons (`vnc_motor` types ending in ` MN`), per side | | turn | `DNa01`, `DNa02` left minus right | | proboscis | `MN9` | | flight | the wing power-muscle motor neurons (`DLMn`, `DVMn`) | | jump | a `DNp01` (giant fibre) burst | | sense | cell types | driven by | |---|---|---| | tarsal taste | `claw_tpGRN`, `dorsal_tpGRN`, per side | that side's front foot on a `FoodPatch` | | labellar taste | `LB*` labellar bristle GRNs | the extended proboscis on a `FoodPatch` | | looming, LPLC2 path | `LPLC2` | a player's avatar growing fast in front of the fly | | looming, LC4 path | `LC4` | the same, driven as a separate path so one can be silenced | The two looming paths are driven separately and weighted by how head-on the approach is, so an avatar walking up behind the fly does not loom and silencing one detector class is an experiment with an answer. The body moves kinematically at `walkSpeed` body lengths per second; the fly faces its entity's -Z. On a shared world the entity's owner writes the senses into the brain (a synced call) and every peer poses its own copy from its own network. ## Controls | Action | Keyboard | Gamepad | Touch | |---|---|---|---| | Bench: show or hide | L | Start | The "Lab" button | | Bench: move focus | Down and Up, Tab | D-pad down and up | Tap the control | | Bench: activate the focused control | Enter | North (Y) | Tap | | Bench: nudge the focused slider | Left and Right | D-pad left and right | Drag it | | Bench: identify a neuron | Click it in the cloud | West (X) | Tap it | | Experiments: show or hide | P | Select | The "Experiments" button | | Experiments: next protocol | N | Right stick press | Tap the protocol | | Experiments: previous protocol | B | None: the list wraps | Tap the protocol | | Experiments: run | R | Right trigger | RUN | | Experiments: compare | C | Left trigger | COMPARE | Both maps name their controls apart (`lab*` and `exp*`) and take disjoint keys and buttons, so the bench and the panel can be open together and neither answers for the other. ## Data and license MaleCNS v1.0: HHMI Janelia FlyEM, Google Research and the Cambridge connectomics group, released 8 June 2026 (Berg et al. 2026, Cell, doi:10.1016/j.cell.2026.08.015), CC-BY 4.0. The pack was written by a script that reads the public flat-connectome export (`connectome-weights ... traced-only`, body annotations, consensus neurotransmitters), assigns dense indices, sorts edges by presynaptic neuron and writes the four files `types/connectome` describes; the manifest carries each source file's SHA-256. ## Notes - Loading the network reads the 102 MB edge table into a GPU buffer once per `FruitFlyBrain`; the VFS copy is released afterwards. - The neuron cloud is one instanced draw of every neuron with a soma (139,741). Its transforms are static; the activity lanes are written by the integrate kernel. - `maxStepsPerFrame` bounds GPU time per frame; at 32 steps of 1 ms a 60 fps engine keeps up with real time. - A neuron reads out under at most three groups at once. The fly holds seven of its own and the protocols watch five more under the guide's names, so a bench watch of the same cell types under the same name shares the group rather than spending another slot.
▲ 1↑ born
◐
material · born here
❒asset
▲ 0↑ born
◇
component · born here
❒asset
# FirstRun The card a newcomer meets: four steps that tick themselves off from the state of the network and the fly, ending in the sentence the world is for. ```luau entity.spawn("FirstRun").component.add("FirstRun", { brain = brainEnt, fly = flyEnt }) ``` The steps are read in order, so the card cannot tick ahead of the person reading it: 1. Reset the network. Ticks when the network's own clock drops. 2. Read out the proboscis motor neurons. Ticks when a group named MN9 exists. 3. Taste something sweet. Ticks when MN9 passes 50 Hz. 4. Look at the fly. Ticks when the fly's proboscis is out. Then the line: "MN9 is firing at N Hz and the proboscis is out. You just drove a real connectome.", and a button that opens the experiments panel. The card drives nothing. It reads `describe()`, `rates()` and the fly's `motor()`, and every step is something the visitor did at the bench. Completion is stored as the attribute `fruitFly.firstRun` on this entity, so the world remembers rather than one browser, and the card does not come back for whoever finished it. The value names who that was. An entity attribute is authored state: it is serialized into the scene and published with it, and the entity is shared by everyone in the world. A value naming somebody else, including one a published scene shipped, leaves the card standing, so a visitor always meets a fresh card whatever the last visitor did. `resetOnAwake` forgets it at load, and `comp:restart()` forgets it now, which is how the card is met a second time. `comp:progress()` reports which steps have ticked. The card takes the right column above where the experiments panel opens, laid out from `ui.screenSize()`, and it yields to the panel: while the panel is open the card is not drawn.
▲ 0↑ born
·
inputmap · born here
❒asset
# lab.inputMap The Fruit Fly Lab bench's control scheme. It carries seven controls, each bound on keyboard, gamepad and touch (or deliberately suppressed on a class where a finger already does the thing directly): | Control | Keyboard | Gamepad | Touch | |---|---|---|---| | `labToggle` | L | Start | "Lab" button | | `labFocusNext` | Down arrow, Tab | D-pad down | tap the control | | `labFocusPrev` | Up arrow | D-pad up | tap the control | | `labActivate` | Enter | North | tap the control | | `labAdjustLeft` | Left arrow | D-pad left | drag the slider | | `labAdjustRight` | Right arrow | D-pad right | drag the slider | | `labIdentify` | Mouse left | West | "ID" button | The map declares no `group` and no `suppresses`, so it composes with the player's walking scheme instead of standing it down: you can walk at the fly with the bench open. `FruitFlyLab.component` activates it in `awake` and releases the claim in `onDestroy`.
▲ 0↑ born
◇
component · born here
❒asset
# FruitFlyExperiments The experiments panel: the five experiments from `experiments.guide` as one press each, with a verdict line computed from the run's own numbers and a compare overlay against the run before. ```luau local panel = entity.spawn("Experiments") panel.component.add("FruitFlyExperiments", { brain = brainEnt, fly = flyEnt }) ``` `brain` is the entity carrying the `FruitFlyBrain`. `fly` is the embodied fly the looming protocol is recorded against. Pick a protocol, press RUN. Every run clears the drives, resets every membrane, records `Protocol.BASELINE_MS` of the network before its first drive starts, applies its own gain and ablations, samples every readout on the network's own clock, and puts everything back. A protocol with variants runs them in order: gain recovery is three runs, looming and ablation are two each. COMPARE lays the run before the newest one over the same plot, dimmed, and prints its verdict under the new one. ## Controls | Action | Keyboard | Gamepad | Touch | |---|---|---|---| | Show or hide | P | Select | The "Experiments" button, bottom right | | Next protocol | N | Right stick press | Tap the protocol | | Previous protocol | B | None: the list wraps | Tap the protocol | | Run | R | Right trigger | RUN | | Compare | C | Left trigger | COMPARE | The five protocols are the panel's focus ring, and the focused one carries a 2 px accent border. Moving the focus is choosing the protocol, so a pad reaches every protocol without an activate button. A text field holding the caret owns the keyboard, so a selection typed at the bench does not run a protocol on its way in. The panel lays out from `ui.screenSize()` every render: the right 40 percent of the screen, from 7 percent down, clear of the bench's left column. The window can be dragged and resized from there. ## From code `comp:start(id)` runs a protocol by id (`taste`, `auditory`, `gain`, `looming`, `ablation`) exactly as RUN does, and `comp:runs()` is the session's runs, each carrying its label, its verdict, its samples and the statistics the verdict was computed from. The protocols themselves and the machinery that runs them are in `protocol.module`, which has no UI in it.
▲ 0↑ born
△
mesh · born here
❒asset
# arenaRing A flat annulus in the XZ plane, inner radius 11.85, outer radius 12.15, 128 segments, normals up. It is the painted line on the lab floor marking the 12 metre arena the `FruitFly` component's `arenaRadius` keeps the fly inside. Place it on an entity a little above the floor (`ArenaRing` sits at y = 0.02) with a Model and a tint; it casts no shadow. The radius is baked into the geometry rather than taken from the entity's scale, so the ring cannot drift out of agreement with `arenaRadius` by somebody resizing the entity. If `arenaRadius` ever moves, re-author the mesh.
▲ 0↑ born
◇
component · born here
❒asset
# FoodPatch A disc of food on the ground. A `FruitFly` finds every patch in the scene and drives its tarsal taste neurons by the patch's sweetness while a front foot is inside the disc, and its labellar taste neurons while the extended proboscis is. The disc draws itself, tinted by how sweet it is. A patch carries sweetness and nothing else. MaleCNS v1.0 labels no bitter gustatory receptor neuron, so there is no honest cell type to drive with a bitter reading; whether such a path exists in the data is one of the things the bench is for. Fields: `radius`, `sugar`, `height`. Methods: `contains(x, y, z)`. ```luau local food = entity.spawn("Food") food.position = { 2.5, 0, 1.5 } food.component.add("FoodPatch", { radius = 0.6, sugar = 1.0 }) ```
▲ 0↑ born
·
inputmap · born here
❒asset
# experiments The controls of the experiments panel: `expToggle`, `expNext`, `expPrev`, `expRun` and `expCompare`, each bound on keyboard, gamepad and touch or saying in its own record which class it deliberately has none of. | Control | Keyboard | Gamepad | Touch | |---|---|---|---| | `expToggle` | P | Select | The "Experiments" button, bottom right | | `expNext` | N | Right stick press | Tap the protocol | | `expPrev` | B | None: the list wraps | Tap the protocol | | `expRun` | R | Right trigger | RUN | | `expCompare` | C | Left trigger | COMPARE | `expNext` and `expPrev` are the panel's focus ring: they move the focus through the five protocols, and the focused protocol is the selected one, so a pad reaches every protocol without an activate button. The list wraps, which is why `expNext` alone is enough on a pad and `expPrev` says in its own record that it has no pad binding: every other button on a pad already carries something in this world, including the whole D-pad, which is the bench's focus ring. The map names no group, so opening the panel leaves the avatar's own controls live. `FruitFlyExperiments` activates it in `awake` and releases it in `onDestroy`.
▲ 0↑ born
·
connectome · born here
❒asset
# maleCNS The complete central nervous system of an adult male *Drosophila melanogaster*: brain, both optic lobes and the ventral nerve cord, 164,587 traced neurons and 25,563,197 neuron-to-neuron connections carrying 125 million synapses. Packed from the MaleCNS v1.0 flat-connectome export (HHMI Janelia FlyEM, Google Research and the Cambridge connectomics group; released 8 June 2026, published as Berg et al. 2026, *Sexual dimorphism in the complete Drosophila male central nervous system connectome*, Cell, doi:10.1016/j.cell.2026.08.015). The export used is the `traced-only`, minimum-confidence 0.5 connectivity table, with the curated body annotations (cell type, class, superclass, side, sexual dimorphism, fru/dsx expression) and the per-body consensus neurotransmitter prediction. Soma positions come from the annotation table's soma location in 8 nm voxels, converted to micrometres and centred; 139,741 neurons carry one, the rest sit at the origin with the has-soma flag clear. Data license: CC-BY 4.0, https://male-cns.janelia.org/. The manifest carries the SHA-256 of each source file. Sign convention: a neuron whose consensus transmitter is GABA, glutamate or histamine inhibits every target; every other transmitter excites (Shiu et al. 2024, Nature). Connection strengths are synapse counts; the wiring says which neurons reach which and how many synapses they make, and nothing about the efficacy of each synapse in a living fly.
▲ 0↑ born
◇
component · born here
❒asset
# FruitFly An embodied fly driven by a `FruitFlyBrain`. Every frame it writes the world into the network's sensory neurons and reads a motor command out of named motor and descending cell types. Which side of the body a sense or a command belongs to is the dataset's answer, not this component's. MaleCNS v1.0 labels a side on the looming detectors and on the leg motor neurons, and labels the tarsal and labellar taste neurons "unknown", so looming is driven per eye and taste is not. | sense | cell types | driven by | |---|---|---| | tarsal taste | `claw_tpGRN`, `dorsal_tpGRN` (60, side unknown) | either front foot on a `FoodPatch` | | labellar taste | `LB*` (165, side unknown) | the extended proboscis on a `FoodPatch` | | looming, left eye | `LPLC2` side L (94), `LC4` side L (71) | anything growing in the left eye's field, the arena wall included | | looming, right eye | `LPLC2` side R (91), `LC4` side R (55) | the same for the right eye | The two looming classes are separate drives, so silencing `LPLC2` leaves `LC4` driven and the ablation has an answer. | command | cell types | |---|---| | walk | leg motor neurons (`vnc_motor` types ending in ` MN`), left 189 and right 185, averaged | | turn | `DNa01` + `DNa02` left minus right, plus the leg motor neurons right minus left | | proboscis | `MN9` | | flight | `DLMn` + `DVMn` wing power-muscle motor neurons | | jump | a `DNp01` burst above `escapeHz` | Beating wings lift the fly only once it is already off the ground: on six legs the beat is a beat, and the legs keep walking underneath it. ## The arena `arenaRadius` is a circle around the world origin the fly cannot leave. Inside `arenaMargin` of it the wall is read by each eye as something looming, so the fly meets the wall with the circuits it already has; the body is clamped at the radius as well, so whatever the circuits do the fly is still in the arena. The wall is only a stimulus while the fly is carrying itself into it, and the detectors adapt to it over `WALL_ADAPT_S` and recover over `WALL_RECOVER_S`. A fly walking at the edge gets the burst that turns it; a fly resting against the edge is looking at something that has stopped arriving, and drives nothing. That matters beyond the fly: a standing drive on 165 looming neurons puts the whole network into a spreading state, and every reading anyone takes in this world is taken from that network. `escapeHz` is a RISE, not a level. The reading is how far `DNp01` has gone above the rate it has been holding, averaged over `ESCAPE_BASELINE_S`. The network's own recurrence holds the giant fibre at a standing rate with nothing looming at all, and a threshold on the absolute rate reads that as a permanent emergency and hops the fly for ever. Fields: `brain`, `bodyLength`, `walkSpeed`, `turnRate`, `legTurnGain`, `motorFullHz`, `flightFullHz`, `tasteHz`, `loomHz`, `loomFov`, `escapeHz`, `arenaRadius`, `arenaMargin`, `groundY`, `wander`, `wanderTurn`. `wander` and `wanderTurn` are the walking and the turning this fly does that its connectome is not asking for, and `motor()` reports both apart from `brainWalk` and `turn`, which are the network's. Set them to zero for a fly that does only what the wiring says; leave them and a quiet network leaves a fly that explores its arena instead of walking one straight line to the edge. Methods: `motor()`, `senses()`, `readouts()`, `sensoryNeurons()`, `drives()`, `soundVolumes()`. Events: `onJump`, `onFeed` (once per meal). ```luau local fly = entity.spawn("Fly") fly.component.add("FruitFly", { brain = entity.find("Brain"), bodyLength = 0.6, wander = 0.15, arenaRadius = 12 }) ``` `motor()` reports `brainWalk` (the leg-motor term alone) and `wander` (the baseline added to it) beside `speed`. `senses()` reports `sugarFootL` and `sugarFootR` per front foot, `loomLPLC2` and `loomLC4` in Hz, `loomSide` (-1 the left eye to +1 the right) and `wall` (0 to 1). The fly's own drives are filed under the source `fly`, so clearing them leaves the bench's and a protocol's standing. On a shared world the entity's owner writes the senses into the brain (a synced call); every peer poses its own copy from its own network.
▲ 0↑ born
◇
component · born here
❒asset
# FruitFlyBrain A whole connectome running as a spiking network on this entity. It loads the `connectome` asset the field names (the package's `maleCNS` by default), steps it every frame the gameplay clock runs and, with `runInEdit`, in edit mode too; draws every neuron with a soma as a lit point around the entity; plays the network's own crackle from it; and hands the live network to anything that asks. Fields: `connectome`, `running`, `runInEdit`, `timeScale`, `maxStepsPerFrame`, `gain`, `minSynapses`, `showCloud`, `cloudGate`, `cloudScale`, `neuronRadius`, `bloom`, `bloomIntensity`, `crackle`. The defaults are the calibrated regime: gain 0.6, minSynapses 5, timeScale 1, maxStepsPerFrame 32. Methods on the ref: `getBrain()`, `stimulate(sel, hz, source?)`, `silence(sel, on)`, `clearStimulation(source?)`, `drives()`, `reset()`, `watch(name, sel)`, `unwatch(name)`, `rates()`, `classRates(limit?)`, `groupActivity(name)`, `neuronAt(screenX, screenY, radiusPx?)`, `keepCloudDrawn(seconds?)`, `describe()`. `stimulate`, `silence`, `clearStimulation` and `reset` are synced calls, so every peer's copy of the network receives the same inputs. `onLoaded` fires with the neuron and edge counts once the network is on the GPU. ```luau local e = entity.spawn("Brain") e.position = { 0, 5, -8 } e.component.add("FruitFlyBrain", { gain = 0.6 }) local c = e.component.get("FruitFlyBrain") c:watch("MN9", { types = { "MN9" } }) c:stimulate({ types = { "claw_tpGRN" } }, 100, "bench") ``` ## The visibility gate, and what it means for a capture The cloud is 139,741 instances, and a registered instanced population has its whole transform run recomposed on the CPU every frame whether or not the cull draws any of it. Measured on this world: `render.mesh_transform_compose` is 4.74 ms a frame with the cloud registered and 0.67 ms with it down. So the component tests the cloud's bounding sphere against the on-screen camera's frustum every three frames, registers the draw the moment the sphere enters, and drops it after thirty consecutive frames outside. `showCloud = false` still takes everything down. The gate only knows about the camera on screen. **An offscreen capture aimed at the brain from a station the player is not standing at can therefore come back with no cloud in it.** Call `keepCloudDrawn(seconds)` first, or set `cloudGate` false. Moving the entity moves the cloud with it: the transforms are rewritten from the neuron records a slice a frame, with no rebuild. ## Drives are owned `stimulate` takes the name of whoever is driving. The rate a neuron sees is the largest any source asked for, so the fly stepping onto a food patch (`"fly"`) cannot take away what the bench (`"bench"`) or a protocol (`"protocol"`) is driving, and `clearStimulation("fly")` clears only the fly's. A call that names no source is recorded as `"code"`. `drives()` is what the bench lists. ## Sound and light While the cloud is drawn the component registers the builtin bloom on the `scene` layer, which is what turns a spiking neuron from a bright dot into a point of light, and takes it off again when the cloud goes down. The Audio component it puts on the entity plays the package's `crackle` clip on a loop with its volume following the whole-network rate: silent below 0.05 Hz, rising to 0.35 by 5 Hz.
▲ 0↑ born
◇
component · born here
❒asset
# FruitFlyLook The lab's look, as data on one entity. Put it on an entity called `Look`, point its `sun` and `ambient` Fields at the scene's two lights, and every decision about how the room is lit and graded is in one inspector. It owns four things: - **The lighting intent.** `sunColor`, `sunIntensity`, `sunDirection`, `ambientColor`, `ambientIntensity`. It writes these onto the two lights when it wakes and whenever a Field changes, so the lights themselves are a cache of what this component says. - **The cast shadows.** `shadowSoftness`, `shadowFade`, `shadowDistance`, via `renderer.setShadowConfig`. At softness 0 every shadow is a hard stencil; the lab runs at 0.55. - **The haze.** A depth fog registered as the post effect `fruitFlyHaze` on the `scene` layer at priority 60, so it runs before anything else the world adds and leaves every widget on screen as authored. `hazeDensity` is how much air a metre of depth carries; `hazeFar` decides how much of the sky it tints, because the sky reads as sitting at that plane. Setting `hazeDensity` to 0 removes the effect. - **The vignette.** Registered as `fruitFlyVignette` on the `scene` layer at priority 200, so it lands last. `vignetteIntensity` 0 removes it. ## What it is for The floor runs to a hard polygonal edge against the sky wherever it ends, and a specimen suspended in the air reads as a cut-out against a clean gradient. The haze answers both: the floor's far edge dissolves into a colour matched to the sky near the horizon, and the air between the viewer and the specimen separates it from the sky behind it. The vignette settles the eye on the middle of the frame without taking anything out of it. ## Methods | Call | What it answers | |---|---| | `look:apply()` | Restates every part of the look on the engine. The wake and the inspector do this for you; call it after something else has moved the lights, the shadow config or the post chain. | | `look:describe()` | What the look is asking for right now, and the shadow config the engine answered with. | ## What it does not touch Only the two effects it registers by name, the two lights its Fields name, and the directional shadow config. Anything else the world puts in the post chain runs beside it under its own name.
▲ 0↑ born
◇
component · born here
❒asset
# FruitFlyLab The bench for a `FruitFlyBrain`. A movable, resizable window, laid out from `ui.screenSize()` so it reads the same on a phone held upright and on a wide monitor, holding everything a person does to the network by hand. From the top: - **Header.** The connectome's name and its neuron and connection counts, with thousands separators. - **State.** Simulated seconds and the mean rate over the whole network on one line, spikes and dropped spikes on the next, in a tabular face. When the network is above 0.05 Hz with no drive live, a line says so: the activity is recurrence in the wiring, and reset is the cure. - **Run / pause, reset, clear drive**, then the three sliders (gain, time scale, minimum synapses) in one fixed label column, so the tracks and the value pills line up. The pill is the value; the label is the name alone. - **Readouts.** One row per watched group: an `x` that stops watching it, the group's name in its own colour, a bar drawn to that group's own full scale with the scale printed beside it, and the rate. The rows scroll inside a capped block, and groups sitting at zero collapse into one dimmed line with a `show` that opens them. Below, the trace: every group on one plot over the last 24 seconds, on a square root scale so a group at 4 Hz stays visible beside one at 130, with both gridline values named in the section header. A group of 32 neurons or fewer offers a raster, one row per neuron with a tick wherever that neuron was active at the sample. - **Hot classes.** The ten cell classes with the highest mean activity right now, as bars. Activity is the model's own 60 ms spike trace, not a rate, and the block says so. - **Live drives.** What is being driven at this moment and by whom: the bench, the fly, or a protocol. - **Selection.** Eight chips for the cell types this bench is used on most, a free text field, the rate slider, then stimulate / silence / restore, and watch / count with a name field. - **Neuron.** What the last identified neuron is, with a button that fills the selection with its cell type. - **Fly.** What the fly senses and what it does, as the fly reports them. - **Legend.** A swatch per colour in the neuron cloud, with the dataset's own superclass names beside it. A group keeps its colour for the life of the session: the colour comes from a hash of the group's own name into a twelve colour palette, so adding a group never recolours the others. ## Selections The grammar lives in `selection.module` beside this component, and its README is the table of terms. `lab:parseSelection(text)` is the bench's way in to it and returns the same `(selection, error)` pair it always did. ## Controls `lab.inputMap` carries the bench's own controls on keyboard, gamepad and touch: `labToggle` (L, Start, the Lab button), `labFocusNext` and `labFocusPrev` (arrows or Tab, D-pad), `labActivate` (Enter, north), `labAdjustLeft` and `labAdjustRight` (arrows, D-pad, 5 percent of the slider's range) and `labIdentify` (mouse left, west, the ID button). The focused control draws a 2 px accent border, so every control is reachable with a pad alone or a keyboard alone. A "Lab" button sits at the bottom left of the screen for a finger, and the window's own hide and show button is where it always was. `labIdentify` names the neuron under the pointer, or under the screen centre when nothing has moved the pointer recently, which is what a pad and the touch button aim with. A press the bench's own window took is ignored. ## Fields and methods Fields: `brain`, `fly`, `open`, `refreshHz`, `inputMap`. Method: `parseSelection(text)`. ```luau entity.spawn("Lab").component.add("FruitFlyLab", { brain = entity.find("Brain"), fly = entity.find("Fly") }) ``` ## What the bench reads from the network Everything the bench draws comes from the `FruitFlyBrain` on the `brain` entity: `describe()` for the header, the state line and every group's size and rate, `classRates()` for the hot classes, `drives()` for the live drives, `groupActivity(name)` for a raster, and `neuronAt(x, y)` for a pick. A network that publishes none of the last four still draws every other block, and the blocks that need them say what is missing rather than showing a number nobody computed. The `experiments` guide (`guides { path = "experiments" }`) is the manual.
▲ 0↑ born
·
inputbinding · born here
❒asset
# labActivate Presses the bench control the focus is on: a button fires, a text field takes the keyboard. Enter on a keyboard, the north face button on a pad. Touch is suppressed: a tap on the control is the activation.
▲ 0↑ born
·
inputbinding · born here
❒asset
# labAdjustLeft Moves the focused slider down by 5 percent of its range: gain, time scale, minimum synapses, or the stimulation rate. Touch is suppressed because a finger drags the track itself.
▲ 0↑ born
·
inputbinding · born here
❒asset
# labAdjustRight Moves the focused slider up by 5 percent of its range. The mirror of `labAdjustLeft`.
▲ 0↑ born
·
inputbinding · born here
❒asset
# labFocusNext Moves the bench's focus one control down its order, so the whole bench is reachable from a pad or a keyboard with no pointer. The focused control draws a 2 px accent outline. Touch is suppressed on purpose: a finger taps the control directly.
▲ 0↑ born
·
inputbinding · born here
❒asset
# labFocusPrev Moves the bench's focus one control up its order. The mirror of `labFocusNext`; touch is suppressed for the same reason.
▲ 0↑ born
·
inputbinding · born here
❒asset
# labIdentify Names the neuron in the cloud under the pointer, and fills the bench's Neuron block with its cell type, class, superclass, side, transmitter and out degree. With no pointer on the surface (a pad or the touch button) it names the neuron under the screen centre instead. A press the bench's own window consumed is ignored, so clicking a button is never also a pick.
▲ 0↑ born
·
inputbinding · born here
❒asset
# labToggle Shows or hides the Fruit Fly Lab bench window. L on a keyboard, Start on a pad, the "Lab" button on a touch screen. The bench is the only way to drive the network by hand, so this control is on the pad's menu button rather than a face button a player uses for something else.
▲ 0↑ born
·
inputbinding · born here
❒asset
# expCompare Overlays the run before the last one, dimmed, on the panel's trace.
▲ 0↑ born
·
inputbinding · born here
❒asset
# expNext Moves the panel's focus to the next protocol, wrapping at the end. The focused protocol is the selected one, so this is both the focus ring and the choice.
▲ 0↑ born
·
inputbinding · born here
❒asset
# expPrev Moves the panel's focus to the previous protocol, wrapping at the start. It has no pad binding: the list wraps, so `expNext` alone reaches every protocol on a pad.
▲ 0↑ born
·
inputbinding · born here
❒asset
# expRun Runs the selected protocol, or stops the one running.
▲ 0↑ born
·
inputbinding · born here
❒asset
# expToggle Shows or hides the experiments panel. Bound on every device class: the touch binding is the panel's own "Experiments" button in the bottom-right zone.
▲ 0↑ born
·
assettype · born here
❒asset
# connectome A whole nervous system's wiring diagram as one asset: every neuron with its soma position, cell type, class and neurotransmitter, and every neuron-to-neuron connection with its synapse count, packed into the binary form a GPU spiking simulation binds directly. The `brain` module of the `fruitFly` package runs any instance of this type; the type itself carries no animal. ``` maleCNS.connectome/ manifest.json counts, provenance, byte layouts, vocabularies neurons.bin 32 bytes per neuron offsets.bin u32[neurons + 1], CSR row starts into edges.bin edges.bin u32 per connection: target index | synapse count << 18 README.md the animal, the dataset, the release, the license .metadata description + tags ``` ## The manifest ```json { "dataset": "MaleCNS v1.0 ...", "license": "CC-BY 4.0", "citation": "...", "neurons": 164587, "edges": 25563197, "edge_format": "...", "neuron_record": "...", "flags": "...", "sign_rule": "...", "soma_centre_um": [x, y, z], "vocab": { "types": [...], "superclasses": [...], "classes": [...], "neurotransmitters": [...], "sides": [...], "dimorphism": [...], "fruDsx": [...] } } ``` ## The neuron record (32 bytes, little-endian) | offset | type | field | |---|---|---| | 0 | f32 | soma x, micrometres, centred on `soma_centre_um` | | 4 | f32 | soma y | | 8 | f32 | soma z | | 12 | u32 | index into `vocab.types` | | 16 | u32 | flags (below) | | 20 | u32 | source body id, low 32 bits | | 24 | u32 | source body id, high 32 bits | | 28 | u32 | out-degree (number of edges in this neuron's row) | Flags: bits 0-5 superclass, 6-13 class, 14-17 neurotransmitter, 18-19 side, bit 20 has a soma position, 21-23 dimorphism, 24-26 fruDsx, bit 27 set when the neuron excites its targets (clear when it inhibits). Every bit field indexes the vocabulary of the same name, 0 being `unknown`. ## Parts A payload larger than one blob may carry is stored as numbered parts, `edges.0.bin`, `edges.1.bin`, ..., and the manifest's `parts` says how many (`"parts": { "edges": 2 }`). `ref:parts("edges")` lists them with the byte offset each starts at, so a GPU upload writes each part in place; `ref:bytes("edges")` concatenates them when a caller wants the whole table. A payload without an entry in `parts` is the single file `<name>.bin`. ## The edge (4 bytes) Bits 0-17 hold the postsynaptic neuron's index, bits 18-31 the synapse count clamped at 16383. Row `i` of the table is `edges[offsets[i] .. offsets[i+1])`, so a neuron's outgoing connections are one contiguous run, which is what an event-driven spike propagation reads. ## Reading one from Luau ```luau local ref = asset.resolve("maleCNS", "connectome") local m = ref:manifest() -- the decoded manifest local neurons = ref:bytes("neurons") -- a Luau `buffer` of neurons.bin local edges = ref:bytes("edges") -- the whole edge table, for a GPU upload ref:counts() -- { neurons = ..., edges = ... } ``` `ref:bytes(name)` reads the whole file into a Luau `buffer`, so a call for `edges` on a large connectome holds a hundred megabytes until the caller drops it; hand it to a GPU buffer's `writeBytes` and let it go. ## Making one A connectome is written by a packer outside the engine (the `fruitFly` package's README names the script for MaleCNS). It reads the dataset's own export, assigns dense indices, sorts edges by presynaptic neuron, and writes the four files above. `asset.create("connectome", "<name>")` scaffolds the folder with an empty manifest for a packer to fill.
▲ 0↑ born
backing path · scenes/main.scene

Problems

Everything affecting this asset right now: its own problems, anything wrong inside it, and problems on its direct dependencies.

0problems
No problems reported on this asset or on the parts this page shows. Parts it leaves out are not counted here.
⌬ZeroMind agent review · awaiting first pass
Findings
Reviewer findings (handle · model · tag · quoted note) appear here once the per-pass review log lands. Today only the rolled-up agent_score is exposed.
usability—
did it work as advertised
quality—
authoring polish + cohesion
performance—
frame & memory budget held
agent review score
—
/ 100
awaiting first pass
usability × 0.40
+ quality × 0.35
+ performance × 0.25
± compat factor

Usability ratings

Did the part work as advertised when consumers tried to drop it in. Separate from upvotes: those are taste; this is "did it function".

—%no reports yet
Sign in to report whether this part worked for you.
Discussion

Scoped to this part · feeds back into the world's score.

0comments
Sign in to post.sign in
No comments yet. Be the first.