Web UI
mcnanovna includes an optional Three.js-based 3D viewer for antenna radiation patterns.
Enabling the Web UI
Set the MCNANOVNA_WEB_PORT environment variable:
MCNANOVNA_WEB_PORT=8080 uvx mcnanovnaThen open http://localhost:8080 in your browser.
Features
3D Pattern Visualization
- Interactive rotation with mouse drag
- Zoom with scroll wheel
- Gain-mapped color gradient (red = high, blue = low)
- dBi reference rings
Pattern Sources
- From VNA scan: Run
radiation_patterntool - From known impedance: Use
radiation_pattern_from_data - File upload: Load CSV, EMCAR, NEC2, or S1P files
Controls
| Control | Action |
|---|---|
| Left drag | Rotate view |
| Scroll | Zoom in/out |
| Right drag | Pan |
| Double-click | Reset view |
Side Panel
- Antenna type selector
- Frequency display
- Impedance readout
- Peak gain indicator
- Toggle reference rings
- Toggle axes
API Endpoints
The web UI provides REST and WebSocket endpoints:
REST
| Endpoint | Method | Description |
|---|---|---|
/api/pattern/compute | POST | Compute pattern from S11 data |
/api/pattern/current | GET | Get current pattern data |
/api/status | GET | Server status |
WebSocket
Connect to /ws for real-time pattern updates during measurement.
const ws = new WebSocket('ws://localhost:8080/ws');ws.onmessage = (event) => { const pattern = JSON.parse(event.data); // Update visualization};Pattern Format
All patterns use this JSON structure:
{ "antenna_type": "dipole", "frequency_hz": 145000000, "theta_deg": [0, 5, 10, ...], "phi_deg": [0, 10, 20, ...], "gain_dbi": [-40, -35, -20, ...], "peak_gain_dbi": 2.15, "num_points": 6552}File Upload
Click “Load File” to import external patterns:
| Format | Extension | Notes |
|---|---|---|
| CSV | .csv | 2 or 3 columns |
| EMCAR | .dat | Antenna range format |
| NEC2 | .out, .nec | Simulation output |
| S1P | .s1p | Touchstone → analytical |
Architecture
┌─────────────────────────────────────────────────────────┐│ Browser ││ ┌───────────────────────────────────────────────────┐ ││ │ Three.js Scene │ ││ │ ┌─────────────┐ ┌─────────────┐ ┌───────────┐ │ ││ │ │ Pattern Mesh│ │ OrbitControl│ │ Reference │ │ ││ │ │(gain→color) │ │ (camera) │ │ Rings │ │ ││ │ └─────────────┘ └─────────────┘ └───────────┘ │ ││ └───────────────────────────────────────────────────┘ ││ │ ││ HTTP/WebSocket ││ ▼ ││ ┌───────────────────────────────────────────────────┐ ││ │ FastAPI (webui/api.py) │ ││ │ Pattern compute, WebSocket push │ ││ └───────────────────────────────────────────────────┘ ││ │ ││ Shared NanoVNA ││ ▼ ││ ┌───────────────────────────────────────────────────┐ ││ │ mcnanovna MCP server │ ││ │ (same process, asyncio.Lock) │ ││ └───────────────────────────────────────────────────┘ │└─────────────────────────────────────────────────────────┘The web UI runs in a daemon thread sharing the same process as the MCP server. An asyncio.Lock prevents concurrent VNA access from web and MCP.