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 Bend-optimal for degree-4 planar graphs

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 bend-optimal orthogonal drawings for planar graphs where every node has at most 4 edges (degree <= 4). Based on Tamassia's algorithm:

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

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.1.8.tar.gz (528.6 kB 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.1.8-cp314-cp314-win_amd64.whl (371.0 kB view details)

Uploaded CPython 3.14Windows x86-64

graph_layout-0.1.8-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (1.2 MB view details)

Uploaded CPython 3.14manylinux: glibc 2.17+ x86-64

graph_layout-0.1.8-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl (1.2 MB view details)

Uploaded CPython 3.14manylinux: glibc 2.17+ ARM64

graph_layout-0.1.8-cp314-cp314-macosx_11_0_arm64.whl (363.3 kB view details)

Uploaded CPython 3.14macOS 11.0+ ARM64

graph_layout-0.1.8-cp314-cp314-macosx_10_15_x86_64.whl (378.4 kB view details)

Uploaded CPython 3.14macOS 10.15+ x86-64

graph_layout-0.1.8-cp313-cp313-win_amd64.whl (366.1 kB view details)

Uploaded CPython 3.13Windows x86-64

graph_layout-0.1.8-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (1.2 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ x86-64

graph_layout-0.1.8-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl (1.2 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ ARM64

graph_layout-0.1.8-cp313-cp313-macosx_11_0_arm64.whl (362.4 kB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

graph_layout-0.1.8-cp313-cp313-macosx_10_13_x86_64.whl (377.6 kB view details)

Uploaded CPython 3.13macOS 10.13+ x86-64

graph_layout-0.1.8-cp312-cp312-win_amd64.whl (365.7 kB view details)

Uploaded CPython 3.12Windows x86-64

graph_layout-0.1.8-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (1.3 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ x86-64

graph_layout-0.1.8-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl (1.3 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ ARM64

graph_layout-0.1.8-cp312-cp312-macosx_11_0_arm64.whl (363.6 kB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

graph_layout-0.1.8-cp312-cp312-macosx_10_13_x86_64.whl (378.8 kB view details)

Uploaded CPython 3.12macOS 10.13+ x86-64

graph_layout-0.1.8-cp311-cp311-win_amd64.whl (366.8 kB view details)

Uploaded CPython 3.11Windows x86-64

graph_layout-0.1.8-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (1.3 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ x86-64

graph_layout-0.1.8-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl (1.3 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ ARM64

graph_layout-0.1.8-cp311-cp311-macosx_11_0_arm64.whl (364.6 kB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

graph_layout-0.1.8-cp311-cp311-macosx_10_9_x86_64.whl (378.8 kB view details)

Uploaded CPython 3.11macOS 10.9+ x86-64

graph_layout-0.1.8-cp310-cp310-win_amd64.whl (365.8 kB view details)

Uploaded CPython 3.10Windows x86-64

graph_layout-0.1.8-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (1.2 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ x86-64

graph_layout-0.1.8-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl (1.2 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ ARM64

graph_layout-0.1.8-cp310-cp310-macosx_11_0_arm64.whl (364.9 kB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

graph_layout-0.1.8-cp310-cp310-macosx_10_9_x86_64.whl (378.9 kB view details)

Uploaded CPython 3.10macOS 10.9+ x86-64

graph_layout-0.1.8-cp39-cp39-win_amd64.whl (366.2 kB view details)

Uploaded CPython 3.9Windows x86-64

graph_layout-0.1.8-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (1.2 MB view details)

Uploaded CPython 3.9manylinux: glibc 2.17+ x86-64

graph_layout-0.1.8-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl (1.2 MB view details)

Uploaded CPython 3.9manylinux: glibc 2.17+ ARM64

graph_layout-0.1.8-cp39-cp39-macosx_11_0_arm64.whl (365.2 kB view details)

Uploaded CPython 3.9macOS 11.0+ ARM64

graph_layout-0.1.8-cp39-cp39-macosx_10_9_x86_64.whl (379.4 kB view details)

Uploaded CPython 3.9macOS 10.9+ x86-64

File details

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

File metadata

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

File hashes

Hashes for graph_layout-0.1.8.tar.gz
Algorithm Hash digest
SHA256 6dccdb02d1db0e613642ae60cb8d8cebb59a6f895c1c9afbca512185d7fa6b8c
MD5 3ef06f3929bcc54fc33efd852cc1eb7d
BLAKE2b-256 7ea97ac8fa220af3698610395aa194038906b8efae670f24ab197403a56b1a71

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.1.8-cp314-cp314-win_amd64.whl
Algorithm Hash digest
SHA256 8c8e19697ca1481eed845ef9e9ef1ec4f2cfe612880659d6894d807d6eca9768
MD5 edb42a9e17846fe0af4a0e0c58ea4ffa
BLAKE2b-256 e90d224db60e75d69971bd702232a873e7dd4d974851fe584ec7046b38a84685

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.1.8-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 cb62f76eee479a31ca3cf9a46bd7b28f15c6941d03806bac6b3b9fe197c38385
MD5 8f0ee12f16d2e04a50b9fc81bbeba86c
BLAKE2b-256 438866fddd39d1e50d9b385e0b349b8ef6cfc5212a90a77ae37ca9e603c9fada

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.1.8-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
Algorithm Hash digest
SHA256 bff3d8dea427cabbc5f6c98c02708f37bf1b5904a450642555adeb2ee5fcf9c5
MD5 7cd9842c7b5d63969a9256619cb2035d
BLAKE2b-256 e7911d6a03ee458d8f1d6eae393e758f0ccc4f1c5ee75edb484039fc9dbacd88

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.1.8-cp314-cp314-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 5729b6b4b6c5673ad8c7126edd22b1e4faf8910022f731b361e7918c2ea00128
MD5 e86cdd7831b9d5b8a6f2fd091a66ff5b
BLAKE2b-256 fae7c6c97d4bfe2f61d3b56b69a955977d8b51a06362eac275a870f9ed859cba

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.1.8-cp314-cp314-macosx_10_15_x86_64.whl
Algorithm Hash digest
SHA256 e74272c5efb44b4ef371b20c3b7e99377e5ce40edd1e63b2e45848115aae30d6
MD5 38164b48a01e034ff92f5837f2f871d2
BLAKE2b-256 8cf76992f4334b9dd0b54fa422ae73e17283052243037ee1f128b8b6852c10dc

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.1.8-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 0d2bc12b785be5c3b7b997994232c811524afbb23bdf6922640c76b1e4568e48
MD5 e8a751f13b1bc8e305c4e726cacaed49
BLAKE2b-256 5db336f8f15948925639682b0aa9589834c03c4436a04aa74bd79fe3751ebbe5

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.1.8-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 7f0c5742044634a376cf5b1b954814cf82079001cd73b0ba1d6232fba533b691
MD5 fefbd0ffdfe88ee4120ff49513c58fa6
BLAKE2b-256 1626ff0059a68eabe48113359b81e484774c446fe94437080d1bb46f99661b12

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.1.8-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
Algorithm Hash digest
SHA256 36bcb51b202b35d6c20dd6e7791969d559d709eb7affedd814d9e20ab05a7503
MD5 17ac30337742d9a64d8020801199a396
BLAKE2b-256 d395e91034d28084ccaae69e0d7ecc7669c3c8249907ca2f2579a84dc3ad0223

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.1.8-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 6e9105e49b8b1f3bdc44a2e22e8519b4d60207a0f3f10d1559373b5f7bf8a7a7
MD5 1f28575f86864a11639910aad65ce3b4
BLAKE2b-256 4f96902aff63f132d380c534c9a64e0daf9ab6a76a47557349d1b78e790abdf7

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.1.8-cp313-cp313-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 28a6b3d953d4658abf574609e0823de6fc3d3dc7b790d1e9ee3b1fbccec8636f
MD5 e632e58f469ac1ae7bda8455cdde083e
BLAKE2b-256 6de699ca2096ec8fbfdd50e39eb053779d4ad1b6c7871405d150a5e1a01dc655

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.1.8-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 aa1bf1eede91ab0319d63debee8301538be1fb6c6bc03e7583987c5b194969c9
MD5 b654dfc202e85e0d3cbfa2f2a87ebf3d
BLAKE2b-256 f017d0226bf00101d0628c9160c786872edcdeaa1eadf423bbcd0e98de0ecefd

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.1.8-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 70db2bd0f120b26e8737989a268601ebf8474d08cb817ab9aeaeaaa1ff151a95
MD5 e601a9b63a0c2c8d77ede8c2b393905e
BLAKE2b-256 d18c3d2939630731c37d081c353581a6f611f8aa075647dd3105591f5209485b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.1.8-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
Algorithm Hash digest
SHA256 bb646b732e2ee0271f377ab5a29e3835941432a9abec08e76b6eff1b5bdd7826
MD5 33a204dac2324d80646e1ccd01a27730
BLAKE2b-256 f6379a167edf96ac6042d896b28fc43ee2a61d8a517b61240f3f988474696574

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.1.8-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 4fbe761f1500324579c0abb61def4828526a0b60993035dc39ec01ec2092c6d5
MD5 d9fdad2e3de74fabc71f3a38717c920d
BLAKE2b-256 b7592165a72986e3698b2262c544e1abb5879ec5a14faed192d999e899416965

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.1.8-cp312-cp312-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 08e645b37d3e9d02bcdc3709033ec9dcf14014339d4571e7ba06b4708eaebc54
MD5 a1cc7150b668eb49437600f77bad66bf
BLAKE2b-256 d0e0a56b5c08f85b330efbccc0e9264f63a089289240213aeb8db5e1c155d6f9

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.1.8-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 36419a9c856da08ba481629187c23f75eccd33fe1a3c06518db16844f84c78af
MD5 c2a16e153803f7269ca20e4e8e963620
BLAKE2b-256 33422f9589f783d40aacfcc1388c03ef6bc5a101002fc9033136996e02fab78d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.1.8-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 c82452a1d6d3fd9145322b927c4173fb03f2b937e8dbc252c61da1c4eb035943
MD5 823dd93890b6f23a0c63525d1347365e
BLAKE2b-256 fe922e63c3cf84dd4d3410b13e126233cf980e98b7a6fef32a2087715eee5fe5

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.1.8-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
Algorithm Hash digest
SHA256 201825b7a6f784eed4d60c2737047eba9b9cf25b7c0903b2b7d2b8da45f50efe
MD5 dfb421f8cb66a6494fd77eef0becde9f
BLAKE2b-256 d610e278bf4d24c06f94ef397c720a95c46db7b1dec2fd42b90c5522175acdb7

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.1.8-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 363b418f7cb355c97e7d3429bca345ff170e40192b8fb944bc1d1e1d7e64f8ee
MD5 8ba23020d27377a106fbde723784fc74
BLAKE2b-256 2eaca79f0942b6a0b53621f76e231016ac5d61d159521c79889ad4a310485fd8

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.1.8-cp311-cp311-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 3e6f7268357ab08460c6883342c6eaf19f3c63b60c7eb888500c43f7f33f1a9a
MD5 8c7ea76a17c8f642624c88af80f64a87
BLAKE2b-256 79e23fc75cdbe1e583b8db689a516b3deed16cffdc0ef3e1ddbe709b8df2250a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.1.8-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 53e4fc5ea8d61f0b9615282bdf127f317e1d0e17d368ed56a673b0979d8353b7
MD5 3607cc21114b04a148c2e60101c3abaf
BLAKE2b-256 b4ced0ed99d10036263e262f1b399aaa95981ecdc07e480d95021efd928f53ff

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.1.8-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 a47d15b06320902053b78edc86f6a40aa68f806dff5a735fad24c2228fb797c7
MD5 fa6aa97c1749d6e72378ef1002811aa5
BLAKE2b-256 0ba3aa327808705ff691bdcbf0cd229dce9405840b3790ea28357f57c8e533b4

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.1.8-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
Algorithm Hash digest
SHA256 27657517abcd74f8931b30e27154333ca05044a7056ec82992e5c1af735fe09f
MD5 910e476d46fc32b3d5138ece92aaec51
BLAKE2b-256 d11e313257f8e8b282de8e840e26e78803a0bae9bf006452c53a784821948d13

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.1.8-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 69952e1cb502279324cbfd11e8365cb205187685bddd41d5f96579f6a0424180
MD5 f91ff54cefb758ab77f915600b57f582
BLAKE2b-256 1e2c3a212d58db6430735dfddf3ddad46710bf31ee79c17adc802b894c4ea854

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.1.8-cp310-cp310-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 578854631afedcfc0753b8ce2b2aa476e8a66650b76685a102915a03445f6749
MD5 8637b0885c27bbd1ce7b1fcdbb4532a3
BLAKE2b-256 68714582c3fa99a12e541b21ebd5a21e1782b67a70a7d633327ab58606800ef4

See more details on using hashes here.

File details

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

File metadata

  • Download URL: graph_layout-0.1.8-cp39-cp39-win_amd64.whl
  • Upload date:
  • Size: 366.2 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.1.8-cp39-cp39-win_amd64.whl
Algorithm Hash digest
SHA256 03ba705b10f550d8cc989d156162b3b1f30fd2311cbcc75109ffa0df9508d1ea
MD5 7c1b107f1bf32f5b0740c2244398b940
BLAKE2b-256 e1fd5b22a1f850f21b887102325b7a45dc132d516f266df5a207016f6483c46e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.1.8-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 8efa6324b01c7f51ff390d619a089d544c87790dfea16b4c5488f02a189fac64
MD5 622e99cf07d8babaf2f10f21c5f6a688
BLAKE2b-256 7b3f93c0a77406d83fd0e5189795a1aa0d23f5b2ba8eb902ce93164089ebc81c

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.1.8-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
Algorithm Hash digest
SHA256 025bd5d5dc708500acc8c3c9b1621101b48c0bc576a5eb15904b52e8b4b818f9
MD5 f7767db617596b2a2e7a3c97302675d2
BLAKE2b-256 1b25c1644b4347b557c6c8a7a7ad5f70bfae37d5c9805194fc1fcbe432a138a0

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.1.8-cp39-cp39-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 2a7ba6d00293c1491c989a8ee534404436d0ead712b14ccfc82a06e78faf68e6
MD5 4e8f6c0245feb458eac08528785306ad
BLAKE2b-256 a9e10c3bcf5655dc7246bb344e251d6ceb27d4368fc5d442bf651d467eed32ff

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.1.8-cp39-cp39-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 da6d0f321f9aa0513fc05054e6117dbeb50236423530e62b7a56120bf0a24efd
MD5 d87689e0e8f371ed075312a5707049b5
BLAKE2b-256 4f6fd837345057261ccb53629b9a072f18773a79483663d35ce406d7f6848cfd

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