Skip to main content

A collection of graph layout algorithms in Python

Project description

graph-layout - Python Graph Layout Library

A collection of graph layout algorithms in Python.

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
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)

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.

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

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

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

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

graph_layout-0.3.0.tar.gz (2.1 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.3.0-cp314-cp314-win_amd64.whl (403.0 kB view details)

Uploaded CPython 3.14Windows x86-64

graph_layout-0.3.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (435.3 kB view details)

Uploaded CPython 3.14manylinux: glibc 2.17+ x86-64

graph_layout-0.3.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl (418.0 kB view details)

Uploaded CPython 3.14manylinux: glibc 2.17+ ARM64

graph_layout-0.3.0-cp314-cp314-macosx_11_0_arm64.whl (377.1 kB view details)

Uploaded CPython 3.14macOS 11.0+ ARM64

graph_layout-0.3.0-cp314-cp314-macosx_10_15_x86_64.whl (391.4 kB view details)

Uploaded CPython 3.14macOS 10.15+ x86-64

graph_layout-0.3.0-cp313-cp313-win_amd64.whl (398.3 kB view details)

Uploaded CPython 3.13Windows x86-64

graph_layout-0.3.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (434.0 kB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ x86-64

graph_layout-0.3.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl (415.8 kB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ ARM64

graph_layout-0.3.0-cp313-cp313-macosx_11_0_arm64.whl (375.9 kB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

graph_layout-0.3.0-cp313-cp313-macosx_10_13_x86_64.whl (390.7 kB view details)

Uploaded CPython 3.13macOS 10.13+ x86-64

graph_layout-0.3.0-cp312-cp312-win_amd64.whl (398.2 kB view details)

Uploaded CPython 3.12Windows x86-64

graph_layout-0.3.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (433.7 kB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ x86-64

graph_layout-0.3.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl (416.4 kB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ ARM64

graph_layout-0.3.0-cp312-cp312-macosx_11_0_arm64.whl (377.0 kB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

graph_layout-0.3.0-cp312-cp312-macosx_10_13_x86_64.whl (391.5 kB view details)

Uploaded CPython 3.12macOS 10.13+ x86-64

graph_layout-0.3.0-cp311-cp311-win_amd64.whl (398.7 kB view details)

Uploaded CPython 3.11Windows x86-64

graph_layout-0.3.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (433.3 kB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ x86-64

graph_layout-0.3.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl (422.2 kB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ ARM64

graph_layout-0.3.0-cp311-cp311-macosx_11_0_arm64.whl (377.6 kB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

graph_layout-0.3.0-cp311-cp311-macosx_10_9_x86_64.whl (391.3 kB view details)

Uploaded CPython 3.11macOS 10.9+ x86-64

graph_layout-0.3.0-cp310-cp310-win_amd64.whl (398.5 kB view details)

Uploaded CPython 3.10Windows x86-64

graph_layout-0.3.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (432.7 kB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ x86-64

graph_layout-0.3.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl (422.8 kB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ ARM64

graph_layout-0.3.0-cp310-cp310-macosx_11_0_arm64.whl (378.1 kB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

graph_layout-0.3.0-cp310-cp310-macosx_10_9_x86_64.whl (391.6 kB view details)

Uploaded CPython 3.10macOS 10.9+ x86-64

graph_layout-0.3.0-cp39-cp39-win_amd64.whl (398.9 kB view details)

Uploaded CPython 3.9Windows x86-64

graph_layout-0.3.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (433.5 kB view details)

Uploaded CPython 3.9manylinux: glibc 2.17+ x86-64

graph_layout-0.3.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl (422.5 kB view details)

Uploaded CPython 3.9manylinux: glibc 2.17+ ARM64

graph_layout-0.3.0-cp39-cp39-macosx_11_0_arm64.whl (378.6 kB view details)

Uploaded CPython 3.9macOS 11.0+ ARM64

graph_layout-0.3.0-cp39-cp39-macosx_10_9_x86_64.whl (391.8 kB view details)

Uploaded CPython 3.9macOS 10.9+ x86-64

File details

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

File metadata

  • Download URL: graph_layout-0.3.0.tar.gz
  • Upload date:
  • Size: 2.1 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.3.0.tar.gz
Algorithm Hash digest
SHA256 3e3422be888a18b531c2f15bdbe185ec6cffde5106727f4e29e776e70e12a26b
MD5 b46a58bca1436e44fd9f22802bd696a7
BLAKE2b-256 7aaa8b9051e038825c3dccc794eaef2cb255544b9fd14b45b2577bbe2b10c428

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.3.0-cp314-cp314-win_amd64.whl
Algorithm Hash digest
SHA256 d848d5ff92d140cf9952a00f217f99f55a5eb708b964b02e9630fbe310e20039
MD5 df74a0dc14a9f47fedc0d79c5a92313a
BLAKE2b-256 d276b460ebd7d3c0298d20d35fe0bf7f05037ee4c20ececb5f8899c90831faed

See more details on using hashes here.

File details

Details for the file graph_layout-0.3.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl.

File metadata

File hashes

Hashes for graph_layout-0.3.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 c8a58cf1cceeb99b61aa47e6923c30c0120385aff0f055a6a52a2f7b88b733c3
MD5 8d399f6d3eb17845395abb4a0942a606
BLAKE2b-256 bdd5373de80fb6f2b2fea65949402c8be1297ba1203147085c92565cb2f318a2

See more details on using hashes here.

File details

Details for the file graph_layout-0.3.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl.

File metadata

File hashes

Hashes for graph_layout-0.3.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
Algorithm Hash digest
SHA256 92b705285f63871f5ad2b85d27a47b8625bf91f3e11ca6ec44b00ac88c3af6cb
MD5 0f974561363638550907964bb00b6d5a
BLAKE2b-256 b3fe5d9e94b84bdb4f7fe25cd5f1f2247d1a4e0823611f35d91b50ecb91ce0f2

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.3.0-cp314-cp314-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 85984d40081bdc9d1d5edba37805e2c373871f2a19aaa2d3d2c31c5c3f98a60d
MD5 2eee2d1d781d8fdc0b2fb1ad2ce0aa32
BLAKE2b-256 e97304159b605a7851d4ab194a8e901519b6a7d5eb232a03a8805a528c1a0628

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.3.0-cp314-cp314-macosx_10_15_x86_64.whl
Algorithm Hash digest
SHA256 57b2b1dac8ee1f6ce46d2e02c1a59cf113da54d5bf5b1ad04e92fd04456caf0d
MD5 bd864c6ac784512343e72aea3e527631
BLAKE2b-256 d3f466338eeddb843679259b475cc059b7ff8e519dab54b3c95d03b20f6b7af2

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.3.0-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 59fd28298a9d38b8a07d7fce61d71fbbb518719a361fc11981a7c35ceb29fd95
MD5 c018d3ff928b6ec08615014cbe423665
BLAKE2b-256 e55c4772bae529a57f37c46bf91e502fd7c77499925a00fc6f3b2961aa7d21c0

See more details on using hashes here.

File details

Details for the file graph_layout-0.3.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl.

File metadata

File hashes

Hashes for graph_layout-0.3.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 a992e5f89c3b123097604b8990e8ece5757b412e8d29dc80a1a0f4e97b33de14
MD5 883187a8e4c03c093c6369f884bdf941
BLAKE2b-256 ab021274e928529edc392ad85d1bbde5d953ffc050e4efc3f32895af12236517

See more details on using hashes here.

File details

Details for the file graph_layout-0.3.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl.

File metadata

File hashes

Hashes for graph_layout-0.3.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
Algorithm Hash digest
SHA256 57462d178ea745152d23c9cb0fb1616b37ecf27002c5cb462290718d087dc9b6
MD5 f79fcf320691bbd0607ad6b07838ae94
BLAKE2b-256 60103bb3cd4efe2b5ca447e3d03940f3e7dacfba5c28e5575a4bfb386ff9a66e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.3.0-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 935c421383b0e0a5b372d2ccdf4ba56885ab4ee92996ea4d1d2df43c17635558
MD5 7e7682d568a56205bb6fd79122a19c11
BLAKE2b-256 8eb2a11b86c8c514d01ebeaca791b3e5dcf5be37cf41d4b3ed75d9346ff526e1

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.3.0-cp313-cp313-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 890bea11f7250262dd77e6d7432aa8665832760634608f4cffbad5609e9e8507
MD5 29bd355e825e90805b0fe25852b706e9
BLAKE2b-256 78c1d42906531a59fc4ee523a05f8cb89b3c742ea981615cc4d6b185b4e6a242

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.3.0-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 9177f14deb52548546ba7cc6851f1858aa7527405150a7419fd7d726a18be8ba
MD5 60c3d40ad4fb55f00a8f6c071d9b634e
BLAKE2b-256 f853067e95b7857e9df9eec163d0f0340eb5d32bef336ee0b8dc77dbc4a1680b

See more details on using hashes here.

File details

Details for the file graph_layout-0.3.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl.

File metadata

File hashes

Hashes for graph_layout-0.3.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 573b58e71af714a748e65a9778fce6e1119e970387275d27f649067b9c91b486
MD5 d61d4aa44f15b3fbddef34b18f488a3c
BLAKE2b-256 a1f39a4dc23a5856f48ce1ea4b14f6bd12c526cef19d176e482abf1305939f5e

See more details on using hashes here.

File details

Details for the file graph_layout-0.3.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl.

File metadata

File hashes

Hashes for graph_layout-0.3.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
Algorithm Hash digest
SHA256 aed3a28f415b1b17e7fc088eff0f4e94ac0ce241c18bbab364b8f0dae1bb004e
MD5 350391af2b34e4f5f666755218c6a962
BLAKE2b-256 3db3479b8d737d2db37ea9935af46a95be28a825b5cf06518246139adfd3fa2b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.3.0-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 480908beb1061069d64abe547883c1852479b60d964fbe52f34bd7d1b1931397
MD5 193149d7ccf504bbda0997af814d0166
BLAKE2b-256 2654ae1eb1be6f0116e991e4624b0dcdb8cd0c2fe36e37a76b16548f8cfbc4b2

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.3.0-cp312-cp312-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 dab5e921ace57845cb8d4aee3f84246ec70dd6778dbecb4c406d423c8644c71e
MD5 8a3a3093045d016ec5ea6b3a1ecb123e
BLAKE2b-256 c979d9d6725e91f780afab3f8164d1b5e4d0670d52adb7cbaa4c2c30b5f0ee67

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.3.0-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 c6a2e23619e2a538d98406517f8516931eb87dc31ddac1c5dcdab279f4f0ca4d
MD5 91d17aec37ca828a9d2ac1ee1ddfa5ef
BLAKE2b-256 6ccad5ed1ae6300b473b310f3a6fa7b16de19b38bfaed43389196802d5e31b87

See more details on using hashes here.

File details

Details for the file graph_layout-0.3.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl.

File metadata

File hashes

Hashes for graph_layout-0.3.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 a50ed8f2ce462df44c2a73157790fa8438d5c501416b9da888d6c434ea80b4ba
MD5 29a8fee06acd39ba956765582a6f8829
BLAKE2b-256 03c8457ae859470c17594477f3a473f32aec2e3d3e65cffd29b0695b827595bd

See more details on using hashes here.

File details

Details for the file graph_layout-0.3.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl.

File metadata

File hashes

Hashes for graph_layout-0.3.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
Algorithm Hash digest
SHA256 a5faa49ee457221b80d9cfe2f3abdd909348c51b426a3e559c8b14361d63a27a
MD5 0dad9e86cf63e07f78b53fa0c26e4833
BLAKE2b-256 7691d412c07f576c0bf2a1fd41cfefd32cd02c0456a09fa36ca5d382085b06c6

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.3.0-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 e17ebac57a2305959a7768bd1337fdd0a4ccf00d712c24ce180b7cd5d101c4c3
MD5 dbebdc2aa30a6ce53669f7b37c4e4792
BLAKE2b-256 d5bdfbb30c8569387ab9418a063f133e8e4a4b029712f31724a73531614172ca

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.3.0-cp311-cp311-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 fe3948c3e29499114426a5bedcb5b2fc3a90d601775d6b0b4602eb6a21d9e137
MD5 30fe11bcfcec2707126d8bd637696ea5
BLAKE2b-256 7cc9c9b2f27332854e5e5cc79332445e689f0853349bb18abe7243364394b900

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.3.0-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 43db56cd0ccc3b86399f9c3b5ccd0e0dfaaa97df9de2ece1e5639b06cdfc26a3
MD5 a96c4226439bfd3adebd3d2224032e3b
BLAKE2b-256 2a5318548e5e4b17abdd02ed96a671790599d09acd214e4b05ceeb4c8e99be75

See more details on using hashes here.

File details

Details for the file graph_layout-0.3.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl.

File metadata

File hashes

Hashes for graph_layout-0.3.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 038a84d55130e95a95467f19aa860f50f3fa308c515b6f0d9ff737d5bc75d4e0
MD5 6c1997801a6bd515fbc3d3eb3750853c
BLAKE2b-256 0f967055ef91cd2d988f2c0fbf3b2931ecc2f332205f58fddafe0765b5106501

See more details on using hashes here.

File details

Details for the file graph_layout-0.3.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl.

File metadata

File hashes

Hashes for graph_layout-0.3.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
Algorithm Hash digest
SHA256 ce5c2391a0f30d034568601382793e7dc9b398158504a86f5f5260fb1b054c07
MD5 497b458242366e7fb338f6e8f83ac4a0
BLAKE2b-256 1a24ff434d2a4d168d55a3f357af97e68f8ce7785f1f1b2980451393234de391

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.3.0-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 9146edc7fb5ebb42fd73044c5d44494e299ce643e8f31ea73d35788253f1015d
MD5 dd37376e95115b10c591f70fa055d445
BLAKE2b-256 d9d441cd7622cf7e4021cacbc4e0ad18b4b4bdd7a2bfa37696c0390a3e184aaa

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.3.0-cp310-cp310-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 7e9819def9c3c21a51469a24ed2140446ec9614cc3df388197d1c9b361083605
MD5 c68dd47838eb06b3fa15cccd324d267c
BLAKE2b-256 2fd5742b6fb9bfd94b21c3fa09e1c8416bf93f6350057e6a3a91c641c406e597

See more details on using hashes here.

File details

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

File metadata

  • Download URL: graph_layout-0.3.0-cp39-cp39-win_amd64.whl
  • Upload date:
  • Size: 398.9 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.3.0-cp39-cp39-win_amd64.whl
Algorithm Hash digest
SHA256 d90874b42fc52f66d3b395db19a53372a228c03d98fa960b10224af5d0e091a8
MD5 f21a89e215eada0a88031c1b81ab4f16
BLAKE2b-256 f0504f4685a404ebea906ca1a7eca20e44fce422a3afbf9b315ec093b6f476b1

See more details on using hashes here.

File details

Details for the file graph_layout-0.3.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl.

File metadata

File hashes

Hashes for graph_layout-0.3.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 52e1bc7de0984baa3bfd910e22c184f65e86fe3d397f85dbd9dcdeba555abf4c
MD5 71c7aee0c3e5bdef3ea5f02372720727
BLAKE2b-256 ca62b36177e68baac48c1f0e4aa361815145f92bfad649ae3e551b30555fa718

See more details on using hashes here.

File details

Details for the file graph_layout-0.3.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl.

File metadata

File hashes

Hashes for graph_layout-0.3.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
Algorithm Hash digest
SHA256 897fb05fcfac37648c9edc8b9aacfe86c2d126459d1fd59706796a904e4d8653
MD5 4a2777f55c7fdcc205d6df64cab60ebf
BLAKE2b-256 3bbc548e1f64ac3748a588094fcd68f051e93937761cddcdfb711846b3076f6b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.3.0-cp39-cp39-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 84a02537f5482d987f09be5f9d6a85ae6df47597bcc12533494dd58699d77f2c
MD5 9c43a9260f5ff557f87bd843d56773e5
BLAKE2b-256 718248f3a480d35382dbb654d82b31041b2a5ebc302e96499fe87a4cfba0e785

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.3.0-cp39-cp39-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 2923b7a31bc0a1e5c4f26e12f86a4ff7b3e0039d50c43009f217714ee4b23a1c
MD5 ac041387e9af6273aafce898c2c18cd7
BLAKE2b-256 11f9468fab305f84ec779f6e63567325ea58a720d6e3f48c835d4c96eac0f2be

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