GLIMPSE is a graph-based desktop application to visualize and update GridLAB-D power grid models. With GLIMPSE, you can:
- Search and highlight power grid model objects
- Update model attributes
- Export modified models for future simulations
- Leverage GPU acceleration for rendering large power grids
The application is built with React.js, Electron.js, Node.js, Sigma.js, and Python.
Note
If you're looking for the EPA-developed energy planning tool called glimpse, visit epa.gov/glimpse.
This section will walk you through installing dependencies and building GLIMPSE. Here's what you'll do:
- ✅ Install Node.js (and optionally Nim)
- ✅ Clone the repository and install Node dependencies
- ✅ Create and activate a Python environment
- ✅ Install Python dependencies and plugins
- ✅ Start the development server
- Node.js — Required for all users
- Nim — Only needed if:
- You're on Apple silicon (M chips), OR
- You plan to export modified GLM files
In a directory of your choice, clone the repository:
git clone http://github.com/pnnl/GLIMPSEcd GLIMPSE
npm installNavigate to the local server directory:
cd GLIMPSE/local-server/Option A: UV (Recommended)
uv syncOption B: VENV
python -m venv .venvOption C: Conda
conda create -n glimpse_env
conda activate glimpse_env| Platform | Shell | Command |
|---|---|---|
| POSIX | bash/zsh | source .venv/bin/activate |
| - | fish | source .venv/bin/activate.fish |
| - | csh/tcsh | source .venv/bin/activate.csh |
| - | PowerShell | .\.venv\Scripts\activate.ps1 |
| Windows | cmd.exe | .venv\Scripts\activate.bat |
| - | PowerShell | .\.venv\Scripts\activate.ps1 |
| macOS | bash/zsh | source .venv/bin/activate |
Note
You'll know the environment is active when you see (.venv) at the start of your command line.
For conda, use conda activate glimpse_env instead.
If you used VENV or Conda, install requirements:
pip install -r requirements.txtWith PIP:
pip install glmWith UV:
uv pip install glmYou'll need to build the GLM parser from source using Nim.
Clone the glm parser repository i forked:
cd GLIMPSE/local-server/git clone https://github.com/itsMando/glm.gitcd glmBuild the parser (ensure Nim is installed and in your PATH):
nimble -vnimble release
nimble packageInstall the python binary distributable from dist/ folder:
With PIP:
pip install dist/*.whlWith UV:
uv pip install dist/*.whlFrom the GLIMPSE/ root directory, run:
npm run devThe application will start in development mode. Open your browser and navigate to the provided local address (typically http://localhost:5173/) to access GLIMPSE.
GLIMPSE can also run as a standalone desktop application. The Electron shell starts the bundled local server automatically on launch and shuts it down (including all child processes) when the window is closed — no terminal or browser needed.
Note
These steps assume you have completed the Build from Source setup above (Node dependencies and the Python environment for local-server/). The Python environment must include pyinstaller, which is listed in both local-server/requirements.txt and local-server/pyproject.toml.
Runs the Python backend, the Vite dev server, and Electron together (with hot reload). Closing the Electron window stops all three:
npm run electron:devInstallers are built on and for the OS you are running (electron-builder cannot cross-compile, e.g. a Windows installer must be built on Windows):
npm run dist # build for the current OS
npm run dist:linux # AppImage + .deb (run on Linux)
npm run dist:win # NSIS installer (run on Windows)
npm run dist:mac # .dmg (run on macOS)Each dist command runs three steps:
vite build— bundles the React frontend intodist/pyinstaller server.spec— freezes the Python backend (with its Python runtime) intolocal-server/dist/server/electron-builder— packages both into an installer inrelease/
The finished installer is written to the release/ directory. The installed app needs no Node or Python on the target machine — the backend is fully self-contained.
Tip
If pyinstaller is not on your PATH, activate the Python environment you created for local-server/ first (or, with UV, run uv run pyinstaller server.spec --noconfirm inside local-server/).
The repository ships with a Docker Compose setup that builds and runs GLIMPSE as two containers — the React frontend (served by nginx) and the Flask + SocketIO backend — so you don't need to install Node, Python, or any of the plugins yourself.
Note
This section assumes you already have a working Docker Engine with the Docker Compose plugin (docker compose version should print a version). If not, see Docker's install guide.
git clone http://github.com/pnnl/GLIMPSE
cd GLIMPSEFrom the GLIMPSE/ root directory (where docker-compose.yml lives), run:
docker compose up --buildThe first build takes a few minutes while images are created; subsequent runs are cached and start quickly. Add -d to run detached (in the background):
docker compose up --build -dOnce the containers are running, open your browser and navigate to:
http://localhost:5173
The frontend serves the UI on port 5173 and the backend listens on port 5052.
docker compose downThis stops and removes the containers and network. Built images remain cached for the next start. (If you ran in the foreground, you can also press Ctrl+C first, then run docker compose down to clean up.)
The desktop app runs the backend bound to 127.0.0.1 (loopback only), so the defaults below are safe as-is. A networked deployment is different: the Docker backend binds to 0.0.0.0, which makes it reachable by any client that can route to the port. Because the backend has no per-user login, treat the following environment variables as required hardening before exposing it beyond localhost.
| Variable | Applies to | Default | Purpose |
|---|---|---|---|
GLIMPSE_API_TOKEN |
backend + frontend | (empty → auth off) | Shared bearer token. When set, every HTTP request and WebSocket connection must present it or is rejected (401 / refused handshake). Compose passes the same value to the backend (GLIMPSE_API_TOKEN) and the frontend (API_TOKEN). |
CORS_ORIGINS |
backend | local dev ports | Comma-separated list of browser origins allowed to call the API (e.g. https://glimpse.example.org). * allows any origin but disables credentialed CORS. Pin this to your frontend's real origin in production. |
GLIMPSE_EXPORT_DIR |
backend | system temp /glimpse_exports |
Directory that CIM export writes are confined to. Client-supplied export paths are resolved inside this directory; absolute paths and .. traversal are rejected. |
GLIMPSE_ALLOW_ANY_EXPORT_PATH |
backend | 0 |
Set to 1 only for a desktop build where the user intentionally picks any save location. Disables the export-path confinement above — do not enable on a shared/networked server. |
MAX_UPLOAD_MB |
backend | 50 |
Maximum request body size (MB) for uploads, to bound memory use. Requests over the limit get 413. |
GLIMPSE_MODELS_DIR |
backend | auto-detected | Directory holding the bundled example models offered in the "Example Models" tab. By default the backend looks for a models/ folder next to the server (PyInstaller bundle / Docker bind mount) and then the repo's top-level models/ folder. Missing files are simply not offered. |
EXPOSE_TRACEBACKS |
backend | 0 |
When 1, includes Python tracebacks in error responses (useful for local debugging). Leave off in production so internal details aren't leaked to clients. |
GRIDAPPSD_ADDRESS / GRIDAPPSD_PORT / GRIDAPPSD_USER / GRIDAPPSD_PASSWORD |
backend | localhost / 61613 / system / manager |
GridAPPS-D broker connection. The defaults are GridAPPS-D's own defaults — change the credentials for any real broker and source them from your secret store, not the compose file. |
CIMG_URL |
backend | derived from GRIDAPPSD_ADDRESS |
Blazegraph SPARQL endpoint used for CIM model loads (http://<GRIDAPPSD_ADDRESS host>:8889/bigdata/namespace/kb/sparql by default, matching a standard GridAPPS-D deployment). Set explicitly when Blazegraph runs on a different host/port. The other CIMG_* cimgraph settings can be overridden the same way. |
GLIMPSE_SPARQL_TIMEOUT |
backend | 120 |
Per-query timeout (seconds) for Blazegraph SPARQL queries during CIM model loads, so one stalled query can't hang a load forever. Raise it if a very slow Blazegraph instance times out on large models. |
GLIMPSE_SPARQL_MAX_CONCURRENT |
backend | 4 |
Maximum in-flight SPARQL queries during a CIM model load. Caps the pressure on the Blazegraph JVM when loading large models (e.g. IEEE 9500); raise it on a beefy Blazegraph host for faster loads. |
Generate a random secret and set it before starting the stack — both containers pick it up:
export GLIMPSE_API_TOKEN="$(openssl rand -hex 32)"
docker compose up --buildImportant
This token is a coarse gate, not per-user authentication. It is embedded in the frontend bundle (served in env.js and sent on every request), so anyone who can load the UI can read it. Its job is to keep arbitrary network clients that don't have the frontend from reaching the 0.0.0.0-bound backend. If you need real per-user authorization, put GLIMPSE behind an authenticating reverse proxy or add session/OAuth login on top of this gate. For anything sensitive, also terminate TLS at a proxy so the token isn't sent in cleartext.
GLIMPSE supports two JSON file formats for custom graph visualizations:
-
GLIMPSE JSON Format — Based on glm2json parser output
-
NetworkX Node-Link Format — From NetworkX's node_link_data function
To get started with GridLAB-D models:
- Start with example models in
GLIMPSE/testing/123/— upload all.glmfiles from this folder - Try larger models:
3000/,8500/, and9500/to experience GPU-accelerated rendering with Sigma.js - To re-upload files after visualization, click the LOAD button at the top right
GLIMPSE can import and export CIM (Common Information Model) files.
- Example CIM files are available here
- Modified models can be exported as CIM/XML files through the GLIMPSE interface
GLIMPSE exposes a SocketIO event API so external scripts can load graphs and update the live visualization — adding, removing, restyling, hiding, and showing nodes and edges in any connected frontend. Both the GLIMPSE JSON format and NetworkX node-link data are accepted.
- Full reference:
socket-testing/EVENTS_API.md— payload shapes, field references, the data model, and example clients. - Runnable examples:
socket-testing/— connect and exercise every event (load-graph,update,add-node,add-edge,delete-node,delete-edge).
import socketio, networkx as nx
sio = socketio.Client(); sio.connect("http://127.0.0.1:5052")
sio.call("load-graph", nx.node_link_data(nx.karate_club_graph()))
sio.call("update", {"id": "0", "elementType": "node",
"updates": {"color": "#ff0000", "size": 18, "hidden": None}})@inproceedings{sanchez2024glimpse,
title={GLIMPSE of Future Power Grid Models},
author={Sanchez, Armando Mendoza and Purohit, Sumit},
booktitle={2024 IEEE 18th International Conference on Semantic Computing (ICSC)},
pages={224--225},
year={2024},
organization={IEEE}
}