Skip to main content

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, HolaEdge classes 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.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

hola_graph-0.1.5.tar.gz (208.5 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

hola_graph-0.1.5-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (2.4 MB view details)

Uploaded CPython 3.14manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

hola_graph-0.1.5-cp314-cp314-macosx_11_0_arm64.whl (1.7 MB view details)

Uploaded CPython 3.14macOS 11.0+ ARM64

hola_graph-0.1.5-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (2.4 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

hola_graph-0.1.5-cp313-cp313-macosx_11_0_arm64.whl (1.7 MB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

hola_graph-0.1.5-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (2.4 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

hola_graph-0.1.5-cp312-cp312-macosx_11_0_arm64.whl (1.7 MB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

hola_graph-0.1.5-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (2.4 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

hola_graph-0.1.5-cp311-cp311-macosx_11_0_arm64.whl (1.7 MB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

hola_graph-0.1.5-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (2.4 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

hola_graph-0.1.5-cp310-cp310-macosx_11_0_arm64.whl (1.7 MB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

hola_graph-0.1.5-cp39-cp39-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (2.4 MB view details)

Uploaded CPython 3.9manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

hola_graph-0.1.5-cp39-cp39-macosx_11_0_arm64.whl (1.7 MB view details)

Uploaded CPython 3.9macOS 11.0+ ARM64

File details

Details for the file hola_graph-0.1.5.tar.gz.

File metadata

  • Download URL: hola_graph-0.1.5.tar.gz
  • Upload date:
  • Size: 208.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.2

File hashes

Hashes for hola_graph-0.1.5.tar.gz
Algorithm Hash digest
SHA256 235981328a1e0fcfcabdad09fca5428af9b270743f961fd28669c6cf8832840a
MD5 3449190359f634257d604c3322ac4131
BLAKE2b-256 84d6652ac0634eb111df59eee2162a87501542365ce2bcca3d715250aed11b2d

See more details on using hashes here.

File details

Details for the file hola_graph-0.1.5-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for hola_graph-0.1.5-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 c786a39ef925ad07f5b328f9237d01073bfbb7bb5e26e7b93e1247f9c4e7c1fd
MD5 ae5e5f5a144718b6f7aceec872300370
BLAKE2b-256 6b567157d48b8b10722f74b141fdfe220e3c67f52d0b9c180bb5eb786ff497ea

See more details on using hashes here.

File details

Details for the file hola_graph-0.1.5-cp314-cp314-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for hola_graph-0.1.5-cp314-cp314-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 8daceb44722f2169929627178e83018286bd38cbf83f528dbf8b5c65bf695e79
MD5 9343ea0d604e93f5df0bc01f1494cb8c
BLAKE2b-256 9667694542a0480efe70fcfd3223cfa9807df7e6b9b053e9a9804b5cbf8e92ef

See more details on using hashes here.

File details

Details for the file hola_graph-0.1.5-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for hola_graph-0.1.5-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 0220c4a7da1e54a4d1fbd150c9ce6120ae3dc7cd34b2a49b48bbf6b670d70dbe
MD5 8b44258038460a626a446b932b77e0c5
BLAKE2b-256 64b79cae0bd47a71eb9dfedb4370c65ceab3255372ef8e6b4ba86f383cb06d73

See more details on using hashes here.

File details

Details for the file hola_graph-0.1.5-cp313-cp313-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for hola_graph-0.1.5-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 525fdd7f03aa1c008f55688f2a1408e4a8c2b50e81f024c7a3522a3122e043ca
MD5 0ab5c7d079e7b903645ecccc52db9f60
BLAKE2b-256 3b3541434f1f0460dec5e350ada6bd2838bdbfc80caa2f4fc74d31d558a97aa4

See more details on using hashes here.

File details

Details for the file hola_graph-0.1.5-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for hola_graph-0.1.5-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 89a688465301771a4a863c20b5831f1c6b607173d216183c4ab65de3b1bdddd7
MD5 cc06ae7d4f65c9d9fa04f517e5a3f9cf
BLAKE2b-256 fc8ddfb0c6d95836ea5bda3dc4d38f471dd8f06ae4c6ba1c9eff482c70e38d14

See more details on using hashes here.

File details

Details for the file hola_graph-0.1.5-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for hola_graph-0.1.5-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 228ea5c2bb64d57629d46364b90294f95a26c2d7647f8d572fe7a09c733f78ec
MD5 9edf9c9f2e4355ebc31b4b95b978a954
BLAKE2b-256 af42b262ec3131061ae2830ca7a366931cb5d66bff24c4b87bc2a955cacdafc0

See more details on using hashes here.

File details

Details for the file hola_graph-0.1.5-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for hola_graph-0.1.5-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 e4d82ea0f9b18bac6b0b219f63e74a3fee4e8cf47aeb6df45d54c8dc1a4fb176
MD5 82cc9dd289f33ff497bc259ad4709f8d
BLAKE2b-256 210bfea9b73a9517c4b7eb50484aaa5d22e00b16568d2567780cd283e5ddc522

See more details on using hashes here.

File details

Details for the file hola_graph-0.1.5-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for hola_graph-0.1.5-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 e9b3ca21999079a6cdc9900a0c0ae8828be56aa03daa5fbba5d333bd552f242b
MD5 b25495f1f0aa4750f661af3bf791d2e8
BLAKE2b-256 b3d0300bae2d767b7153996af93c581c9fc1437016f72e10bcfb4f80fe34d145

See more details on using hashes here.

File details

Details for the file hola_graph-0.1.5-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for hola_graph-0.1.5-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 25c8ba12a52726e6f3bf3af0fcf7ee8a385f0a5555a856df8665fda694a3a141
MD5 17f1fd72da62d0eeec220948cd927c83
BLAKE2b-256 f7b34d00ddaa2fad1ec07552cafa7940cdb7048bf96cd2a8d6187f550e050be3

See more details on using hashes here.

File details

Details for the file hola_graph-0.1.5-cp310-cp310-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for hola_graph-0.1.5-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 012444a68032ebdde9bab1b30ffb99bd0de87f395ab74f93162ae29192745830
MD5 df671a5060fc0284986dfcda9ea1454b
BLAKE2b-256 1065a35370ce3bacde68a1070d2af5f3c731ca6ed83304360eac37e324e80e70

See more details on using hashes here.

File details

Details for the file hola_graph-0.1.5-cp39-cp39-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for hola_graph-0.1.5-cp39-cp39-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 34c94a432e4e777c9a95b971c2d5d4e7f4bd261f5e705e08e809b5f8fde67648
MD5 751785205a9075701c38ab44e524f28e
BLAKE2b-256 6a6b9dd40afff469a3db765de988ee16c401bc573325e71664f1b318baf24653

See more details on using hashes here.

File details

Details for the file hola_graph-0.1.5-cp39-cp39-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for hola_graph-0.1.5-cp39-cp39-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 05d92e6f3e095dde16a04ea851c1a7f0ece5da1ce3ab7686931d24cffe8454df
MD5 36722cd420275033509376ef6e4483be
BLAKE2b-256 74b0293757b40271f9d89e1dd0ebad3c8cc76a2207c68199064dcaac3eb8eb38

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page