# VisualTorch: three diagram styles drawn from a real forward pass

> VisualTorch turns a PyTorch model into flow, graph or lenet diagrams by tracing one forward pass with a dummy input. It is quick for straight stacks and honest about what a single trace cannot show.

**willyfh/visualtorch** — VisualTorch aims to help visualize Torch-based neural network architectures.

- Repository: https://github.com/willyfh/visualtorch
- Website: https://visualtorch.readthedocs.io/en
- Stars: 334 · Forks: 20
- Language: Python
- License: MIT
- Published: 2026-09-10 · Updated: 2026-09-10 · Language: en
- Canonical page: https://hysenlabs.com/projects/willyfh-visualtorch

## How the diagram comes out of a traced forward pass

VisualTorch never reads your model class. It runs one forward pass against a dummy input whose shape you supply, and draws the graph that execution actually touched. That is why a single call path covers both `nn.Sequential` stacks and custom `nn.Module` classes that assemble their own layers: the input shape is the only contract between your model and the plotting code.

Sizes on the picture are measured rather than declared. Each box takes its size from the shape of the tensor the layer received, so the drawing follows the route your model walked at trace time rather than the layer list you typed.

Three canonical styles come out of that one trace, named `graph`, `flow` and `lenet`. The choice changes the layout, not the traced content, and `show_dimension=True` switches a node label from the first output tensor to every output tensor the layer returned.

Those visual styles were originally adapted from visualkeras, pytorchviz, pytorch-summary and torchview. What sits underneath now is VisualTorch's own unified tracing backend and its own architecture-handling logic, and version 1.0 replaced the earlier pipeline rather than extending it. The intended reader is a paper author: the README states the project has been used in published research in Nature, IEEE and MDPI, and asks for pull requests that add citing papers.

## Data-dependent branches only render the path the dummy input took

Tracing buys accuracy about the route taken and costs accuracy about the routes not taken. A layer that picks one branch only when a tensor value crosses a threshold is drawn along whichever branch the dummy input happened to take, and the other branch is missing from the picture rather than greyed out. The README calls this inherent to any tracing-based approach, says explicitly that it is not a bug, and says it cannot be fixed without full symbolic execution.

Multi-output layers carry a narrower quirk. A custom multi-task head, or `nn.LSTM` returning `(output, (h_n, c_n))`, keeps its node sized from the first tensor alone, so a box can read smaller than the layer's real output surface. Switching on `show_dimension=True` puts every output tensor's shape in the label, and downstream connections remain correct either way.

For a reviewer, the consequence is that one diagram is one trace. A model with a threshold gate or any layer whose behaviour keys off tensor values needs a second pass with a different dummy input before the picture covers the whole model. No parameter for forcing all branches is documented, and the README closes that paragraph by inviting contributions.

## Upgrading past 0.2.5 means rechecking every plotting call

Version 1.0 was a clean break. The README marks `1.0+` as a major release with breaking API changes, recommends upgrading, and keeps `0.2.5` as the last release carrying the old API. A script written against 0.2.x has to be read against the current API reference pages rather than patched in place.

The version history since then moves in small numbered steps. Release 1.3.0 was published on 2026-07-11, 1.4.0 on 2026-07-25 and 1.4.1 on 2026-07-28, and the last push to the repository is dated 2026-10-01. Release methodology and cadence are written down in GOVERNANCE.md at the repository root, with the PyPI release history page holding the past tags.

Licensing is the easy part of the decision: setup.py declares MIT and points license_files at LICENSE.md, matching the MIT terms the README cites. The Journal of Open Source Software paper carries a 2024 year and a DOI, and the README warns that it describes the project as of its publication date, after which the code was substantially refactored. Cite it, but take the API from the documentation, not from the paper's samples.

## pillow, aggdraw and a torch 2.0 floor decide what installs

Four runtime dependencies set the real installation constraint, and one of them is the framework itself. `requirements.txt` asks for `pillow>=10.0.0`, `numpy>=1.18.1`, `aggdraw>=1.3.19` and `torch>=2.0.0`. Torch therefore has to be 2.0 or newer, and aggdraw, which supplies the anti-aliased drawing primitives, is a hard requirement rather than an extra.

setup.py reads that file at build time and passes it to `install_requires`, so those floors are what a plain install gives you. It also sets `python_requires` to 3.10 and up and ships classifiers for 3.10, 3.11 and 3.12, which leaves Python 3.9 out of range.

The README prints no base install line. It sends you to the Installation page on visualtorch.readthedocs.io, and the one install command it does spell out covers the MCP extra, where the quoting matters:

```bash
pip install "visualtorch[mcp]"
```

That pulls the base package together with the `mcp` extra, which setup.py constrains to `mcp>=1.0.0,<2`. A second extra, `dev`, merges the docs and development requirement files for contributors. Anyone building from source also needs a setuptools build backend, since pyproject.toml requires `setuptools>=83.0.0` and wheel.

## animate() turns one trace into a GIF layer by layer

The quickest first result is the animated reveal, and it takes one call. Every style renders as an animated GIF that lays the model out one layer or column at a time, which turns a static architecture figure into something you can drop into a talk without hand-editing the image:

```python
visualtorch.animate(model, input_shape, style=...)
```

Three arguments are visible in that signature and nothing more: the module, the input shape to trace, and the style name. The documentation carries a separate animated reveal example for each of the three styles, so you can compare the flow, graph and lenet renderings on your own module before committing to one.

The same function is what the MCP server reaches for when it returns an animated reveal, and static PNG diagrams come out of the same tracing pass. The README does not document output paths, frame rates or resolution settings for either product, so a pipeline that needs a fixed file name or a specific pixel size is not covered by what the project publishes.

## The mcp extra registers a stdio server behind one console script

The optional MCP extra turns that tracing into something an assistant client can call. Installing it registers a single console script, `visualtorch-mcp`, wired to `visualtorch_mcp.server:main` through the entry_points table in setup.py. The server speaks stdio and is client-neutral, so the README states that no client-specific plugin or extension is required.

Its advertised surface is narrow and worth reading before you build on it: capability discovery, structured output metadata, documentation resources, subprocess timeouts, and all three canonical styles. It produces static PNG diagrams and animated GIF reveals from PyTorch model source. The code lives in a `visualtorch_mcp/` directory beside the main package, `server.json` sits at the repository root, and the README carries the identifier annotation `io.github.willyfh/visualtorch`.

Because the input is model source, the guide treats this as a trusted-code boundary, which matters for anyone wiring it to models fetched from elsewhere. That guide holds the tool schemas, a generic stdio configuration and worked examples. Subprocess timeouts are exposed as a capability, so a model that hangs during tracing has a stated bound on how long the server waits for it.

## The credited projects are where the styles came from, not the current engine

The credits line is the honest place to start a comparison, because VisualTorch's first visual styles came from there. The project was originally based on visualkeras under the MIT license, with further modifications inspired by pytorchviz, pytorch-summary and torchview, all MIT as well. What came afterwards is the engine: a unified tracing backend and its own architecture-handling logic, plus three canonical styles, the animate entry point and an MCP path.

Two differences decide it for most readers. First, diagram content follows one traced execution, so structure that keys off tensor values never appears in the drawing. If you need a conditional gate drawn whether or not it ran, tracing cannot give it to you and a static enumeration of layers is the approach to look for instead. Second, VisualTorch commits to animation output and to an agent-callable server, which pushes the effort toward slides and clients rather than toward one PNG per run.

Nothing in the repository compares the output against torchview or visualkeras feature by feature, so the useful comparison is the rendered picture on your own model plus whether you need the animated or MCP path at all.

## Conclusion

Adopt VisualTorch when you need a figure of a straight nn.Sequential stack or custom module today and want three layout styles plus an animated reveal from the same trace; the MIT license and the 1.4.1 release leave no friction there. Skip it when the architecture you need to explain is conditional or multi-head, because the drawing covers one traced path and no documented flag widens it, and skip it if your scripts are pinned to 0.2.5 with no time to move to the 1.x API. Before anything else, trace your real model with the input shape you intend to ship and look at the boxes: a layer narrower than its output tensor, or a missing route, means you have hit the trace limit rather than a rendering bug.

## FAQ

### Which Python versions does VisualTorch support?

setup.py sets python_requires to 3.10 and up and declares classifiers for Python 3.10, 3.11 and 3.12, so Python 3.9 and older are outside the supported range.

### How do I move a VisualTorch 0.2.5 script to the current API?

The README marks 1.0 and later as a major release with breaking API changes and recommends upgrading, keeping 0.2.5 or older for the old API. Current signatures live in the API reference section of the documentation.

### Does VisualTorch draw every branch of a conditional layer?

No. It traces a real forward pass, so a branch guarded by a tensor value appears only along the path the traced dummy input took. The README calls that inherent to tracing and says it cannot be fixed without full symbolic execution.

### What does VisualTorch require from torch, and what else comes with it?

requirements.txt asks for torch>=2.0.0 alongside pillow>=10.0.0, numpy>=1.18.1 and aggdraw>=1.3.19, and setup.py passes that file straight into install_requires.

### Can VisualTorch produce diagrams without writing plotting code?

Yes, through the optional MCP extra. Installed with pip install "visualtorch[mcp]", it registers the visualtorch-mcp console script, a client-neutral stdio server that returns static PNG diagrams and animated GIF reveals from PyTorch model source.

### What is the difference between the graph, flow and lenet styles?

All three are rendered from the same traced graph and differ in layout, not in content. The README names them as the canonical styles and publishes an animated reveal example for each one.

## Sources

- [License: MIT](https://github.com/willyfh/visualtorch/blob/main/LICENSE)
- [Project website](https://visualtorch.readthedocs.io/en)
- [README](https://github.com/willyfh/visualtorch/blob/main/README.md)
- [Releases](https://github.com/willyfh/visualtorch/releases)
- [willyfh/visualtorch on GitHub](https://github.com/willyfh/visualtorch)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/willyfh-visualtorch
