<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Language Learning Visualization</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: 'Monaco', 'Consolas', monospace;
background: #0a0a0f;
color: #e0e0e0;
overflow: hidden;
}
#container {
display: flex;
height: 100vh;
}
#canvas-container {
flex: 1;
position: relative;
}
#sidebar {
width: 300px;
background: #12121a;
padding: 20px;
overflow-y: auto;
border-left: 1px solid #333;
}
h1 { font-size: 14px; margin-bottom: 20px; color: #888; }
h2 { font-size: 12px; margin: 15px 0 10px; color: #666; text-transform: uppercase; }
details { margin-bottom: 4px; }
details > summary {
font-size: 12px;
color: #666;
text-transform: uppercase;
cursor: pointer;
padding: 6px 0;
user-select: none;
list-style: none;
}
details > summary::-webkit-details-marker { display: none; }
details > summary::before {
content: '\25b6';
display: inline-block;
width: 14px;
font-size: 8px;
transition: transform 0.15s;
color: #555;
}
details[open] > summary::before {
transform: rotate(90deg);
}
details > summary:hover { color: #999; }
details[open] > summary { color: #4ecdc4; }
details > .section-body { padding-left: 2px; }
.stat {
display: flex;
justify-content: space-between;
padding: 5px 0;
font-size: 12px;
}
.stat-value { color: #4ecdc4; }
.stat-label { color: #999; }
.stat-separator {
border-top: 1px solid #222;
margin: 4px 0;
}
.legend {
display: flex;
flex-direction: column;
gap: 5px;
margin: 10px 0;
}
.legend-item {
display: flex;
align-items: center;
gap: 10px;
font-size: 11px;
}
.legend-color {
width: 20px;
height: 10px;
border-radius: 2px;
}
.slider-container {
margin: 15px 0;
}
.slider-container label {
display: block;
font-size: 11px;
color: #666;
margin-bottom: 5px;
}
input[type="range"] {
width: 100%;
background: #333;
}
.hint {
font-size: 9px;
color: #555;
margin-top: 2px;
}
.cluster-list {
max-height: 200px;
overflow-y: auto;
font-size: 11px;
}
.cluster-item {
padding: 5px;
margin: 2px 0;
background: #1a1a25;
border-radius: 3px;
cursor: pointer;
}
.cluster-item:hover {
background: #252535;
}
#tooltip {
position: absolute;
background: rgba(0,0,0,0.9);
border: 1px solid #4ecdc4;
padding: 10px;
font-size: 11px;
pointer-events: none;
display: none;
max-width: 250px;
z-index: 100;
}
#loading {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: #4ecdc4;
}
canvas { display: block; }
#labels-overlay {
position: absolute;
top: 0; left: 0; right: 0; bottom: 0;
pointer-events: none;
overflow: hidden;
}
.node-label {
position: absolute;
color: #e0e0e0;
font-family: 'Monaco', 'Consolas', monospace;
white-space: nowrap;
text-shadow: 0 0 4px #000, 0 0 8px #000, 1px 1px 2px #000;
pointer-events: none;
transform: translate(-50%, -50%);
transition: opacity 0.3s;
}
/* Histogram panel */
#histogram-panel {
position: absolute;
bottom: 40px;
left: 10px;
background: rgba(10, 10, 18, 0.92);
border: 1px solid #333;
border-radius: 6px;
padding: 12px;
z-index: 150;
width: 520px;
}
#histogram-panel.collapsed {
display: none;
}
#histogram-panel.fullscreen {
top: calc(100% / 12);
left: calc(100% / 12);
right: calc(100% / 12);
bottom: calc(100% / 12 + 30px);
width: auto;
display: flex;
flex-direction: column;
}
#histogram-panel.fullscreen .histogram-canvas-wrap {
flex: 1;
min-height: 0;
}
.histogram-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 8px;
}
.histogram-header h3 {
font-size: 11px;
color: #888;
text-transform: uppercase;
letter-spacing: 1px;
}
.histogram-tabs {
display: flex;
gap: 4px;
}
.histogram-tab {
padding: 3px 8px;
font-size: 10px;
font-family: inherit;
background: #1a1a25;
color: #666;
border: 1px solid #333;
border-radius: 3px;
cursor: pointer;
}
.histogram-tab.active {
color: #4ecdc4;
border-color: #4ecdc4;
}
.histogram-canvas-wrap {
position: relative;
}
#histogram-canvas {
display: block;
background: #0a0a12;
border-radius: 3px;
}
.histogram-stats {
display: flex;
gap: 16px;
margin-top: 6px;
font-size: 10px;
color: #666;
}
.histogram-stats span {
color: #4ecdc4;
}
#histogram-toggle {
position: absolute;
bottom: 10px;
left: 10px;
background: rgba(0,0,0,0.7);
color: #4ecdc4;
padding: 4px 10px;
border-radius: 4px;
font-size: 10px;
font-family: monospace;
z-index: 200;
cursor: pointer;
border: 1px solid #333;
user-select: none;
}
#histogram-toggle:hover {
border-color: #4ecdc4;
}
/* Promotion progress bar */
.prom-bar {
background: #1a1a25;
border-radius: 3px;
height: 6px;
margin: 4px 0 8px;
overflow: hidden;
}
.prom-bar-fill {
height: 100%;
background: #4ecdc4;
border-radius: 3px;
transition: width 0.5s;
}
.prom-check {
display: flex;
justify-content: space-between;
font-size: 10px;
padding: 2px 0;
}
.prom-check .label { color: #888; }
.prom-check .pass { color: #44cc88; }
.prom-check .fail { color: #ff6666; }
/* Benchmark stats */
.bench-row {
display: flex;
justify-content: space-between;
font-size: 11px;
padding: 2px 0;
}
.bench-row .label { color: #888; }
.bench-row .val { color: #4ecdc4; font-variant-numeric: tabular-nums; }
.bench-group {
border-left: 2px solid #222;
padding-left: 8px;
margin: 4px 0;
}
.bench-group-title {
font-size: 10px;
color: #555;
text-transform: uppercase;
margin-bottom: 2px;
}
</style>
</head>
<body>
<div id="container">
<div id="canvas-container">
<canvas id="canvas"></canvas>
<div id="labels-overlay"></div>
<div id="tooltip"></div>
<div id="loading">Loading visualization data...</div>
<!-- Histogram panel -->
<div id="histogram-panel" class="collapsed">
<div class="histogram-header">
<h3>Distribution</h3>
<div class="histogram-tabs">
<button class="histogram-tab active" data-hist="mi">MI</button>
<button class="histogram-tab" data-hist="surprise">Per-Word</button>
<button class="histogram-tab" id="hist-fullscreen" style="margin-left:8px;">FULL</button>
</div>
</div>
<div class="histogram-canvas-wrap">
<canvas id="histogram-canvas" width="496" height="180"></canvas>
</div>
<div class="histogram-stats" id="histogram-stats"></div>
</div>
<div id="histogram-toggle">HISTOGRAMS</div>
</div>
<div id="sidebar">
<h1>LANGUAGE LEARNING VISUALIZER</h1>
<details open>
<summary>Learning Progress</summary>
<div class="section-body">
<div class="stat"><span>Sentences:</span><span class="stat-value" id="stat-sentences">0</span></div>
<div class="stat"><span>Learn Rate:</span><span class="stat-value" id="stat-learn-rate">0%</span></div>
<div class="stat"><span>Level:</span><span class="stat-value" id="stat-level">0</span></div>
<div class="stat"><span>Epoch:</span><span class="stat-value" id="stat-epoch">0</span></div>
<div class="stat"><span>Avg Surprise:</span><span class="stat-value" id="stat-surprise">0</span></div>
</div>
</details>
<details open>
<summary>Graph</summary>
<div class="section-body">
<div class="stat"><span>Words:</span><span class="stat-value" id="stat-words">0</span></div>
<div class="stat"><span>Pairs:</span><span class="stat-value" id="stat-pairs">0</span></div>
<div class="stat"><span>Clusters:</span><span class="stat-value" id="stat-clusters">0</span></div>
<div class="stat"><span>Word Classes:</span><span class="stat-value" id="stat-classes">0</span></div>
</div>
</details>
<details>
<summary>MI Distribution</summary>
<div class="section-body">
<div class="stat"><span>Total MI Pairs:</span><span class="stat-value" id="stat-mi-total">0</span></div>
<div class="stat"><span>MI Mean:</span><span class="stat-value" id="stat-mi-mean">-</span></div>
<div class="stat"><span>MI Std:</span><span class="stat-value" id="stat-mi-std">-</span></div>
<div class="stat"><span>MI Range:</span><span class="stat-value" id="stat-mi-range">-</span></div>
</div>
</details>
<details open>
<summary>Promotion to L1 (Senses)</summary>
<div class="section-body">
<div class="prom-bar"><div class="prom-bar-fill" id="prom-bar-fill" style="width:0%"></div></div>
<div class="prom-check"><span class="label">Sentences > 2000</span><span id="prom-sent" class="fail">--</span></div>
<div class="prom-check"><span class="label">Cluster iterations > 3</span><span id="prom-iter" class="fail">--</span></div>
<div class="prom-check"><span class="label">Classes > 20</span><span id="prom-classes" class="fail">--</span></div>
<div class="prom-check"><span class="label">Structure exhausted</span><span id="prom-exhausted" class="fail">--</span></div>
<div class="stat-separator"></div>
<div class="prom-check"><span class="label">Top-pair / floor</span><span id="prom-top-score" class="fail">--</span></div>
<div class="prom-check"><span class="label">Marginal entropy</span><span id="prom-entropy" class="fail">--</span></div>
<div class="stat-separator"></div>
<div class="stat"><span>Word Senses:</span><span class="stat-value" id="stat-senses">0</span></div>
<div class="stat"><span>Section Pairs:</span><span class="stat-value" id="stat-sections">0</span></div>
</div>
</details>
<details open>
<summary>Benchmark</summary>
<div class="section-body">
<div class="bench-row"><span class="label">Runtime</span><span class="val" id="bench-runtime">-</span></div>
<div class="bench-row"><span class="label">Throughput</span><span class="val" id="bench-throughput">-</span></div>
<div class="bench-group">
<div class="bench-group-title">GPU MI</div>
<div class="bench-row"><span class="label">Total / Calls</span><span class="val" id="bench-mi-summary">-</span></div>
<div class="bench-row"><span class="label">Avg per call</span><span class="val" id="bench-mi-avg">-</span></div>
<div class="bench-row"><span class="label">Pairs processed</span><span class="val" id="bench-mi-pairs">-</span></div>
</div>
<div class="bench-group">
<div class="bench-group-title">Clustering</div>
<div class="bench-row"><span class="label">Total / Calls</span><span class="val" id="bench-cluster-summary">-</span></div>
<div class="bench-row"><span class="label">Avg per round</span><span class="val" id="bench-cluster-avg">-</span></div>
</div>
<div class="bench-group">
<div class="bench-group-title">Eviction</div>
<div class="bench-row"><span class="label">Total / Calls</span><span class="val" id="bench-evict-summary">-</span></div>
</div>
<div class="bench-group">
<div class="bench-group-title">Export</div>
<div class="bench-row"><span class="label">Total / Calls</span><span class="val" id="bench-export-summary">-</span></div>
<div class="bench-row"><span class="label">Avg per export</span><span class="val" id="bench-export-avg">-</span></div>
</div>
</div>
</details>
<details>
<summary>Layout Quality</summary>
<div class="section-body">
<div class="stat"><span>Layout Stress:</span><span class="stat-value" id="stat-stress">-</span></div>
<div class="stat"><span>MI↔Dist Corr:</span><span class="stat-value" id="stat-corr">-</span></div>
<div style="margin-top: 8px;">
<button onclick="exportPositions()" style="width: 100%; padding: 6px; background: #1a1a25; color: #4ecdc4; border: 1px solid #333; border-radius: 4px; cursor: pointer; font-family: inherit; font-size: 11px;">Export Positions</button>
</div>
</div>
</details>
<details open>
<summary>Layout</summary>
<div class="section-body">
<div class="slider-container">
<select id="layout-mode" style="width: 100%; padding: 5px; background: #1a1a25; color: #e0e0e0; border: 1px solid #333;">
<option value="unified">Unified (single cloud)</option>
<option value="atomspaces">Mindmap (radial)</option>
<option value="chapters">Chapters (radial rings)</option>
</select>
<div class="hint">Mindmap = radial by surprise. Chapters = rings per chapter.</div>
</div>
<div class="slider-container">
<label>Detail Level: <span id="detail-level-value">3</span></label>
<input type="range" id="detail-level-slider" min="1" max="4" step="1" value="3">
<div class="hint">1=books 2=core 3=communities 4=full</div>
</div>
<div class="slider-container">
<label>Grid Opacity: <span id="grid-opacity-value">0.4</span></label>
<input type="range" id="grid-opacity-slider" min="0.05" max="1.0" step="0.05" value="0.4">
</div>
<div class="slider-container">
<label>Cell Size: <span id="cell-size-value">8</span></label>
<input type="range" id="cell-size-slider" min="4" max="20" step="1" value="8">
</div>
<div class="slider-container">
<label>Cell Gap: <span id="cell-gap-value">0</span></label>
<input type="range" id="cell-gap-slider" min="0" max="8" step="0.5" value="0">
</div>
</div>
</details>
<details open>
<summary>Color Mode</summary>
<div class="section-body">
<div class="slider-container">
<select id="color-mode" style="width: 100%; padding: 5px; background: #1a1a25; color: #e0e0e0; border: 1px solid #333;">
<option value="density">Connection Density</option>
<option value="cluster" selected>Cluster Membership</option>
<option value="wordClass">Word Class</option>
<option value="atomspace">Atomspace</option>
<option value="vagueness">Vagueness/Surprise</option>
<option value="mindmap">Mindmap (centrality)</option>
</select>
<div class="hint">How nodes are colored</div>
</div>
</div>
</details>
<details>
<summary>Legend</summary>
<div class="section-body">
<div class="legend" id="density-legend">
<div class="legend-item">
<div class="legend-color" style="background: #ffeeaa;"></div>
<span>Hub (many connections)</span>
</div>
<div class="legend-item">
<div class="legend-color" style="background: #e6b333;"></div>
<span>High connectivity</span>
</div>
<div class="legend-item">
<div class="legend-color" style="background: #66cc99;"></div>
<span>Medium connectivity</span>
</div>
<div class="legend-item">
<div class="legend-color" style="background: #3399cc;"></div>
<span>Low connectivity</span>
</div>
<div class="legend-item">
<div class="legend-color" style="background: #334dcc;"></div>
<span>Isolated (few connections)</span>
</div>
</div>
<div class="legend" id="vagueness-legend" style="display: none;">
<div class="legend-item">
<div class="legend-color" style="background: #ff4444;"></div>
<span>High surprise (unknown)</span>
</div>
<div class="legend-item">
<div class="legend-color" style="background: #ffcc44;"></div>
<span>Learning</span>
</div>
<div class="legend-item">
<div class="legend-color" style="background: #44cc88;"></div>
<span>Low surprise</span>
</div>
<div class="legend-item">
<div class="legend-color" style="background: #4488ff;"></div>
<span>Well known</span>
</div>
</div>
<div class="legend" id="cluster-legend" style="display: none;">
<div class="legend-item">
<span>Each cluster has a unique color</span>
</div>
</div>
<div class="legend" id="wordclass-legend" style="display: none;">
<div class="legend-item">
<span>Each grammatical word class has a unique color</span>
</div>
<div class="legend-item">
<div class="legend-color" style="background: #666;"></div>
<span>Unclassified words (gray)</span>
</div>
</div>
<div class="legend" id="atomspace-legend" style="display: none;">
<div class="legend-item">
<div class="legend-color" style="background: rgb(255,235,153);"></div>
<span>Common (shared knowledge)</span>
</div>
<div class="legend-item">
<div class="legend-color" style="background: rgb(102,204,255);"></div>
<span>Alice in Wonderland</span>
</div>
<div class="legend-item">
<div class="legend-color" style="background: rgb(255,102,153);"></div>
<span>Pride and Prejudice</span>
</div>
<div class="legend-item">
<div class="legend-color" style="background: rgb(102,255,153);"></div>
<span>Sherlock Holmes</span>
</div>
<div class="legend-item">
<div class="legend-color" style="background: rgb(204,127,255);"></div>
<span>Great Expectations</span>
</div>
<div class="legend-item">
<div class="legend-color" style="background: rgb(255,178,76);"></div>
<span>Moby Dick</span>
</div>
</div>
<div class="legend" id="mindmap-legend" style="display: none;">
<div class="legend-item">
<div class="legend-color" style="background: linear-gradient(to right, #ddd, #4ecdc4);"></div>
<span>Center = vivid (certain)</span>
</div>
<div class="legend-item">
<div class="legend-color" style="background: linear-gradient(to right, #888, #334);"></div>
<span>Edge = faded (vague)</span>
</div>
<div class="legend-item">
<span>Hue = community, brightness = centrality</span>
</div>
</div>
<h2 style="margin-top: 10px;">Edges (MI Strength)</h2>
<div class="legend">
<div class="legend-item">
<div class="legend-color" style="background: #ffffff;"></div>
<span>Very strong MI</span>
</div>
<div class="legend-item">
<div class="legend-color" style="background: #ffff33;"></div>
<span>Strong MI</span>
</div>
<div class="legend-item">
<div class="legend-color" style="background: #33cccc;"></div>
<span>Medium MI</span>
</div>
<div class="legend-item">
<div class="legend-color" style="background: #1a3380;"></div>
<span>Weak MI</span>
</div>
</div>
</div>
</details>
<details>
<summary>Filters</summary>
<div class="section-body">
<div class="slider-container">
<label>Min Edge MI: <span id="mi-value">0.5</span></label>
<input type="range" id="mi-slider" min="0" max="5" step="0.1" value="0.5">
<div class="hint">Higher = fewer edges, only strong links</div>
</div>
<div class="slider-container">
<label>Max Surprise: <span id="vague-value">10</span></label>
<input type="range" id="vague-slider" min="0" max="10" step="0.5" value="10">
<div class="hint">Lower = only well-known words</div>
</div>
</div>
</details>
<details>
<summary>Display</summary>
<div class="section-body">
<div class="slider-container">
<label>Point Size: <span id="point-size-value">1.0</span></label>
<input type="range" id="point-size-slider" min="0.1" max="5" step="0.1" value="1.0">
</div>
<div class="slider-container">
<label>Edge Opacity: <span id="line-width-value">0.4</span></label>
<input type="range" id="line-width-slider" min="0.1" max="3" step="0.1" value="0.4">
</div>
<div class="slider-container">
<label style="display: flex; align-items: center; gap: 8px;">
<input type="checkbox" id="auto-rotate" checked> Auto Rotate
</label>
</div>
<div class="slider-container">
<label style="display: flex; align-items: center; gap: 8px;">
<input type="checkbox" id="show-labels" checked> Show Labels
</label>
</div>
<div class="slider-container">
<label>Label Count: <span id="label-count-value">60</span></label>
<input type="range" id="label-count-slider" min="10" max="200" step="10" value="60">
<div class="hint">How many top words get labels</div>
</div>
</div>
</details>
<details open>
<summary>Atomspaces</summary>
<div class="section-body">
<div class="cluster-list" id="atomspace-list">
<div style="color:#555;font-size:10px;padding:4px;">No atomspace data — use (compartment-export)</div>
</div>
</div>
</details>
<details>
<summary>Word Clusters</summary>
<div class="section-body">
<div class="cluster-list" id="cluster-list"></div>
</div>
</details>
<details open>
<summary>Word Classes</summary>
<div class="section-body">
<div class="cluster-list" id="class-list"></div>
</div>
</details>
</div>
</div>
<script src="viz-3d.js?v=76"></script>
</body>
</html>