griphogram
Animated visualization of gradient flow across distributed ML graph topologies.
Generates publication-quality GIFs showing how gradient tensors propagate between model replicas under different aggregation strategies — AllReduce, Gossip Protocol, and Parameter Server — on fully-connected or custom graph topologies.
Installation
pip install griphogram
Requires Python ≥ 3.11 and Pillow ≥ 10.0.
Quick Start
from griphogram import GraphBuilder, GIFRenderer, AllReduceStrategy
# Define a weighted adjacency matrix (edge weights = gradient magnitudes)
adj_matrix = [
[0.0, 0.82, 0.57, 0.93, 0.68],
[0.82, 0.0, 0.45, 0.71, 0.86],
[0.57, 0.45, 0.0, 0.63, 0.39],
[0.93, 0.71, 0.63, 0.0, 0.78],
[0.68, 0.86, 0.39, 0.78, 0.0],
]
graph = (
GraphBuilder()
.with_adjacency_matrix(adj_matrix, center=(800, 620), radius=330)
.build()
)
GIFRenderer(graph, AllReduceStrategy()).render_gif("allreduce.gif")
CLI
# Generate all three canonical GIFs
griphogram --output-dir ./gifs --width 800 --height 600 --fps 18 --duration 6.0
# Or via module
python -m griphogram -o ./gifs
Package Layout
src/griphogram/
├── __init__.py # Public API surface
├── __main__.py # CLI entry point
├── types.py # StrEnum, dataclasses, Protocol, TypeAlias
├── graph.py # Node, CurvedEdge, Graph, GraphBuilder
├── particles.py # Shape renderers (match/case dispatch)
├── renderer.py # GIFRenderer (Template Method)
├── theme.py # Visual theme configuration
└── strategy/
├── allreduce.py # Ring-AllReduce
├── gossip.py # Decentralized SGD
└── parameter_server.py
Custom Strategies
Any class that satisfies the AggregationStrategy protocol works — no
inheritance is required:
from griphogram.types import EdgeDescriptor, Particle
class MyCustomStrategy:
@property
def title(self) -> str:
return "My Strategy"
@property
def subtitle(self) -> str:
return "custom gradient exchange"
def get_phase_text(self, frame: int, total_frames: int) -> str:
return f"Step {frame}"
def get_edge_alpha(self, src: int, dst: int, frame: int, total_frames: int) -> float:
return 1.0
def get_particles(
self, edges: list[EdgeDescriptor], frame: int, total_frames: int,
) -> list[Particle]:
particles = []
for edge in edges:
t = (frame / total_frames) % 1.0
x, y = edge.bezier_fn(t)
particles.append(Particle(x, y, edge.style.color, edge.style.shape))
return particles
Development
# Install in editable mode with dev dependencies
pip install -e ".[dev]"
# Run tests
pytest # fast tests only
pytest -m slow # GIF rendering tests
pytest --cov=griphogram # with coverage
# Lint & type-check
ruff check src/ tests/
mypy src/
Release files for griphogram 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| griphogram-0.1.0.tar.gz | 5.8 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| griphogram-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 5.8 MB
Release files / griphogram-0.1.0.tar.gz
| Download URL | griphogram-0.1.0.tar.gz |
|---|---|
| Size | 5.8 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
699737f0920f033f15ce7062cb14f2ed998b5d04924b6bdceb1544b5f75ee2f0
|
|
BLAKE2b-256 checksum How to use checksums |
d367db6c44937e44f80ceff808ce59ef5d3fc3e25d119e1e5bbf32832188c4c2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.12
|
Release files / griphogram-0.1.0-py3-none-any.whl
| Download URL | griphogram-0.1.0-py3-none-any.whl |
|---|---|
| Size | 20.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
f774548bfad909b4da7f0c2d0876d7a56346379bb06990229b7f2d2281dc589d
|
|
BLAKE2b-256 checksum How to use checksums |
f2a16a7cadf931b63059d0995a94ac33ab459e155ad0c2e7e8d3db21f5150e2d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.12
|