hola-graph
A Python wrapper for the HOLA (Human-like Orthogonal Layout Algorithm) from the adaptagrams C++ library. HOLA produces graph layouts that approximate what a human would create - clean, orthogonal, and aesthetically pleasing.
Based on the research paper: HOLA: Human-like Orthogonal Network Layout (Kieffer, Dwyer, Marriott, Wybrow - IEEE TVCG 2016).
Features
- HOLA Layout Algorithm: Produces human-like orthogonal graph layouts
- High-Level API:
HolaGraph,HolaNode,HolaEdgeclasses with Pythonic interface - Low-Level Bindings: Direct access to C++ classes via
hola_graph._core - File I/O: Load/save graphs in TGLF format, export to SVG and JSON
- NetworkX Integration: Convert between hola-graph and NetworkX graphs
- Matplotlib Visualization: Plot graphs directly with customizable styling
- Layout Options: Configurable via HolaOpts and ColaOptions classes
- Geometric Types: Point, Box, Polygon, Rectangle from libavoid
Installation
Note that currently wheels are only available for linux and macos for python versions 3.9-3.14:
pip install hola-graph
or
uv add hola-graph
Building
Requirements:
- Python 3.9+
- C++14 compatible compiler
- CMake 3.18+
# Clone the repository
git clone https://github.com/shakfu/hola-graph.git
cd hola-graph
# Build (downloads and compiles adaptagrams automatically)
make
# or
make build
# Run tests to verify installation
make test
Or build directly with uv/pip:
uv build # Creates wheel and sdist in dist/
pip install .
Quick Start
Basic Usage (High-Level API)
from hola_graph import HolaGraph
# Create a graph
g = HolaGraph()
# Add nodes (width, height) - returns the created node
a = g.add_node(30, 20, label="A")
b = g.add_node(30, 20, label="B")
c = g.add_node(30, 20, label="C")
# Connect nodes
g.connect(a, b)
g.connect(b, c)
# Apply HOLA layout
g.layout()
# Export to SVG
g.to_svg("graph.svg")
# Access node properties
print(f"Node A position: ({a.x}, {a.y})")
print(f"Node A size: {a.width} x {a.height}")
Loading from File
from hola_graph import HolaGraph
# Load, layout, and export
g = HolaGraph.from_tglf("input.tglf")
g.layout()
g.to_svg("output.svg")
# Iterate over nodes and edges
for node in g.nodes:
print(f"{node.label}: ({node.x}, {node.y})")
for edge in g.edges:
print(f"Edge {edge.id}: {edge.source} -> {edge.target}")
Low-Level API (Direct C++ Bindings)
For advanced use cases, access the C++ bindings directly:
from hola_graph._core import Graph, Node, Edge, do_hola, HolaOpts
# Create a graph
g = Graph()
# Add nodes (width, height)
n1 = Node.allocate(30, 20)
n2 = Node.allocate(30, 20)
g.add_node(n1)
g.add_node(n2)
g.add_edge(n1, n2)
# Apply layout with options
opts = HolaOpts()
opts.nodePaddingScalar = 1.5
do_hola(g, opts)
# Export
with open("graph.svg", "w") as f:
f.write(g.to_svg())
NetworkX Integration
import networkx as nx
from hola_graph import utils as pu
# Create from NetworkX graph
nx_graph = nx.karate_club_graph()
g = pu.from_networkx(nx_graph, node_width=25, node_height=25)
pu.apply_hola(g)
# Or get positions for NetworkX visualization
pos = pu.layout_networkx(nx_graph)
nx.draw(nx_graph, pos=pos)
Matplotlib Visualization
from hola_graph import utils as pu
import matplotlib.pyplot as plt
g = pu.load_graph("graph.tglf")
pu.apply_hola(g)
# Display
pu.plot_graph(g, title="My Graph", node_color="lightgreen")
plt.show()
# Or save to file
pu.save_plot(g, "graph.png", dpi=150)
JSON Serialization
from hola_graph import utils as pu
# Export to JSON
json_str = pu.to_json(g)
pu.save_json(g, "graph.json")
# Import from JSON
g = pu.from_json(json_str)
g = pu.load_json("graph.json")
API Reference
High-Level API (hola_graph)
| Class | Description |
|---|---|
HolaGraph |
Main graph class with Pythonic interface |
HolaNode |
Node with position, size, and label properties |
HolaEdge |
Frozen dataclass representing an edge |
HolaGraph Methods
# Construction
g = HolaGraph() # Create empty graph
g = HolaGraph.from_tglf(path) # Load from TGLF file
# Adding nodes and edges
node = g.add_node(w, h) # Add node, returns HolaNode
node = g.add_node(w, h, label="A") # Add node with label
g.connect(node1, node2) # Connect two nodes
# Layout and export
g.layout() # Apply HOLA layout
g.layout(opts) # Apply with HolaOpts
g.to_svg(path) # Export to SVG file
svg_str = g.to_svg() # Get SVG as string
tglf_str = g.to_tglf() # Get TGLF as string
# Properties
g.nodes # List of HolaNode objects
g.edges # List of HolaEdge objects
len(g) # Number of nodes
HolaNode Properties
node.id # Unique node ID
node.label # Node label (auto-generated if not set)
node.x, node.y # Center position
node.position # (x, y) tuple
node.width, node.height # Dimensions
node.size # (width, height) tuple
HolaEdge Attributes
edge.id # Unique edge ID
edge.source # Source node ID
edge.target # Target node ID
Low-Level API (hola_graph._core)
| Class | Description |
|---|---|
Graph |
C++ graph container |
Node |
C++ graph vertex |
Edge |
C++ connection between nodes |
HolaOpts |
Configuration for HOLA algorithm |
ColaOptions |
Configuration for constraint-based layout |
| Function | Description |
|---|---|
do_hola(graph, opts=None) |
Apply HOLA layout algorithm |
graph_from_tglf_file(path) |
Load graph from TGLF file |
Utility Functions (hola_graph.utils)
# File I/O
load_graph(path) # Load from TGLF
save_svg(graph, path) # Save as SVG
save_tglf(graph, path) # Save as TGLF
load_json(path) / save_json(g, p) # JSON I/O
# Graph building
create_node(w, h, x=None, y=None) # Create validated node
GraphBuilder() # Fluent graph construction
# Layout helpers
apply_hola(graph, opts=None) # Apply layout, return graph
compact_layout_opts() # Preset for dense layouts
spacious_layout_opts() # Preset for spread-out layouts
layout_context(graph) # Context manager for temporary layout
# Analysis
graph_stats(graph) # Get statistics dict
print_graph_info(graph) # Print summary
# NetworkX
to_networkx(graph) # Convert to NetworkX
from_networkx(nx_graph) # Convert from NetworkX
layout_networkx(nx_graph) # Get HOLA positions for NetworkX
# Visualization
plot_graph(graph, ax=None, ...) # Plot with matplotlib
save_plot(graph, path, ...) # Save visualization
plot_comparison(g1, g2, ...) # Side-by-side comparison
Optional Dependencies
Install with pip for additional features:
pip install networkx # For NetworkX integration
pip install matplotlib # For visualization
Or install all optional dependencies:
pip install hola-graph[all]
SWIG Wrapper
The adaptagrams library also provides a comprehensive SWIG-based Python wrapper. If swig is available, build it with:
make swig-python
The extension will be in build/adaptagrams/build.
Credits
HOLA algorithm authors:
Steve Kieffer, Tim Dwyer, Kim Marriott, and Michael Wybrow. HOLA: Human-like Orthogonal Network Layout. IEEE Transactions on Visualization and Computer Graphics, Volume 22, Issue 1, pages 349-358. IEEE, 2016.
This project builds against a fork of adaptagrams with CMake support.
Thanks to Wenzel Jakob for pybind11.
License
MIT License. See LICENSE for details.
Metadata
Release files for hola-graph 0.1.5
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| hola_graph-0.1.5.tar.gz | 208.5 kB | Without provenance | Details |
Built distributions (wheels)
Total release size: 24.8 MB
Release files / hola_graph-0.1.5.tar.gz
| Download URL | hola_graph-0.1.5.tar.gz |
|---|---|
| Size | 208.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
235981328a1e0fcfcabdad09fca5428af9b270743f961fd28669c6cf8832840a
|
|
BLAKE2b-256 checksum How to use checksums |
84d6652ac0634eb111df59eee2162a87501542365ce2bcca3d715250aed11b2d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.2
|
Release files / hola_graph-0.1.5-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
| Download URL | hola_graph-0.1.5-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl |
|---|---|
| Size | 2.4 MB |
| Tags | CPython 3.14 Linux glibc 2.27+ x86-64 Linux glibc 2.28+ x86-64 |
|
SHA-256 checksum How to use checksums |
c786a39ef925ad07f5b328f9237d01073bfbb7bb5e26e7b93e1247f9c4e7c1fd
|
|
BLAKE2b-256 checksum How to use checksums |
6b567157d48b8b10722f74b141fdfe220e3c67f52d0b9c180bb5eb786ff497ea
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.2
|
Release files / hola_graph-0.1.5-cp314-cp314-macosx_11_0_arm64.whl
| Download URL | hola_graph-0.1.5-cp314-cp314-macosx_11_0_arm64.whl |
|---|---|
| Size | 1.7 MB |
| Tags | CPython 3.14 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
8daceb44722f2169929627178e83018286bd38cbf83f528dbf8b5c65bf695e79
|
|
BLAKE2b-256 checksum How to use checksums |
9667694542a0480efe70fcfd3223cfa9807df7e6b9b053e9a9804b5cbf8e92ef
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.2
|
Release files / hola_graph-0.1.5-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
| Download URL | hola_graph-0.1.5-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl |
|---|---|
| Size | 2.4 MB |
| Tags | CPython 3.13 Linux glibc 2.27+ x86-64 Linux glibc 2.28+ x86-64 |
|
SHA-256 checksum How to use checksums |
0220c4a7da1e54a4d1fbd150c9ce6120ae3dc7cd34b2a49b48bbf6b670d70dbe
|
|
BLAKE2b-256 checksum How to use checksums |
64b79cae0bd47a71eb9dfedb4370c65ceab3255372ef8e6b4ba86f383cb06d73
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.2
|
Release files / hola_graph-0.1.5-cp313-cp313-macosx_11_0_arm64.whl
| Download URL | hola_graph-0.1.5-cp313-cp313-macosx_11_0_arm64.whl |
|---|---|
| Size | 1.7 MB |
| Tags | CPython 3.13 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
525fdd7f03aa1c008f55688f2a1408e4a8c2b50e81f024c7a3522a3122e043ca
|
|
BLAKE2b-256 checksum How to use checksums |
3b3541434f1f0460dec5e350ada6bd2838bdbfc80caa2f4fc74d31d558a97aa4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.2
|
Release files / hola_graph-0.1.5-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
| Download URL | hola_graph-0.1.5-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl |
|---|---|
| Size | 2.4 MB |
| Tags | CPython 3.12 Linux glibc 2.27+ x86-64 Linux glibc 2.28+ x86-64 |
|
SHA-256 checksum How to use checksums |
89a688465301771a4a863c20b5831f1c6b607173d216183c4ab65de3b1bdddd7
|
|
BLAKE2b-256 checksum How to use checksums |
fc8ddfb0c6d95836ea5bda3dc4d38f471dd8f06ae4c6ba1c9eff482c70e38d14
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.2
|
Release files / hola_graph-0.1.5-cp312-cp312-macosx_11_0_arm64.whl
| Download URL | hola_graph-0.1.5-cp312-cp312-macosx_11_0_arm64.whl |
|---|---|
| Size | 1.7 MB |
| Tags | CPython 3.12 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
228ea5c2bb64d57629d46364b90294f95a26c2d7647f8d572fe7a09c733f78ec
|
|
BLAKE2b-256 checksum How to use checksums |
af42b262ec3131061ae2830ca7a366931cb5d66bff24c4b87bc2a955cacdafc0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.2
|
Release files / hola_graph-0.1.5-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
| Download URL | hola_graph-0.1.5-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl |
|---|---|
| Size | 2.4 MB |
| Tags | CPython 3.11 Linux glibc 2.27+ x86-64 Linux glibc 2.28+ x86-64 |
|
SHA-256 checksum How to use checksums |
e4d82ea0f9b18bac6b0b219f63e74a3fee4e8cf47aeb6df45d54c8dc1a4fb176
|
|
BLAKE2b-256 checksum How to use checksums |
210bfea9b73a9517c4b7eb50484aaa5d22e00b16568d2567780cd283e5ddc522
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.2
|
Release files / hola_graph-0.1.5-cp311-cp311-macosx_11_0_arm64.whl
| Download URL | hola_graph-0.1.5-cp311-cp311-macosx_11_0_arm64.whl |
|---|---|
| Size | 1.7 MB |
| Tags | CPython 3.11 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
e9b3ca21999079a6cdc9900a0c0ae8828be56aa03daa5fbba5d333bd552f242b
|
|
BLAKE2b-256 checksum How to use checksums |
b3d0300bae2d767b7153996af93c581c9fc1437016f72e10bcfb4f80fe34d145
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.2
|
Release files / hola_graph-0.1.5-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
| Download URL | hola_graph-0.1.5-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl |
|---|---|
| Size | 2.4 MB |
| Tags | CPython 3.10 Linux glibc 2.27+ x86-64 Linux glibc 2.28+ x86-64 |
|
SHA-256 checksum How to use checksums |
25c8ba12a52726e6f3bf3af0fcf7ee8a385f0a5555a856df8665fda694a3a141
|
|
BLAKE2b-256 checksum How to use checksums |
f7b34d00ddaa2fad1ec07552cafa7940cdb7048bf96cd2a8d6187f550e050be3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.2
|
Release files / hola_graph-0.1.5-cp310-cp310-macosx_11_0_arm64.whl
| Download URL | hola_graph-0.1.5-cp310-cp310-macosx_11_0_arm64.whl |
|---|---|
| Size | 1.7 MB |
| Tags | CPython 3.10 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
012444a68032ebdde9bab1b30ffb99bd0de87f395ab74f93162ae29192745830
|
|
BLAKE2b-256 checksum How to use checksums |
1065a35370ce3bacde68a1070d2af5f3c731ca6ed83304360eac37e324e80e70
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.2
|
Release files / hola_graph-0.1.5-cp39-cp39-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
| Download URL | hola_graph-0.1.5-cp39-cp39-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl |
|---|---|
| Size | 2.4 MB |
| Tags | CPython 3.9 Linux glibc 2.27+ x86-64 Linux glibc 2.28+ x86-64 |
|
SHA-256 checksum How to use checksums |
34c94a432e4e777c9a95b971c2d5d4e7f4bd261f5e705e08e809b5f8fde67648
|
|
BLAKE2b-256 checksum How to use checksums |
6a6b9dd40afff469a3db765de988ee16c401bc573325e71664f1b318baf24653
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.2
|
Release files / hola_graph-0.1.5-cp39-cp39-macosx_11_0_arm64.whl
| Download URL | hola_graph-0.1.5-cp39-cp39-macosx_11_0_arm64.whl |
|---|---|
| Size | 1.7 MB |
| Tags | CPython 3.9 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
05d92e6f3e095dde16a04ea851c1a7f0ece5da1ce3ab7686931d24cffe8454df
|
|
BLAKE2b-256 checksum How to use checksums |
74b0293757b40271f9d89e1dd0ebad3c8cc76a2207c68199064dcaac3eb8eb38
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.2
|
Security for hola-graph 0.1.5
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.