FlyBrain-Lab / src /ui /static /index.html
timfromhcs's picture
FlyBrain V5.0.0 Space sync (v1 API, backup, watchdog, fixed tabs)
3865888 verified
Raw
History Blame Contribute Delete
24.9 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>FlyBrain Lab — Biological Connectome Research Platform</title>
<script src="/static/vendor/three.min.js"></script>
<script src="/static/vendor/OrbitControls.js"></script>
<link rel="stylesheet" href="/static/css/lab.css">
</head>
<body>
<header>
<div class="brand">
<div class="brand-logo">FB</div>
<div>
<div class="brand-title">FlyBrain Lab</div>
<div class="brand-subtitle">Janelia MaleCNS v1.0 Biological Research Workstation</div>
</div>
</div>
<div class="header-meta">
<span class="badge badge-state" id="sim-status-badge"><span class="dot-pulse"></span><span id="sim-status-text">PAUSED</span></span>
<span class="badge badge-gpu" id="backend-badge">Detecting backend…</span>
<span class="badge badge-state" id="provenance-badge" title="Loading live provenance from /api/provenance…">Loading provenance…</span>
<button class="btn btn-green" id="btn-toggle-sim" onclick="toggleSimulation()">▶ Start Simulation</button>
<button class="btn" onclick="stepSimulation(1)">+1 Step</button>
<button class="btn" onclick="stepSimulation(10)">+10 Steps</button>
</div>
</header>
<nav>
<button class="nav-tab active" onclick="switchTab('overview')">Overview</button>
<button class="nav-tab" onclick="switchTab('world')">World</button>
<button class="nav-tab" onclick="switchTab('stream')">Live Stream</button>
<button class="nav-tab" onclick="switchTab('connectome')">Connectome 3D</button>
<button class="nav-tab" onclick="switchTab('colony')">Colony</button>
<button class="nav-tab" onclick="switchTab('provenance')">Provenance</button>
<button class="nav-tab" onclick="switchTab('experiments')">Experiments & Determinism</button>
<button class="nav-tab" onclick="switchTab('memory')">Memory Explorer</button>
<button class="nav-tab" onclick="switchTab('evolution')">Evolution Lineage</button>
<button class="nav-tab" onclick="switchTab('dreams')">Dream Studio</button>
<button class="nav-tab" onclick="switchTab('backups')">Backups</button>
<button class="nav-tab" onclick="switchTab('diagnostics')">Diagnostics & Hardware</button>
</nav>
<main>
<!-- Tab: Embodied 3D World (server-authoritative MuJoCo; browser renders) -->
<div id="tab-world" class="tab-content">
<div class="viewer-container">
<div id="world-canvas-wrapper">
<canvas id="world-canvas"></canvas>
<div class="viewer-controls-overlay">
<label style="font-size: 11px; color: var(--text-dim);">Camera:</label>
<select id="world-cam" onchange="worldCamMode=this.value">
<option value="third">Third-person</option>
<option value="first">First-person</option>
<option value="observer">Observer</option>
<option value="free">Free orbit</option>
</select>
<label style="font-size: 11px; color: var(--text-dim);"><input type="checkbox" id="world-debug" onchange="worldDebug=this.checked"> Debug</label>
<button class="btn" onclick="worldStep(5)">+ Step</button>
<button class="btn" onclick="worldDream(false)">Dream</button>
<button class="btn" onclick="worldDream(true)">Dream+Image</button>
</div>
</div>
<div class="inspector-panel">
<div style="font-size: 14px; font-weight: 700; border-bottom: 1px solid var(--border-subtle); padding-bottom: 8px;">Organism</div>
<div class="inspector-row"><span class="inspector-label">Goal</span><span class="inspector-val" id="w-goal">—</span></div>
<div class="inspector-row"><span class="inspector-label">Energy / Hunger</span><span class="inspector-val" id="w-needs">—</span></div>
<div class="inspector-row"><span class="inspector-label">Location</span><span class="inspector-val" id="w-loc">—</span></div>
<div class="inspector-row"><span class="inspector-label">World time</span><span class="inspector-val" id="w-time">—</span></div>
<div class="inspector-row"><span class="inspector-label">Models</span><span class="inspector-val" id="w-models">—</span></div>
<div style="display: flex; gap: 6px; margin-top: 10px;">
<input type="text" id="w-say-text" placeholder="Say something…" style="flex: 1;">
<button class="btn btn-green" onclick="worldSay()">Speak</button>
</div>
<div style="display: flex; gap: 6px; margin-top: 6px;">
<input type="text" id="w-imagine-text" placeholder="Imagine…" style="flex: 1;">
<button class="btn" onclick="worldImagine()">Imagine</button>
</div>
<div id="w-friends" style="margin-top: 10px; font-size: 12px;"></div>
<canvas id="world-minimap" width="220" height="220" style="margin-top: 10px; border: 1px solid var(--border-subtle); border-radius: 8px;"></canvas>
</div>
</div>
</div>
<!-- Tab 1: Overview -->
<div id="tab-overview" class="tab-content active">
<div class="grid-overview">
<div class="card">
<div class="card-header"><span>Simulation Step</span><span id="stat-latency">0.0 ms</span></div>
<div class="card-value" id="stat-step">0</div>
<div class="card-subtext" id="stat-speed">Throughput: 0 steps/sec</div>
</div>
<div class="card">
<div class="card-header"><span>Active Spikes (LIF)</span><span>Threshold 1.0</span></div>
<div class="card-value" id="stat-spikes" style="color: var(--accent-cyan);">0</div>
<div class="card-subtext" id="stat-total-spikes">Cumulative Spikes: 0</div>
</div>
<div class="card">
<div class="card-header"><span>Mean Activation / Potential</span><span>Leaky Integrator</span></div>
<div class="card-value" id="stat-act">0.0000</div>
<div class="card-subtext" id="stat-pot">Potential: 0.000 mV</div>
</div>
<div class="card">
<div class="card-header"><span>Active Motor Efferent</span><span>Top Population</span></div>
<div class="card-value" id="stat-action" style="color: var(--accent-green);">explore</div>
<div class="card-subtext" id="stat-pred-error">Prediction Error: 0.000</div>
</div>
</div>
<div style="display: grid; grid-template-columns: 2fr 1fr; gap: 20px;">
<div class="card">
<div class="card-header"><span>Homeostatic Drive Regulation</span><span>Energy, Curiosity, Social, Integrity</span></div>
<div style="display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; margin-top: 14px;">
<div>
<div style="font-size: 11px; color: var(--text-dim);">Energy</div>
<div style="font-size: 20px; font-weight: bold; color: var(--accent-amber);" id="drive-energy">1.00</div>
</div>
<div>
<div style="font-size: 11px; color: var(--text-dim);">Curiosity</div>
<div style="font-size: 20px; font-weight: bold; color: var(--accent-cyan);" id="drive-curiosity">0.80</div>
</div>
<div>
<div style="font-size: 11px; color: var(--text-dim);">Social</div>
<div style="font-size: 20px; font-weight: bold; color: var(--accent-purple);" id="drive-social">0.50</div>
</div>
<div>
<div style="font-size: 11px; color: var(--text-dim);">Integrity</div>
<div style="font-size: 20px; font-weight: bold; color: var(--accent-green);" id="drive-integrity">1.00</div>
</div>
</div>
</div>
<div class="card">
<div class="card-header"><span>Active Sensory Stimulus</span><span>Direct Injection</span></div>
<div style="display: flex; gap: 8px; margin-top: 10px;">
<button class="btn" onclick="injectSensory('visual', 1.5)">Stimulate Vision</button>
<button class="btn" onclick="injectSensory('auditory', 1.2)">Stimulate Audio</button>
<button class="btn btn-green" onclick="injectReward(1.0)">+Reward</button>
</div>
</div>
</div>
</div>
<!-- Tab: Live Stream (24/7 mode) -->
<div id="tab-stream" class="tab-content">
<div class="card" style="margin-bottom: 20px;">
<div class="card-header"><span>24/7 Stream Control</span><span id="stream-mode-badge" class="badge badge-state">STOPPED</span></div>
<div class="prov-grid">
<div class="prov-row"><span class="prov-label">Uptime</span><span class="prov-val" id="stream-uptime">—</span></div>
<div class="prov-row"><span class="prov-label">Simulation step</span><span class="prov-val" id="stream-step">—</span></div>
<div class="prov-row"><span class="prov-label">Spikes / latency p95</span><span class="prov-val" id="stream-perf">—</span></div>
<div class="prov-row"><span class="prov-label">Watchdog</span><span class="prov-val" id="stream-watchdog">—</span></div>
</div>
<div style="display: flex; gap: 8px; margin-top: 12px; flex-wrap: wrap;">
<button class="btn btn-green" onclick="streamCmd('start')">▶ START</button>
<button class="btn btn-amber" onclick="streamCmd('pause')">⏸ PAUSE</button>
<button class="btn" onclick="streamCmd('resume')">⏵ RESUME</button>
<button class="btn btn-red" onclick="streamCmd('stop')">⏹ STOP</button>
<button class="btn" onclick="stepSimulation(1)">+1 STEP</button>
</div>
</div>
</div>
<!-- Tab: Colony (organisms) -->
<div id="tab-colony" class="tab-content">
<div class="card" style="margin-bottom: 20px;">
<div class="card-header"><span>ALife Colony</span><span id="colony-meta">—</span></div>
<div style="margin-top: 10px; display: flex; gap: 8px; flex-wrap: wrap;">
<button class="btn btn-green" onclick="colonyCmd('step')">+ Step 5 ticks</button>
<button class="btn" onclick="colonyCmd('reproduce')">+ Reproduce</button>
<button class="btn btn-amber" onclick="colonyCmd('reset')">Reset colony</button>
</div>
</div>
<div class="card">
<div class="card-header"><span>Organisms (live state)</span><span>sort/filter in place</span></div>
<table style="margin-top: 10px;">
<thead><tr><th>ID</th><th>Gen</th><th>Stage</th><th>Alive</th><th>Age</th><th>Energy</th><th>Neurons</th><th>Genome</th></tr></thead>
<tbody id="tbody-colony"></tbody>
</table>
</div>
</div>
<!-- Tab 2: Connectome 3D -->
<div id="tab-connectome" class="tab-content">
<div class="viewer-container">
<div id="connectome-canvas-wrapper">
<canvas id="connectome-canvas"></canvas>
<div class="viewer-controls-overlay">
<label style="font-size: 11px; color: var(--text-dim);">Side:</label>
<select id="filter-side" onchange="filterConnectome()">
<option value="ALL">All Hemispheres</option>
<option value="L">Left (L)</option>
<option value="R">Right (R)</option>
<option value="M">Midline (M)</option>
</select>
<label style="font-size: 11px; color: var(--text-dim);">Search Body ID:</label>
<input type="text" id="search-body-id" placeholder="e.g. 187792" style="width: 120px;" onkeydown="if(event.key==='Enter') searchNeuron()">
<button class="btn" onclick="resetCamera()">Reset View</button>
</div>
</div>
<div class="inspector-panel" id="inspector-card">
<div style="font-size: 14px; font-weight: 700; border-bottom: 1px solid var(--border-subtle); padding-bottom: 8px;">
Neuron Inspector
</div>
<div class="inspector-row"><span class="inspector-label">Body ID</span><span class="inspector-val" id="insp-body-id">Select a neuron</span></div>
<div class="inspector-row"><span class="inspector-label">Internal Index</span><span class="inspector-val" id="insp-idx">-</span></div>
<div class="inspector-row"><span class="inspector-label">Hemisphere Side</span><span class="inspector-val" id="insp-side">-</span></div>
<div class="inspector-row"><span class="inspector-label">Presynaptic T-Bars</span><span class="inspector-val" id="insp-tbars">-</span></div>
<div class="inspector-row"><span class="inspector-label">Membrane Potential</span><span class="inspector-val" id="insp-pot">-</span></div>
<div class="inspector-row"><span class="inspector-label">Spike State (LIF)</span><span class="inspector-val" id="insp-spk">-</span></div>
<div class="inspector-row"><span class="inspector-label">Current Activation</span><span class="inspector-val" id="insp-act">-</span></div>
<div class="inspector-row"><span class="inspector-label">3D Coordinates (nm)</span><span class="inspector-val" id="insp-coords">-</span></div>
<div style="font-size: 11px; color: var(--text-dim); line-height: 1.4; margin-top: 10px;">
Click any soma sphere in the 3D viewer to query real biological EM provenance, coordinates, and live membrane potential.
</div>
</div>
</div>
</div>
<!-- Tab: Scientific Provenance (live from /api/provenance) -->
<div id="tab-provenance" class="tab-content">
<div class="card" style="margin-bottom: 20px;">
<div class="card-header"><span>Scientific Status — live backend contract</span><span id="prov-graph-identity" class="badge badge-state">loading…</span></div>
<div class="prov-grid">
<div class="prov-row"><span class="prov-label">Graph</span><span class="prov-val" id="prov-graph">—</span></div>
<div class="prov-row"><span class="prov-label">Sampling</span><span class="prov-val" id="prov-sampling">—</span></div>
<div class="prov-row"><span class="prov-label">Synaptic weights</span><span class="prov-val" id="prov-weights">—</span></div>
<div class="prov-row"><span class="prov-label">Population annotation</span><span class="prov-val" id="prov-pops">—</span></div>
<div class="prov-row"><span class="prov-label">Dataset</span><span class="prov-val mono" id="prov-dataset">—</span></div>
<div class="prov-row"><span class="prov-label">Numerical validation</span><span class="prov-val" id="prov-numerics">trajectory parity (max abs diff &lt; 1e-4), exact spike trains — NOT bit-exact</span></div>
<div class="prov-row"><span class="prov-label">Graph hash</span><span class="prov-val mono" id="prov-hash">—</span></div>
</div>
</div>
</div>
<!-- Tab 3: Experiments -->
<div id="tab-experiments" class="tab-content">
<div class="card" style="margin-bottom: 20px;">
<div class="card-header"><span>Launch Reproducible Research Experiment</span><span>Deterministic Manifest</span></div>
<div style="display: flex; gap: 14px; align-items: flex-end; margin-top: 12px;">
<div>
<div style="font-size: 11px; color: var(--text-dim); margin-bottom: 4px;">Graph Mode</div>
<select id="exp-mode">
<option value="REAL_SUBGRAPH">REAL_SUBGRAPH — sampled MaleCNS subgraph (recommended)</option>
<option value="REAL">REAL — legacy alias of REAL_SUBGRAPH</option>
<option value="SPATIAL_SURROGATE">MaleCNS Spatial Surrogate</option>
<option value="SYNTHETIC_TEST">Synthetic Test Circuit</option>
</select>
</div>
<div>
<div style="font-size: 11px; color: var(--text-dim); margin-bottom: 4px;">Neuron Scale</div>
<select id="exp-scale">
<option value="256">256 Neurons</option>
<option value="512">512 Neurons</option>
<option value="1024">1024 Neurons</option>
</select>
</div>
<div>
<div style="font-size: 11px; color: var(--text-dim); margin-bottom: 4px;">Seed</div>
<input type="number" id="exp-seed" value="42" style="width: 80px;">
</div>
<div>
<div style="font-size: 11px; color: var(--text-dim); margin-bottom: 4px;">Steps</div>
<input type="number" id="exp-steps" value="50" style="width: 80px;">
</div>
<button class="btn btn-green" onclick="runExperiment()">▶ Run Experiment</button>
</div>
</div>
<div class="card">
<div class="card-header"><span>Experiment History & Verification</span><span>Recorded SHA-256 Manifests</span></div>
<table id="table-experiments">
<thead>
<tr>
<th>Experiment ID</th>
<th>Mode</th>
<th>Neurons</th>
<th>Steps</th>
<th>Latency</th>
<th>Final State Hash</th>
<th>Action</th>
</tr>
</thead>
<tbody id="tbody-experiments"></tbody>
</table>
</div>
</div>
<!-- Tab 4: Memory -->
<div id="tab-memory" class="tab-content">
<div class="card">
<div class="card-header"><span>Episodic & Skill Memory Explorer</span><span>SQLite WAL Engine</span></div>
<div style="margin-bottom: 14px;">
<input type="text" id="memory-search" placeholder="Search episodic recollections..." style="width: 300px;" oninput="fetchMemory()">
</div>
<table id="table-episodes">
<thead>
<tr><th>ID</th><th>Step</th><th>Action</th><th>Reward</th><th>Prediction Error</th><th>Timestamp</th></tr>
</thead>
<tbody id="tbody-episodes"></tbody>
</table>
</div>
</div>
<!-- Tab 5: Evolution -->
<div id="tab-evolution" class="tab-content">
<div class="card" style="margin-bottom: 20px;">
<div class="card-header"><span>Autonomous Structural Evolution</span><span>Mutations, Evaluation & Rollback</span></div>
<div style="margin-top: 10px; display: flex; gap: 14px;">
<button class="btn btn-green" onclick="triggerEvolution()">+ Evolve New Generation</button>
<span style="font-size: 13px; color: var(--text-dim); align-self: center;" id="evo-meta-text">Generation 0</span>
</div>
</div>
<div class="card">
<div class="card-header"><span>Evolution Lineage Tree</span><span>Evaluated Variants</span></div>
<div id="evo-lineage-container" style="display: flex; flex-direction: column; gap: 12px; margin-top: 10px;"></div>
</div>
</div>
<!-- Tab 6: Dreams -->
<div id="tab-dreams" class="tab-content">
<div class="card" style="margin-bottom: 20px;">
<div class="card-header"><span>Offline Dream & Counterfactual Experience Replay</span><span>Consolidation Studio</span></div>
<div style="margin-top: 10px; display: flex; gap: 14px;">
<button class="btn" onclick="triggerDream('deterministic')">Run Deterministic Replay (Seed 42)</button>
<button class="btn btn-amber" onclick="triggerDream('exploratory')">Run Exploratory Dream</button>
</div>
</div>
<div class="card">
<div class="card-header"><span>Consolidated Dream Records</span><span>Counterfactual Simulations</span></div>
<div id="dreams-list" style="display: flex; flex-direction: column; gap: 10px; margin-top: 10px;"></div>
</div>
</div>
<!-- Tab: Backups -->
<div id="tab-backups" class="tab-content">
<div class="card" style="margin-bottom: 20px;">
<div class="card-header"><span>Backup Management (local disk)</span><span id="gdrive-badge" class="badge badge-state">drive: …</span></div>
<div style="margin-top: 10px; display: flex; gap: 8px; flex-wrap: wrap;">
<button class="btn btn-green" onclick="backupCreate()">⬇ BACKUP NOW</button>
<button class="btn" onclick="fetchBackups()">Refresh</button>
</div>
<div class="prov-val" id="gdrive-detail" style="margin-top: 8px; font-size: 12px;"></div>
</div>
<div class="card">
<div class="card-header"><span>Backup generations (hash-verified)</span><span>restore refuses corrupt/invalid</span></div>
<table style="margin-top: 10px;">
<thead><tr><th>Name</th><th>Trigger</th><th>Step</th><th>State hash</th><th>Actions</th></tr></thead>
<tbody id="tbody-backups"></tbody>
</table>
</div>
</div>
<!-- Tab 7: Diagnostics -->
<div id="tab-diagnostics" class="tab-content">
<div class="card" style="margin-bottom: 20px;">
<div class="card-header"><span>Host System & Physical Hardware</span><span>Live Discovery</span></div>
<div style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; margin-top: 12px;" id="diag-system-grid"></div>
</div>
<div class="card">
<div class="card-header"><span>Dataset Provenance & Cryptographic Hashes</span><span>Janelia MaleCNS v1.0</span></div>
<table style="margin-top: 10px;">
<tbody id="diag-hashes-tbody"></tbody>
</table>
</div>
</div>
</main>
<div id="toast-container"></div>
<script src="/static/js/lab.js"></script>
</body>
</html>