A pybind11 wrapper to adaptagrams HOLA: Human-like Orthogonal Layout Algorithm.
Project description
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
Requirements
- Python 3.9+
- C++14 compatible compiler
- CMake 3.18+
Building
# 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.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file hola_graph-0.1.4.tar.gz.
File metadata
- Download URL: hola_graph-0.1.4.tar.gz
- Upload date:
- Size: 181.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f6876fd0a3621c309fd697a91b27b50a89b2beaddd5e552bc2e9d0bc1cd41b50
|
|
| MD5 |
15fb8c11f33f4919e18fecb489538d00
|
|
| BLAKE2b-256 |
eec3bb2983c1ed19fd9ac6f40a816e6f9ae73d888284508bb7af890bb91d448d
|
File details
Details for the file hola_graph-0.1.4-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.
File metadata
- Download URL: hola_graph-0.1.4-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- Upload date:
- Size: 2.4 MB
- Tags: CPython 3.14, manylinux: glibc 2.27+ x86-64, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
34c66416d861147ef28c59faff59176a157213d1f65a26471fc16d2d293a7bbd
|
|
| MD5 |
6f9577ec075a608e6978216af15dcd4a
|
|
| BLAKE2b-256 |
b398b5e2e516c5a720b73719db3e52aedeff1bd5a3067c5d277a4b79b46083e7
|
File details
Details for the file hola_graph-0.1.4-cp314-cp314-macosx_11_0_arm64.whl.
File metadata
- Download URL: hola_graph-0.1.4-cp314-cp314-macosx_11_0_arm64.whl
- Upload date:
- Size: 1.7 MB
- Tags: CPython 3.14, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e209a6f3dbebcc024b80091340137c9729c1802b38d6de8d8a5c9c636156420c
|
|
| MD5 |
005afaf26e6b3e7b34a9cf60bd60c381
|
|
| BLAKE2b-256 |
71d98366421d100c29ac4331b42d6b335813f6d271103ca44bff00ec7b4f07a0
|
File details
Details for the file hola_graph-0.1.4-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.
File metadata
- Download URL: hola_graph-0.1.4-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- Upload date:
- Size: 2.4 MB
- Tags: CPython 3.13, manylinux: glibc 2.27+ x86-64, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9ba562e0d9b55e41407f08c2d474bf76d85442a6fafb96f28c83ae8e4db876e3
|
|
| MD5 |
38c295ea159f0ae0731254087a0d620c
|
|
| BLAKE2b-256 |
2067d791fbb3a23e1b70ff63f36725fd7bb2420f439d054b3531b72cc6979521
|
File details
Details for the file hola_graph-0.1.4-cp313-cp313-macosx_11_0_arm64.whl.
File metadata
- Download URL: hola_graph-0.1.4-cp313-cp313-macosx_11_0_arm64.whl
- Upload date:
- Size: 1.7 MB
- Tags: CPython 3.13, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
27c4cabe6a25173e9861bad2060c9cc93417fb6ce91ea2c111cb7ea5d56c1dd7
|
|
| MD5 |
7d6699103e6b380ad6bbc66bec10dcf8
|
|
| BLAKE2b-256 |
48ab4d75dd231978d9765cc4e33f16835d8485a38e56f227f74a2e0737230b2c
|
File details
Details for the file hola_graph-0.1.4-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.
File metadata
- Download URL: hola_graph-0.1.4-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- Upload date:
- Size: 2.4 MB
- Tags: CPython 3.12, manylinux: glibc 2.27+ x86-64, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1769021a941f187f266e19502f04673955737c09269f8e6fd8cfdd51440e1287
|
|
| MD5 |
63ad71d25c01550350744965cf517988
|
|
| BLAKE2b-256 |
21083c17d5a01ed9a9090a1f9ea74cddb7b1854a790b0093115ae92f6c014765
|
File details
Details for the file hola_graph-0.1.4-cp312-cp312-macosx_11_0_arm64.whl.
File metadata
- Download URL: hola_graph-0.1.4-cp312-cp312-macosx_11_0_arm64.whl
- Upload date:
- Size: 1.7 MB
- Tags: CPython 3.12, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e20b87f5077247e5d066f7661f9b7642098c2b0b77b30e177dca8d71045c5e8e
|
|
| MD5 |
e8aeb2ea62c48b3d03585275a6dea394
|
|
| BLAKE2b-256 |
01fcf802998730228d3b4a53f4941e46b280366ab7662d07ef44a7b5e95ddbb1
|
File details
Details for the file hola_graph-0.1.4-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.
File metadata
- Download URL: hola_graph-0.1.4-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- Upload date:
- Size: 2.4 MB
- Tags: CPython 3.11, manylinux: glibc 2.27+ x86-64, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
011b2f4b1fb62a83c66193a57b832315b5c4e6965207cfdc3be38695c5c4041b
|
|
| MD5 |
2ade82626ea6b0ba2c294d71b7f63a03
|
|
| BLAKE2b-256 |
d223f2ac15a6e9fb7125ec85dd49a5e0430a55e4f280d4f3ea982b7df0b787a1
|
File details
Details for the file hola_graph-0.1.4-cp311-cp311-macosx_11_0_arm64.whl.
File metadata
- Download URL: hola_graph-0.1.4-cp311-cp311-macosx_11_0_arm64.whl
- Upload date:
- Size: 1.7 MB
- Tags: CPython 3.11, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
547cc82b5566e85b9f987d008a3d8da1937cb5f8fefeca84232b71087b0d443c
|
|
| MD5 |
5e51f98022dac1a60d6157fadc1ce193
|
|
| BLAKE2b-256 |
f4edb592fa36e9724f72c511880580604eca370fbd17e129983fe8e2951fe7a3
|
File details
Details for the file hola_graph-0.1.4-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.
File metadata
- Download URL: hola_graph-0.1.4-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- Upload date:
- Size: 2.4 MB
- Tags: CPython 3.10, manylinux: glibc 2.27+ x86-64, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8aa4cdb2c3aeedcb383e067e4838a0df0f9dc6e5c6071691859638e4b4e7d450
|
|
| MD5 |
aa6bc465b612c22b84f4e5180705817a
|
|
| BLAKE2b-256 |
b1e934ea954217335f83ed252974b069e99bce18560f42c327302ef31b7b1fee
|
File details
Details for the file hola_graph-0.1.4-cp310-cp310-macosx_11_0_arm64.whl.
File metadata
- Download URL: hola_graph-0.1.4-cp310-cp310-macosx_11_0_arm64.whl
- Upload date:
- Size: 1.7 MB
- Tags: CPython 3.10, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
880e4957bf416efb9991ea52d3a8d85c0bf5d00cca6d40e85f33aa1078af1dc0
|
|
| MD5 |
a32c531c49ffb695b3173a46be107b77
|
|
| BLAKE2b-256 |
10bbb24fe9f7232c57cf7c2218a252580ed324bb4fd2b2b962d5ccfc1648cbb2
|
File details
Details for the file hola_graph-0.1.4-cp39-cp39-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.
File metadata
- Download URL: hola_graph-0.1.4-cp39-cp39-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- Upload date:
- Size: 2.4 MB
- Tags: CPython 3.9, manylinux: glibc 2.27+ x86-64, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4bda9559cfded817dc82b665ced2f30fec1b28e3be6294e4c576876d6195b116
|
|
| MD5 |
1cfed96c56f220f3548baf785c4761b7
|
|
| BLAKE2b-256 |
9c15a478730a3c4ff27711ba3eab850e479fdc60b72a67d4e33dbe22da9b441e
|
File details
Details for the file hola_graph-0.1.4-cp39-cp39-macosx_11_0_arm64.whl.
File metadata
- Download URL: hola_graph-0.1.4-cp39-cp39-macosx_11_0_arm64.whl
- Upload date:
- Size: 1.7 MB
- Tags: CPython 3.9, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4207e40cc9ec87cdc2c4faa65bb49135f596899cdd22969cca8e550c9e2e0703
|
|
| MD5 |
8d023065e2f2beb8412c3e6d798b2b49
|
|
| BLAKE2b-256 |
670318f81f67b30336a5d8614bbe629804593004aa0c8e0e0358bcc853060f20
|