Skip to main content

graph-layout - Python Graph Layout Library

A collection of graph layout algorithms in Python.

Written in pure Python with optional Cython acceleration. Prebuilt wheels are published for CPython 3.9-3.14 on Linux (x86_64/aarch64), macOS (Intel/Apple Silicon) and 64-bit Windows, so pip install needs no compiler there. The accelerated module is optional at runtime -- every algorithm falls back to pure Python if it is missing -- but building from the sdist does require a C compiler and CMake, which is what happens on platforms outside that matrix (musllinux/Alpine and 32-bit builds are not published). If you need C++-level performance for large graphs or a more comprehensive graph algorithm and file format toolkit, see the sibling project ogdf-py. For guidance on choosing between the two, see graph-layout vs. ogdf-py.

Layout Algorithms

Family Algorithm Description
Basic RandomLayout Random positions within canvas (baseline/starting point)
Bipartite BipartiteLayout Two parallel rows for bipartite graphs
Cola Layout Constraint-based layout with overlap avoidance (port of WebCola)
Force-Directed ForceAtlas2Layout Continuous layout with adaptive speeds (Gephi algorithm)
FruchtermanReingoldLayout Classic force-directed with cooling temperature
KamadaKawaiLayout Stress minimization based on graph-theoretic distances
SMACOFLayout Stress majorization (Guttman transform); converges more reliably than Kamada-Kawai
SpringLayout Simple Hooke's law spring forces
YifanHuLayout Multilevel force-directed for medium-large graphs
Hierarchical SugiyamaLayout Layered DAG drawing (Sugiyama method)
ReingoldTilfordLayout Classic tree layout
RadialTreeLayout Radial tree with root at center
Circular CircularLayout Nodes arranged on a circle
ShellLayout Concentric circles by degree or grouping
Spectral SpectralLayout Laplacian eigenvector embedding
Orthogonal KandinskyLayout Edges use only horizontal/vertical segments
GIOTTOLayout Orthogonal drawing for degree-4 planar graphs (opt-in bend-minimal via bend_optimal)
Planar SchnyderLayout Straight-line drawing via Schnyder's realizer on the (n-1) x (n-1) grid
FPPLayout de Fraysseix-Pach-Pollack shift method on the (2n-4) x (n-2) grid
TutteLayout Barycentric (spring) embedding with convex faces for 3-connected planar graphs
MixedModelLayout Visibility representation: bar-vertices with bendless port-attached edges
PlanarizationLayout Draws non-planar graphs; crossings become explicit dummy-vertex points

Installation

# Standard installation (includes Cython extensions for best performance)
pip install graph-layout

# With ILP compaction support (for optimal Kandinsky area minimization)
pip install graph-layout[ilp]

# Development installation
git clone https://github.com/shakfu/graph-layout.git
cd graph-layout
uv sync

Quick Start

Random Layout (Baseline)

Random layout places nodes at random positions. Useful as a baseline for comparing layout quality or as a starting point for iterative algorithms:

from graph_layout import RandomLayout

nodes = [{} for _ in range(10)]
links = [{'source': i, 'target': (i + 1) % 10} for i in range(10)]

layout = RandomLayout(
    nodes=nodes,
    links=links,
    size=(800, 600),
    margin=50,        # Optional padding from edges
    random_seed=42,   # For reproducible layouts
)
layout.run()

for i, node in enumerate(layout.nodes):
    print(f"Node {i}: ({node.x:.1f}, {node.y:.1f})")

Force-Directed Layout

from graph_layout import FruchtermanReingoldLayout

nodes = [{} for _ in range(6)]
links = [
    {'source': 0, 'target': 1},
    {'source': 1, 'target': 2},
    {'source': 2, 'target': 0},
    {'source': 3, 'target': 4},
    {'source': 4, 'target': 5},
    {'source': 2, 'target': 3},
]

layout = FruchtermanReingoldLayout(
    nodes=nodes,
    links=links,
    size=(800, 600),
    iterations=300,
)
layout.run()

for i, node in enumerate(layout.nodes):
    print(f"Node {i}: ({node.x:.1f}, {node.y:.1f})")

ForceAtlas2 Layout

ForceAtlas2 is designed for large network visualization with degree-weighted repulsion and adaptive speeds:

from graph_layout import ForceAtlas2Layout

layout = ForceAtlas2Layout(
    nodes=nodes,
    links=links,
    size=(800, 600),
    scaling=2.0,           # Repulsion strength
    gravity=1.0,           # Pull toward center
    linlog_mode=True,      # Tighter clusters
    strong_gravity_mode=False,  # Distance-based gravity
)
layout.run()

Yifan Hu Multilevel Layout

Yifan Hu is ideal for medium-large graphs (1K-100K nodes) using multilevel coarsening:

from graph_layout import YifanHuLayout

layout = YifanHuLayout(
    nodes=nodes,
    links=links,
    size=(800, 600),
    use_barnes_hut=True,       # O(n log n) approximation
    coarsening_threshold=0.75, # Stop coarsening when ratio > 0.75
    min_coarsest_size=10,      # Minimum nodes in coarsest graph
)
layout.run()

Cola (Constraint-Based) Layout

from graph_layout import ColaLayoutAdapter

nodes = [
    {'x': 0, 'y': 0, 'width': 50, 'height': 30},
    {'x': 100, 'y': 0, 'width': 50, 'height': 30},
    {'x': 200, 'y': 0, 'width': 50, 'height': 30},
]
links = [
    {'source': 0, 'target': 1},
    {'source': 1, 'target': 2},
]

layout = ColaLayoutAdapter(
    nodes=nodes,
    links=links,
    avoid_overlaps=True,
    link_distance=100,
)
layout.run()

Hierarchical Layout (Trees/DAGs)

from graph_layout import SugiyamaLayout

# Tree structure
nodes = [{} for _ in range(7)]
links = [
    {'source': 0, 'target': 1},
    {'source': 0, 'target': 2},
    {'source': 1, 'target': 3},
    {'source': 1, 'target': 4},
    {'source': 2, 'target': 5},
    {'source': 2, 'target': 6},
]

layout = SugiyamaLayout(
    nodes=nodes,
    links=links,
    size=(800, 600),
    layer_separation=80,
    node_separation=50,
)
layout.run()

Circular Layout

from graph_layout import CircularLayout, ShellLayout

nodes = [{} for _ in range(10)]
links = [{'source': i, 'target': (i + 1) % 10} for i in range(10)]

# Simple circular
layout = CircularLayout(nodes=nodes, links=links, size=(800, 600))
layout.run()

# Concentric shells by degree
layout = ShellLayout(nodes=nodes, links=links, size=(800, 600), auto_shells=2)
layout.run()

Spectral Layout

from graph_layout import SpectralLayout

layout = SpectralLayout(
    nodes=nodes,
    links=links,
    size=(800, 600),
    normalized=True,
)
layout.run()

Bipartite Layout

Bipartite layout places nodes in two parallel rows, ideal for user-item networks, author-paper relationships, or any bipartite graph:

from graph_layout import BipartiteLayout

# User-item bipartite graph
nodes = [{} for _ in range(7)]  # 3 users + 4 items
links = [
    {'source': 0, 'target': 3},  # user 0 -> item 3
    {'source': 0, 'target': 4},
    {'source': 1, 'target': 4},
    {'source': 1, 'target': 5},
    {'source': 2, 'target': 5},
    {'source': 2, 'target': 6},
]

layout = BipartiteLayout(
    nodes=nodes,
    links=links,
    size=(800, 600),
    top_set=[0, 1, 2],       # Users on top row
    bottom_set=[3, 4, 5, 6], # Items on bottom row
    minimize_crossings=True, # Reorder to reduce edge crossings
)
layout.run()

# Check if graph is bipartite
print(f"Is bipartite: {layout.is_bipartite}")

# Count edge crossings (O(m log m) using inversion counting)
from graph_layout.bipartite import count_crossings
edges = [(0, 3), (0, 4), (1, 4), (1, 5), (2, 5), (2, 6)]  # Same as links above
crossings = count_crossings(layout.top_nodes, layout.bottom_nodes, edges)
print(f"Edge crossings: {crossings}")

Algorithm insight: Edge crossings in a bipartite drawing equal the number of inversions when edges are sorted by their top-layer position. This allows O(m log m) counting via merge sort instead of O(m²) pairwise comparison—a 188x speedup for 10,000 edges.

Orthogonal Layout (Kandinsky)

Kandinsky layout produces diagrams where all edges use only horizontal and vertical segments. Ideal for UML diagrams, flowcharts, and ER diagrams. Uses a TSM (Topology-Shape-Metrics) approach:

from graph_layout import KandinskyLayout

layout = KandinskyLayout(
    nodes=nodes,
    links=links,
    size=(800, 600),
    node_width=60,
    node_height=40,
    node_separation=60,
    handle_crossings=True,   # Insert crossing vertices for non-planar graphs
    optimize_bends=True,     # Minimize bends using min-cost flow
    compact=True,            # Compact layout to reduce area
    compaction_method="auto", # "auto", "greedy", or "ilp" (ILP requires scipy)
)
layout.run()

# Access edge routing information
for edge in layout.orthogonal_edges:
    print(f"Edge {edge.source}->{edge.target}: {len(edge.bends)} bends")

# Check crossing information
print(f"Edge crossings detected: {layout.num_crossings}")
print(f"Total bends: {layout.total_bends}")

Port Constraints

Specify which side of a node edges should exit/enter from:

from graph_layout import KandinskyLayout
from graph_layout.orthogonal import Side

# Links with explicit port constraints
links = [
    {"source": 0, "target": 1, "source_side": Side.EAST, "target_side": Side.WEST},
    {"source": 1, "target": 2, "source_side": "south", "target_side": "north"},  # Strings work too
    {"source": 2, "target": 3},  # No constraint - uses heuristic
]

layout = KandinskyLayout(nodes=nodes, links=links, size=(800, 600))
layout.run()

# Verify constraints were applied
edge = layout.orthogonal_edges[0]
print(f"Edge exits from: {edge.source_port.side}")  # Side.EAST

GIOTTO Layout (Degree-4 Planar)

GIOTTO produces orthogonal drawings for planar graphs where every node has at most 4 edges (degree <= 4), based on Tamassia's algorithm. Edges are routed heuristically by default; pass bend_optimal=True (below) to draw from the bend-minimal representation:

from graph_layout import GIOTTOLayout

# 3x3 grid graph (degree-4 planar)
nodes = [{} for _ in range(9)]
links = [
    # Horizontal edges
    {"source": 0, "target": 1}, {"source": 1, "target": 2},
    {"source": 3, "target": 4}, {"source": 4, "target": 5},
    {"source": 6, "target": 7}, {"source": 7, "target": 8},
    # Vertical edges
    {"source": 0, "target": 3}, {"source": 1, "target": 4}, {"source": 2, "target": 5},
    {"source": 3, "target": 6}, {"source": 4, "target": 7}, {"source": 5, "target": 8},
]

layout = GIOTTOLayout(
    nodes=nodes,
    links=links,
    size=(800, 600),
    strict=True,  # Raise error if graph doesn't meet requirements
)
layout.run()

print(f"Valid input: {layout.is_valid_input}")
print(f"Total bends: {layout.total_bends}")

Use strict=False to fall back to Kandinsky-like behavior for graphs that don't meet GIOTTO's requirements:

# Graph with degree > 4 - would raise error with strict=True
layout = GIOTTOLayout(nodes=nodes, links=links, strict=False)
layout.run()  # Falls back to Kandinsky-like algorithm

Bend-optimal drawing (bend_optimal)

By default GIOTTO routes edges with a geometric heuristic. Pass bend_optimal=True to instead draw directly from the bend-minimal orthogonal representation (Topology-Shape-Metrics), which dramatically reduces bends — for example a 3x3 grid drops from 24 bends to 0, and K4 from 14 to 4:

layout = GIOTTOLayout(nodes=nodes, links=links, bend_optimal=True)
layout.run()

# Requesting it does not guarantee it is applied: the representation must be a
# realizable orthogonal shape. It works for biconnected, max-degree-4 planar
# graphs whose coordinate assignment is planar; other inputs silently fall back
# to the heuristic router. `used_bend_optimal` reports which path actually ran.
if not layout.used_bend_optimal:
    print("fell back to the heuristic router (not bend-minimal)")

It is opt-in (default off) while the compaction is completed; see docs/rectangularization-plan.md for the remaining work to make it the default.

Planar Straight-Line Layouts

Five algorithms draw a connected planar graph with straight-line edges and no crossings on a compact grid (and one, PlanarizationLayout, extends this to non-planar graphs). They share one substrate — a planar embedding from the LR-planarity test, triangulation to a maximal planar graph, and a canonical ordering — and each falls back to a deterministic circular placement for out-of-domain input, reporting which path ran via a used_* flag.

from graph_layout import SchnyderLayout, FPPLayout, TutteLayout

# A planar graph (square with a diagonal)
nodes = [{} for _ in range(4)]
links = [
    {"source": 0, "target": 1}, {"source": 1, "target": 2},
    {"source": 2, "target": 3}, {"source": 3, "target": 0},
    {"source": 0, "target": 2},
]

layout = SchnyderLayout(nodes=nodes, links=links, size=(800, 600))
layout.run()
print(f"Drew via Schnyder: {layout.used_schnyder}")
  • SchnyderLayout — realizer-based drawing; vertex-count barycentric coordinates on the (n-1) x (n-1) grid (Schnyder 1990).

  • FPPLayout — de Fraysseix-Pach-Pollack shift method (slope-±1 "tent" over the contour) on the (2n-4) x (n-2) grid.

  • TutteLayout — barycentric spring embedding; provably convex faces for 3-connected planar graphs (Tutte 1963).

  • MixedModelLayout — Tamassia-Tollis visibility representation: vertices are horizontal bars, edges bendless vertical segments at distinct ports (high angular resolution for high-degree vertices). Exposes vertex_bars and edge_routes.

  • PlanarizationLayout — draws non-planar graphs by replacing crossings with dummy vertices, then routing each edge as a polyline through its crossing points. Exposes crossings, crossing_count, and edge_routes.

from graph_layout import PlanarizationLayout

# K5 is non-planar
nodes = [{} for _ in range(5)]
links = [{"source": i, "target": j} for i in range(5) for j in range(i + 1, 5)]

layout = PlanarizationLayout(nodes=nodes, links=links, size=(800, 600))
layout.run()
print(f"Crossings: {layout.crossing_count}")  # 1 for K5

Visualization

Generate visualization images for all algorithms:

uv run python scripts/visualize.py

This creates images in ./build/ showing each algorithm's output.

Algorithm Comparison

Algorithm Best For Complexity Features
Random Baselines, starting points O(n) Uniform distribution, reproducible
Bipartite User-item, author-paper networks O(n + m) Auto-detection, crossing minimization
Cola Constrained layouts, overlap avoidance O(n^2) per iteration Constraints, groups, 3D
ForceAtlas2 Large networks, community detection O(n log n) with Barnes-Hut Adaptive speed, degree-weighted
Fruchterman-Reingold General graphs, aesthetics O(n^2) per iteration Temperature cooling
Kamada-Kawai Small-medium graphs, stress minimization O(n^2) per iteration Graph-theoretic distances
Spring Simple layouts, baselines O(n^2) per iteration Hooke's law
Yifan Hu Medium-large graphs (1K-100K nodes) O(n log n) with Barnes-Hut Multilevel coarsening, adaptive step
Sugiyama DAGs, hierarchies O(n^2) Layer-based, crossing minimization
Reingold-Tilford Trees O(n) Compact, balanced
Circular Ring structures, cycles O(n) Simple, predictable
Shell Grouped/stratified data O(n) Degree-based grouping
Spectral Clustering visualization O(n^3) eigendecomp Reveals structure
Kandinsky UML, flowcharts, ER diagrams O(m²) Orthogonal edges, bend minimization, compaction, port constraints
GIOTTO Degree-4 planar graphs O(m²) Bend-optimal orthogonal, validates planarity
Schnyder Compact planar straight-line O(n²) Realizer, crossing-free, (n-1)² grid
FPP Planar straight-line O(n²) Shift method, crossing-free, (2n-4)x(n-2) grid
Tutte 3-connected planar graphs O(n³) solve Convex faces, barycentric
Mixed-Model High-degree planar graphs O(n²) Visibility bars, bendless edges, high angular resolution
Planarization Non-planar graphs O((n+c)²) Crossings as explicit dummy vertices

Advanced Features

Cola: Overlap Avoidance & Constraints

from graph_layout import ColaLayoutAdapter
from graph_layout.cola.linklengths import SeparationConstraint

# Overlap avoidance
layout = ColaLayoutAdapter(
    nodes=nodes,
    links=links,
    avoid_overlaps=True,
)
layout.run()

# Hierarchical groups
groups = [{'leaves': [0, 1], 'padding': 10}, {'leaves': [2, 3], 'padding': 10}]
layout = ColaLayoutAdapter(
    nodes=nodes,
    links=links,
    groups=groups,
)
layout.run()

# Separation constraints
constraint = SeparationConstraint(axis='x', left=0, right=1, gap=50)
layout = ColaLayoutAdapter(
    nodes=nodes,
    links=links,
    constraints=[constraint],
)
layout.run()

Event System (Animation)

from graph_layout import FruchtermanReingoldLayout
from graph_layout.types import EventType

def on_tick(event):
    print(f"Alpha: {event['alpha']:.3f}")

layout = FruchtermanReingoldLayout(
    nodes=nodes,
    links=links,
    size=(800, 600),
    on_tick=on_tick,
)
layout.run()

# Or register events after construction
layout = FruchtermanReingoldLayout(nodes=nodes, links=links)
layout.on(EventType.tick, on_tick)
layout.run()

3D Layout

from graph_layout.cola import Layout3D, Node3D, Link3D

nodes = [Node3D(0, 0, 0), Node3D(1, 0, 0), Node3D(0, 1, 0)]
links = [Link3D(0, 1), Link3D(1, 2), Link3D(2, 0)]

layout = Layout3D(nodes, links, ideal_link_length=1.0)
layout.start(iterations=100)

Export Formats

All layout classes support exporting to SVG, DOT (Graphviz), and GraphML formats via methods:

from graph_layout import CircularLayout

# Create and run a layout
layout = CircularLayout(
    nodes=[{"index": i} for i in range(5)],
    links=[{"source": i, "target": (i + 1) % 5} for i in range(5)],
    size=(400, 400),
).run()

# Export to SVG (web/print)
svg = layout.to_svg(node_color="#4a90d9", show_labels=True)
with open("graph.svg", "w") as f:
    f.write(svg)

# Export to DOT (Graphviz)
dot = layout.to_dot(directed=False, include_positions=True)
with open("graph.dot", "w") as f:
    f.write(dot)

# Export to GraphML (interchange format)
graphml = layout.to_graphml(include_positions=True)
with open("graph.graphml", "w") as f:
    f.write(graphml)

Orthogonal layouts (KandinskyLayout, GIOTTOLayout) automatically use orthogonal-specific export with rectangular nodes and bend points:

from graph_layout import KandinskyLayout

layout = KandinskyLayout(nodes=nodes, links=links, size=(800, 600)).run()

# SVG with orthogonal edges (polylines with bends)
svg = layout.to_svg()  # Automatically uses orthogonal rendering

# GraphML with bend point data
graphml = layout.to_graphml()  # Includes bend coordinates and port sides

# DOT with splines=ortho
dot = layout.to_dot()  # Uses box nodes and ortho splines

Standalone functions are also available:

from graph_layout import to_svg, to_dot, to_graphml

svg = to_svg(layout, node_color="#ff0000")
dot = to_dot(layout, directed=True)
graphml = to_graphml(layout)

Configuration via Properties

All layout algorithms support configuration via constructor parameters and properties:

from graph_layout import FruchtermanReingoldLayout

# Configure via constructor
layout = FruchtermanReingoldLayout(
    nodes=nodes,
    links=links,
    size=(800, 600),
    iterations=300,
    temperature=100.0,
    cooling_factor=0.95,
)

# Or modify properties after construction
layout = FruchtermanReingoldLayout()
layout.nodes = nodes
layout.links = links
layout.size = (800, 600)
layout.temperature = 50.0
layout.run()

# Access results via properties
for node in layout.nodes:
    print(f"({node.x}, {node.y})")

Module Structure

graph_layout/
    __init__.py              # Top-level exports
    base.py                  # Base classes (BaseLayout, IterativeLayout, StaticLayout)
    types.py                 # Common types (Node, Link, Group, EventType)
    basic/                   # Basic utility layouts
        random.py            # RandomLayout
    bipartite/               # Bipartite layouts
        bipartite.py         # BipartiteLayout
    cola/                    # Constraint-based layout (WebCola port)
        layout.py            # Main 2D layout
        layout3d.py          # 3D layout
        adapter.py           # ColaLayoutAdapter (Pythonic API)
        descent.py           # Gradient descent optimizer
        vpsc.py              # VPSC constraint solver
        ...
    force/                   # Force-directed layouts
        force_atlas2.py
        fruchterman_reingold.py
        kamada_kawai.py
        spring.py
        yifan_hu.py
    hierarchical/            # Tree and DAG layouts
        sugiyama.py
        reingold_tilford.py
        radial_tree.py
    circular/                # Circular layouts
        circular.py
        shell.py
    spectral/                # Spectral methods
        spectral.py
    orthogonal/              # Orthogonal layouts
        kandinsky.py         # Kandinsky layout (arbitrary degree)
        giotto.py            # GIOTTO layout (degree-4 planar, bend-optimal)
        types.py             # NodeBox, Port, OrthogonalEdge, Side
        planarization.py     # Edge crossing detection and vertex insertion
        orthogonalization.py # Bend minimization via min-cost flow
        compaction.py        # Greedy layout area minimization
        compaction_ilp.py    # ILP-based optimal area minimization
    export/                  # Export to various formats
        svg.py               # to_svg, to_svg_orthogonal
        dot.py               # to_dot, to_dot_orthogonal (Graphviz)
        graphml.py           # to_graphml, to_graphml_orthogonal

Performance

Cython Speedups

This project includes a Cython _speedups.pyx module which provides significant speedups over pure Python:

Algorithm Cython Speedup Notes
Fruchterman-Reingold 50-60x faster O(n²) force calculations
ForceAtlas2 15-20x faster Degree-weighted forces
Yifan Hu 5-7x faster Multilevel overhead in Python
Shortest paths (Dijkstra) 5x faster Priority queue operations

Benchmark Results

Benchmarks on random scale-free graphs (Barabási-Albert model), 50 iterations:

Algorithm 500 nodes 1,000 nodes 5,000 nodes
Random 0.001s 0.002s 0.015s
Circular 0.001s 0.002s 0.015s
Yifan Hu 0.007s 0.014s 0.077s
ForceAtlas2 0.031s 0.066s 0.402s
FR + Barnes-Hut 0.082s 0.188s 1.277s
Spectral 0.036s 0.102s 6.428s
Fruchterman-Reingold 0.059s -- --
Kamada-Kawai 5.5s -- --
Kandinsky 0.78s 3.6s --

Note: FR and KK use O(n²) and are too slow for graphs >500 nodes without Barnes-Hut. Kandinsky uses O(m²) for edge crossing detection.

Algorithmic Optimizations

Beyond Cython speedups, several algorithms use asymptotically better approaches:

Function Naive Optimized Technique
count_crossings() O(m²) O(m log m) Merge sort inversion counting
Force repulsion O(n²) O(n log n) Barnes-Hut quadtree
Yifan Hu layout O(n²) O(n log n) Multilevel coarsening + Barnes-Hut

Recommendations by graph size:

  • < 500 nodes: Any algorithm works well

  • 500-2,000 nodes: Use Yifan Hu, ForceAtlas2, or FR+Barnes-Hut

  • > 2,000 nodes: Use Yifan Hu (fastest) or ForceAtlas2 (best for communities)

Barnes-Hut Approximation

ForceAtlas2 and Yifan Hu use Barnes-Hut O(n log n) approximation by default for graphs >50 nodes. For Fruchterman-Reingold, enable it manually:

layout = FruchtermanReingoldLayout(
    nodes=nodes,
    links=links,
    use_barnes_hut=True,
    barnes_hut_theta=0.5,  # 0=exact, higher=faster but less accurate
)

Running Benchmarks

# Generate benchmark graphs
uv run python scripts/generate_benchmark_graphs.py

# Run benchmarks
uv run python scripts/benchmark_layouts.py --graphs "large_*"

Development

make test          # Run tests
make typecheck     # Type checking
make lint          # Lint code
make qa            # Run all qualtiy checks

Related project: ogdf-py

ogdf-py is a sibling project: Python bindings (via nanobind) to the C++ Open Graph Drawing Framework (OGDF). The two overlap heavily -- graph-layout reimplements in pure Python many algorithms OGDF implements in C++ -- and graph-layout's own test suite uses ogdf-py as an independent correctness oracle (tests/test_ogdf_oracle.py) and as a speed baseline (tests/benchmarks/compare_ogdf.py).

Prefer ogdf-py when:

  • Scale and speed matter. OGDF is compiled C++. On the identical stress-majorization algorithm it runs ~15-20x faster than graph-layout, and the gap grows with size: at 5000 nodes graph-layout's SMACOF takes ~4.5 minutes versus OGDF's ~16 seconds (see tests/benchmarks/README.md). For graphs beyond ~1000 nodes, or performance-critical pipelines, reach for ogdf-py.

  • You need more than layout. OGDF ships a large, mature toolkit graph-layout does not: maximum and minimum-cost flow, matching, Steiner trees, triconnectivity / SPQR-trees, node colouring, and read/write for the GML, GraphML, DOT, GEXF, GDF, and TLP formats.

  • You want a battle-tested reference. OGDF is a long-standing framework from the graph-drawing research community.

Prefer graph-layout when:

  • Zero native dependency. Pure Python (plus optional Cython); pip install graph-layout needs no C++ toolchain and works on every platform and Python version -- including those where ogdf-py ships no prebuilt wheel (Windows, Python 3.9, 3.14+).

  • You want readable, hackable implementations. Every algorithm is Python you can read, modify, and extend -- useful for learning and experimentation.

  • You need a layout ogdf-py doesn't expose. Constraint-based layout (Cola: overlap avoidance, separation constraints, groups), ForceAtlas2, and the FPP and mixed-model planar straight-line layouts are graph-layout-only. (Both libraries also do force-directed, hierarchical, orthogonal, and Schnyder/Tutte planar drawing.)

  • Throughput on a budget. Not every graph-layout algorithm is slower: its multilevel YifanHu is faster than OGDF's flagship FMMM at every size tested, trading ~20% layout quality for speed.

In short: ogdf-py for C++ performance and algorithmic breadth; graph-layout for a dependency-free, readable, easily-extended pure-Python library with a handful of layout families of its own.

Another earlier graph-drawing sibling project, hola-graph, is a pybind11 wrapper for the adaptagrams HOLA: Human-like Orthogonal Network Layout algorithm by Steve Kieffer, Tim Dwyer, Kim Marriott and Michael Wybrow.

Credits

  • Cola: Port of WebCola by Tim Dwyer (see also libcola-releated papers in the adaptagrams project.

  • ForceAtlas2: Based on "ForceAtlas2, a Continuous Graph Layout Algorithm for Handy Network Visualization" by Jacomy et al. (2014)

  • Fruchterman-Reingold: Based on "Graph Drawing by Force-directed Placement" (1991)

  • Kamada-Kawai: Based on "An Algorithm for Drawing General Undirected Graphs" (1989)

  • Yifan Hu: Based on "Efficient and High Quality Force-Directed Graph Drawing" (2005)

  • Sugiyama: Based on "Methods for Visual Understanding of Hierarchical System Structures" (1981)

  • Reingold-Tilford: Based on "Tidier Drawings of Trees" (1981)

  • Kandinsky: Based on the Kandinsky model and Tamassia's bend minimization algorithm (1987)

  • GIOTTO: Based on Tamassia's "On Embedding a Graph in the Grid with the Minimum Number of Bends" (1987)

License

MIT

Download files

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

Source Distribution

graph_layout-0.5.0.tar.gz (2.2 MB view details)

Uploaded Source

Built Distributions

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

graph_layout-0.5.0-cp314-cp314-win_amd64.whl (466.3 kB view details)

Uploaded CPython 3.14Windows x86-64

graph_layout-0.5.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl (501.2 kB view details)

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

graph_layout-0.5.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl (490.3 kB view details)

Uploaded CPython 3.14manylinux: glibc 2.17+ ARM64manylinux: glibc 2.28+ ARM64

graph_layout-0.5.0-cp314-cp314-macosx_11_0_arm64.whl (441.4 kB view details)

Uploaded CPython 3.14macOS 11.0+ ARM64

graph_layout-0.5.0-cp314-cp314-macosx_10_15_x86_64.whl (456.4 kB view details)

Uploaded CPython 3.14macOS 10.15+ x86-64

graph_layout-0.5.0-cp313-cp313-win_amd64.whl (461.6 kB view details)

Uploaded CPython 3.13Windows x86-64

graph_layout-0.5.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl (500.1 kB view details)

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

graph_layout-0.5.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl (486.9 kB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ ARM64manylinux: glibc 2.28+ ARM64

graph_layout-0.5.0-cp313-cp313-macosx_11_0_arm64.whl (440.3 kB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

graph_layout-0.5.0-cp313-cp313-macosx_10_13_x86_64.whl (455.7 kB view details)

Uploaded CPython 3.13macOS 10.13+ x86-64

graph_layout-0.5.0-cp312-cp312-win_amd64.whl (461.3 kB view details)

Uploaded CPython 3.12Windows x86-64

graph_layout-0.5.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl (497.2 kB view details)

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

graph_layout-0.5.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl (486.6 kB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ ARM64manylinux: glibc 2.28+ ARM64

graph_layout-0.5.0-cp312-cp312-macosx_11_0_arm64.whl (439.0 kB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

graph_layout-0.5.0-cp312-cp312-macosx_10_13_x86_64.whl (453.4 kB view details)

Uploaded CPython 3.12macOS 10.13+ x86-64

graph_layout-0.5.0-cp311-cp311-win_amd64.whl (462.4 kB view details)

Uploaded CPython 3.11Windows x86-64

graph_layout-0.5.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl (501.6 kB view details)

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

graph_layout-0.5.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl (493.5 kB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ ARM64manylinux: glibc 2.28+ ARM64

graph_layout-0.5.0-cp311-cp311-macosx_11_0_arm64.whl (443.2 kB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

graph_layout-0.5.0-cp311-cp311-macosx_10_9_x86_64.whl (456.7 kB view details)

Uploaded CPython 3.11macOS 10.9+ x86-64

graph_layout-0.5.0-cp310-cp310-win_amd64.whl (463.2 kB view details)

Uploaded CPython 3.10Windows x86-64

graph_layout-0.5.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl (501.4 kB view details)

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

graph_layout-0.5.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl (494.8 kB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ ARM64manylinux: glibc 2.28+ ARM64

graph_layout-0.5.0-cp310-cp310-macosx_11_0_arm64.whl (443.4 kB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

graph_layout-0.5.0-cp310-cp310-macosx_10_9_x86_64.whl (457.1 kB view details)

Uploaded CPython 3.10macOS 10.9+ x86-64

graph_layout-0.5.0-cp39-cp39-win_amd64.whl (463.6 kB view details)

Uploaded CPython 3.9Windows x86-64

graph_layout-0.5.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl (502.3 kB view details)

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

graph_layout-0.5.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl (494.7 kB view details)

Uploaded CPython 3.9manylinux: glibc 2.17+ ARM64manylinux: glibc 2.28+ ARM64

graph_layout-0.5.0-cp39-cp39-macosx_11_0_arm64.whl (443.6 kB view details)

Uploaded CPython 3.9macOS 11.0+ ARM64

graph_layout-0.5.0-cp39-cp39-macosx_10_9_x86_64.whl (457.4 kB view details)

Uploaded CPython 3.9macOS 10.9+ x86-64

File details

Details for the file graph_layout-0.5.0.tar.gz.

File metadata

  • Download URL: graph_layout-0.5.0.tar.gz
  • Upload date:
  • Size: 2.2 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.2

File hashes

Hashes for graph_layout-0.5.0.tar.gz
Algorithm Hash digest
SHA256 56b5e9f4646fc939993cca2b15cb2ca7a8e133bb7f7733ca49d86e8e48c85bd7
MD5 2940ec52e91245c4fdea90a6f467141a
BLAKE2b-256 f0f173ea9a89738c0f716cd0017687a4aa32f219777536c41a9ecf3a931b5472

See more details on using hashes here.

File details

Details for the file graph_layout-0.5.0-cp314-cp314-win_amd64.whl.

File metadata

File hashes

Hashes for graph_layout-0.5.0-cp314-cp314-win_amd64.whl
Algorithm Hash digest
SHA256 d6edacb7ab26ccc5deeb4559d5bce28bd35058f470b7c1c5b55c4617bdf3a29b
MD5 b4e50f06260b77c28331cbe640117213
BLAKE2b-256 abe94376e27696c71a9aaefcefb0728bd60726874841547fd44b39ba92cd11a1

See more details on using hashes here.

File details

Details for the file graph_layout-0.5.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for graph_layout-0.5.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 a43dcde385769076f869e4724c34b0d3e38f535edf77a945b7aea946f2e1343e
MD5 dee9c97a48e7c90a0e85c968df573d03
BLAKE2b-256 454ab3589b998586693029b2e050820199695661203b5eefc36b2036f5733dc4

See more details on using hashes here.

File details

Details for the file graph_layout-0.5.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for graph_layout-0.5.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 88351cc9f77eec463b5afb1ca9dee0e6010d55c22db575c8c014f4865e8c8a6c
MD5 8405e6c314ba09bb97cdb08a292e02e1
BLAKE2b-256 e1192490d40e88ef3dba1b24f65f71745fa39c1bedceb4bf5978ed5f6331836f

See more details on using hashes here.

File details

Details for the file graph_layout-0.5.0-cp314-cp314-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for graph_layout-0.5.0-cp314-cp314-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 66fbb612e29054f252f5c2c4dc4b01945c6296f0819c723b281df7a210267d9b
MD5 ead230fba0bd24890cdbac1ae14e486b
BLAKE2b-256 59c3bbcbdc18f019a037fe340e1d2bfe5dbc7e8d4c989ba92aabb5a543de9655

See more details on using hashes here.

File details

Details for the file graph_layout-0.5.0-cp314-cp314-macosx_10_15_x86_64.whl.

File metadata

File hashes

Hashes for graph_layout-0.5.0-cp314-cp314-macosx_10_15_x86_64.whl
Algorithm Hash digest
SHA256 866e5c77f68a9fe9a6fa14c45f1fe2d9bc75d814ac14dd01655bd48aa94ebdb2
MD5 0749a88cd543b1da46912d6faa2004bc
BLAKE2b-256 1740f42e601dd048f881721e33878eda2a0f949bf90776b30033e3904e9880e5

See more details on using hashes here.

File details

Details for the file graph_layout-0.5.0-cp313-cp313-win_amd64.whl.

File metadata

File hashes

Hashes for graph_layout-0.5.0-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 84a4e2814527e07cb551edb496b62e65dfd3a25cd138e51a907e005f10fc0d11
MD5 673be65a8bb7b547579b609034a9fd5a
BLAKE2b-256 5b77f97c059edcddb6a5f0a42abfa325089852d9c9462916c358bf31d91f68bc

See more details on using hashes here.

File details

Details for the file graph_layout-0.5.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for graph_layout-0.5.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 8af468522b72774a069da863809d5cd1866e394f8c5cac9b81de2d710334baaa
MD5 9d7af25a71da701065b5ac8ffc95dee0
BLAKE2b-256 f7ff121c5eec3890b0c338d2a558b2cef5f5f677679e7efc4c09b2011cc7bf8c

See more details on using hashes here.

File details

Details for the file graph_layout-0.5.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for graph_layout-0.5.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 9681860c4a136739b6a3a1b1dfa97c122a74c32b65e6f6c4a7400fcd2aceff1d
MD5 54eedf21e8a8632ed595e9f689d6fd0c
BLAKE2b-256 b4c5641f46d6400c443b9779051ab6d9845e8b728aa1e165e133752eb60d8eec

See more details on using hashes here.

File details

Details for the file graph_layout-0.5.0-cp313-cp313-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for graph_layout-0.5.0-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 5393896aecb1a45d5443dc7d7b92e120df02bf61ab6dd59db8c64af92040fb19
MD5 e405f269f20baca03d06e18308a3fa8b
BLAKE2b-256 9e8f4a1afb1ccb0977ffedf3260d91e5dd520125295cd6af406f3e6aaf7f2c2c

See more details on using hashes here.

File details

Details for the file graph_layout-0.5.0-cp313-cp313-macosx_10_13_x86_64.whl.

File metadata

File hashes

Hashes for graph_layout-0.5.0-cp313-cp313-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 b00b967726e033c79ff57077989d3c1ab2e8c1d0702cd5cbffc5eb0326c9b463
MD5 1d1d93ce2a25d270e78d0ac29436ba2d
BLAKE2b-256 9452d25ae2174399e9204f44eef9d49c28bb9f18a494eb1aac346d236da67c11

See more details on using hashes here.

File details

Details for the file graph_layout-0.5.0-cp312-cp312-win_amd64.whl.

File metadata

File hashes

Hashes for graph_layout-0.5.0-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 8f699496a497f8ed94ae1d992ca510f6b42fcc6fa75e8606ff7bbe22fec8ae8e
MD5 f56789979bd898c70a8b277381bed7d4
BLAKE2b-256 ecb113ae529a1e63e20e2bdb0d7914abf24a9c9bb394fd9e4c979ab7c754df10

See more details on using hashes here.

File details

Details for the file graph_layout-0.5.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for graph_layout-0.5.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 8b65d6d4993db46ab9c12fcf79002a352fdda5a6b32a5b52404fdedbeffaeed1
MD5 bf6fd8eb9f30dfe85eeff23f5c9d2a74
BLAKE2b-256 1ae667bedc21f724b0d34f3ed2467974666bb1fcb810af3e7ce9e524208193fc

See more details on using hashes here.

File details

Details for the file graph_layout-0.5.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for graph_layout-0.5.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 81f0c08f97e00ab6235908703d9fae14fcc0a268f95e1f5137155a40658d2c99
MD5 239318bb43afa0e6c30151438584a5d4
BLAKE2b-256 c76899289a39f561223217cd9a5f81dff0b94ef4593e56b2d29ef0636a7c586e

See more details on using hashes here.

File details

Details for the file graph_layout-0.5.0-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for graph_layout-0.5.0-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 6597c99fb3df43bcd90b48908d784c2fd05511373259fd0aa552419c898e0d5b
MD5 cc503d8e5cd76a271be92c9961699bba
BLAKE2b-256 97adf9902ffa4aa9fce344604832214a708aeb4c7cdfbd7adc85b05548b7385b

See more details on using hashes here.

File details

Details for the file graph_layout-0.5.0-cp312-cp312-macosx_10_13_x86_64.whl.

File metadata

File hashes

Hashes for graph_layout-0.5.0-cp312-cp312-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 d9dc5f0a94354a9a98d6393e7c6d813083e2b341374bf4dfa1949c92dc91862d
MD5 adef4693fe4b898765ca0e498f123c1b
BLAKE2b-256 41bbd7f09fcfdd60d49b1dab8926b546c5a58ddfdcc0e4731fb615bdf9f87a5c

See more details on using hashes here.

File details

Details for the file graph_layout-0.5.0-cp311-cp311-win_amd64.whl.

File metadata

File hashes

Hashes for graph_layout-0.5.0-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 6b7574db3edecd6ac51e1069aa1b94a3145dc2fc23e89371bf6cc39319b5a85f
MD5 e84b15c1afb3a70d40006016cedb6340
BLAKE2b-256 74901f50fd73248a345a611ef70eb19d4401216b2fb1af6c9b3bdc6915dd772c

See more details on using hashes here.

File details

Details for the file graph_layout-0.5.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for graph_layout-0.5.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 61c48beccba443880688aadcd4deae74b62fe58e4840c7101f7fa91e3080d60e
MD5 d9c141926193ac7eb29b08baf3790173
BLAKE2b-256 9700b6b42565bd358fae504f948537bed754bd981de41e94f945e6c789fdf6ca

See more details on using hashes here.

File details

Details for the file graph_layout-0.5.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for graph_layout-0.5.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 3a789be7c39be0c65294df3b33d268df27099ca9919dce9f4650053a38b3a401
MD5 eae5558e237f914024e24ce68609c2b4
BLAKE2b-256 5dc69bc1207a2d1cf8fe53e6ec92cd7ad09f25d11a6fa3d5cce02a2fd3a9063d

See more details on using hashes here.

File details

Details for the file graph_layout-0.5.0-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for graph_layout-0.5.0-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 7dbe4a54ae227301866d1075f6946b1adcdbce1c7ce354bbb5c81df3b2ab759b
MD5 d3345ce4ac747448ebdbc8e95733bf4b
BLAKE2b-256 a683acaa3728bb8fb0fa0701125fe4302fc058ba768699e3393f95c69057dd75

See more details on using hashes here.

File details

Details for the file graph_layout-0.5.0-cp311-cp311-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for graph_layout-0.5.0-cp311-cp311-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 5562668bbbdafeff70ffbc85400e2e3c1e607732de9a83d882a7288967e0026f
MD5 8acab8d2d9acc274e5c337a2e61af903
BLAKE2b-256 4950fc5b96516301d220705d52b07b32d1fcbda1f089185ce8e2f6256d4c418e

See more details on using hashes here.

File details

Details for the file graph_layout-0.5.0-cp310-cp310-win_amd64.whl.

File metadata

File hashes

Hashes for graph_layout-0.5.0-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 d13e1336c92ed080a42f0ac20fb4acda78ca41c822f5f126fbdc7fcce74b3c46
MD5 0073dcae718fd40cca1eb96ed0152db9
BLAKE2b-256 cd309f9bc6c429f9d20749aa9e599db7e26c64d7fd193d506474b8f834c74c7b

See more details on using hashes here.

File details

Details for the file graph_layout-0.5.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for graph_layout-0.5.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 a040421087b558b1121a06ce570b6ef93c036869239233a85826c11f9c0ed139
MD5 7dd49368e864b57427c452794247feaf
BLAKE2b-256 32f6c7af7922e162824ef36f31ce78ad24c91942bde91a408b157333a7e70c8b

See more details on using hashes here.

File details

Details for the file graph_layout-0.5.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for graph_layout-0.5.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 6af39f2c0232d461804835bca28c182ac1a4c5c61a4f40517eace87e1da5bd02
MD5 1d808fa67b8f48582f7d70df218db6d1
BLAKE2b-256 2c0e997f700e8c1271b4ec530da9f7d7a72e4f0d1332a1e6173a2b9c021f6728

See more details on using hashes here.

File details

Details for the file graph_layout-0.5.0-cp310-cp310-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for graph_layout-0.5.0-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 d52e537bda6b06756c4956b0a794ae1ec96db992ebd578452bad14d3e2adc7e0
MD5 79fb1ae2f35f788ce57cf36cb6e21658
BLAKE2b-256 9d875904015c7acd72ef79ef4dc58e050db679a00abb0f6222a8d8f728f55832

See more details on using hashes here.

File details

Details for the file graph_layout-0.5.0-cp310-cp310-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for graph_layout-0.5.0-cp310-cp310-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 a3c0b1348206eb57a1753374da0fac8dbf8c732a36da71e2cc7fd27ae8f8eef6
MD5 b160167039a74b7a7dd771abe2a0a20b
BLAKE2b-256 413f87833eda66b21f088193659a7de2b9fc66c80a5944c478af0501a59e9afc

See more details on using hashes here.

File details

Details for the file graph_layout-0.5.0-cp39-cp39-win_amd64.whl.

File metadata

  • Download URL: graph_layout-0.5.0-cp39-cp39-win_amd64.whl
  • Upload date:
  • Size: 463.6 kB
  • Tags: CPython 3.9, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.2

File hashes

Hashes for graph_layout-0.5.0-cp39-cp39-win_amd64.whl
Algorithm Hash digest
SHA256 83cf13595c0052f534725e1fcb6120d7fdc0cd3613d57f5aafaec8ff43579f59
MD5 2a9675123d891ae50fed1094719ae278
BLAKE2b-256 9498809fa32fccdd86df5aa7ab09955408a5985f69a2858b4477e31a463d1564

See more details on using hashes here.

File details

Details for the file graph_layout-0.5.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for graph_layout-0.5.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 7ad7670f1bc811fa7a8b07d26c06ed2f72d0f28e6e06e84063dbbee621b442f9
MD5 5f3d84636ed0cad150c7765b3a17cd1c
BLAKE2b-256 dda3f38d14d9fb2cf3f274d8297014a0173d9d26e3403f4651d46b9e48bad5fa

See more details on using hashes here.

File details

Details for the file graph_layout-0.5.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for graph_layout-0.5.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 d2a029fbf9529e95439d6ede67f0fb5d304c8e3380f98f558f32c0208dd5e687
MD5 708423b0eda02097e9876847a8d9638f
BLAKE2b-256 99890fbfd2215ac513a0a0f5f42ff9e3b47664aab8b45dd48db0359695ee0ea3

See more details on using hashes here.

File details

Details for the file graph_layout-0.5.0-cp39-cp39-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for graph_layout-0.5.0-cp39-cp39-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 21d6c54203a81dea50c03856ef21c694fb75be28255d28b0d17b67807a265ef7
MD5 b883eb05b84595d6d71d3912be300e98
BLAKE2b-256 5304049c3d7806f5f74b5a20f80de7b017b32bb4faa7a969e75baf1e4ab53b22

See more details on using hashes here.

File details

Details for the file graph_layout-0.5.0-cp39-cp39-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for graph_layout-0.5.0-cp39-cp39-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 6e6c8c976269abe6e890af1770d2735ead80a3578d2aa6b8a261bb5ef2bd3bc6
MD5 76b90d20ff9c1cb97c7894bb8568004e
BLAKE2b-256 0172a41e9ff317759c51453b2ad4b652b5ff47dbedb875d20eab07f23282fbb5

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.5.0 This release

31 files

0.4.1

31 files

0.4.0

31 files

0.3.2

31 files

0.3.0

31 files

0.2.0

31 files

0.1.8

31 files

0.1.7

31 files

0.1.6

31 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page