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.2.0.tar.gz (2.0 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.2.0-cp314-cp314-win_amd64.whl (391.2 kB view details)

Uploaded CPython 3.14Windows x86-64

graph_layout-0.2.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (423.6 kB view details)

Uploaded CPython 3.14manylinux: glibc 2.17+ x86-64

graph_layout-0.2.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl (406.3 kB view details)

Uploaded CPython 3.14manylinux: glibc 2.17+ ARM64

graph_layout-0.2.0-cp314-cp314-macosx_11_0_arm64.whl (365.4 kB view details)

Uploaded CPython 3.14macOS 11.0+ ARM64

graph_layout-0.2.0-cp314-cp314-macosx_10_15_x86_64.whl (379.6 kB view details)

Uploaded CPython 3.14macOS 10.15+ x86-64

graph_layout-0.2.0-cp313-cp313-win_amd64.whl (386.4 kB view details)

Uploaded CPython 3.13Windows x86-64

graph_layout-0.2.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (422.3 kB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ x86-64

graph_layout-0.2.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl (404.1 kB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ ARM64

graph_layout-0.2.0-cp313-cp313-macosx_11_0_arm64.whl (364.2 kB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

graph_layout-0.2.0-cp313-cp313-macosx_10_13_x86_64.whl (379.0 kB view details)

Uploaded CPython 3.13macOS 10.13+ x86-64

graph_layout-0.2.0-cp312-cp312-win_amd64.whl (386.4 kB view details)

Uploaded CPython 3.12Windows x86-64

graph_layout-0.2.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (422.0 kB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ x86-64

graph_layout-0.2.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl (404.7 kB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ ARM64

graph_layout-0.2.0-cp312-cp312-macosx_11_0_arm64.whl (365.2 kB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

graph_layout-0.2.0-cp312-cp312-macosx_10_13_x86_64.whl (379.8 kB view details)

Uploaded CPython 3.12macOS 10.13+ x86-64

graph_layout-0.2.0-cp311-cp311-win_amd64.whl (386.8 kB view details)

Uploaded CPython 3.11Windows x86-64

graph_layout-0.2.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (421.6 kB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ x86-64

graph_layout-0.2.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl (410.5 kB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ ARM64

graph_layout-0.2.0-cp311-cp311-macosx_11_0_arm64.whl (365.9 kB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

graph_layout-0.2.0-cp311-cp311-macosx_10_9_x86_64.whl (379.6 kB view details)

Uploaded CPython 3.11macOS 10.9+ x86-64

graph_layout-0.2.0-cp310-cp310-win_amd64.whl (386.7 kB view details)

Uploaded CPython 3.10Windows x86-64

graph_layout-0.2.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (421.0 kB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ x86-64

graph_layout-0.2.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl (411.1 kB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ ARM64

graph_layout-0.2.0-cp310-cp310-macosx_11_0_arm64.whl (366.3 kB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

graph_layout-0.2.0-cp310-cp310-macosx_10_9_x86_64.whl (379.8 kB view details)

Uploaded CPython 3.10macOS 10.9+ x86-64

graph_layout-0.2.0-cp39-cp39-win_amd64.whl (387.1 kB view details)

Uploaded CPython 3.9Windows x86-64

graph_layout-0.2.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (421.8 kB view details)

Uploaded CPython 3.9manylinux: glibc 2.17+ x86-64

graph_layout-0.2.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl (410.8 kB view details)

Uploaded CPython 3.9manylinux: glibc 2.17+ ARM64

graph_layout-0.2.0-cp39-cp39-macosx_11_0_arm64.whl (366.9 kB view details)

Uploaded CPython 3.9macOS 11.0+ ARM64

graph_layout-0.2.0-cp39-cp39-macosx_10_9_x86_64.whl (380.1 kB view details)

Uploaded CPython 3.9macOS 10.9+ x86-64

File details

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

File metadata

  • Download URL: graph_layout-0.2.0.tar.gz
  • Upload date:
  • Size: 2.0 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.2.0.tar.gz
Algorithm Hash digest
SHA256 ad4a61bfae15a620b3576bdee44c5ed216f638c53c204ee2b85706fc7e39e5eb
MD5 3e69a65b3ea25fafc21c0e519e2e06b6
BLAKE2b-256 8f733b763d835895103b7f34e2d945e1a4a6654646ce0325a71802f359275cfa

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.2.0-cp314-cp314-win_amd64.whl
Algorithm Hash digest
SHA256 921fb5fad069f43711a8ff0094757d15c6f0a8214dbeb49ca1582818bd5f77ba
MD5 d57d0aa84de0a5be0e29a49386e7c205
BLAKE2b-256 3980340a69bc05ef5265ebfc3188e4b8cc2bb105e9c14c9381f6cc1ec5a692e6

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.2.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 f5328265fc01f61c2a85c5984b02160a94abb7642c9329dfad08bb97d60f6180
MD5 c19d174f156e6f39a916482eefa19271
BLAKE2b-256 1f0595f8e1398f7ea0d3f04bb64769d3179d0cd71e5b2ec6a44905d248c87db2

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.2.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
Algorithm Hash digest
SHA256 e980d3ebeea0fcdfa0c7d457bfcb697ee0a516dc724d5c4377b05f47dad20439
MD5 183d157fe085f1f3697dcbd683fee228
BLAKE2b-256 86c61e8243c5c6c84c247e1bc723ce9c0d970ae861ad64105c2a0c6917768662

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.2.0-cp314-cp314-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 032feae014146a7cf0cf8fc3889a16981a69e5e605ae186dfd633f6f0f7a0494
MD5 f3ce2a6a59621927f7655059d8ccda77
BLAKE2b-256 1e5572a6caa939f9e043fd91844e2d144f2a7f42c23c1ab0377a7a956e077961

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.2.0-cp314-cp314-macosx_10_15_x86_64.whl
Algorithm Hash digest
SHA256 6853a7724a6b49800fe2e7dafb40ec4f1894ff08021d8b31daf59fba69d5ed30
MD5 d79ed6e1bb3b9f9346dc9f3659805f08
BLAKE2b-256 7fd90e0ad3756fcfad384fe412bd1a08c6d8669e263cc69037b0ab5367360b04

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.2.0-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 790fa7d6fb7e78872c5f645d1286cc9a8b72305b0229fd954206c0952cae26b8
MD5 97c8da7e04dcf889d683622ef7f5c42f
BLAKE2b-256 b0a7e6ace473aa08cca56511f6c2341850cdc4703876282a330e8b47c37e0aaf

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.2.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 579d539d4ff65fb3b35f39b4a100bdbee75bc207978cf6f72b8780d2c4fe155d
MD5 c2d04f51b3713163f985e2d0cdb8f53d
BLAKE2b-256 69a3301061b7e7102f49eeddd7d0f9fae0faf1c4bf7597be221fdc7a24fd0a7a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.2.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
Algorithm Hash digest
SHA256 e96ecf4a008a92d8c8ff38df19cadf31c41ce53d81d12d136dcce343a1458538
MD5 42699d19b23edcf728a363576970e567
BLAKE2b-256 a37d75208bac8a3e2f5f07b78cf2c1f6e73cdf128f00a3601b34177b5cc8437f

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.2.0-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 ecea49cb5e676bce5790c9c5bfb0280750c9b0c28647998192770ed2394266ae
MD5 e8c1188d3022cdbfb6f4aba50bf150c7
BLAKE2b-256 c731d5b0c483ce5361f700f4c418926674b84baf87dbf08599ae7ff8bbdc89d2

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.2.0-cp313-cp313-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 3abc71c105a612954e53e74115247350227f50ab396b895430d4421492e241bb
MD5 6f5fdbc0dd0d2c3ca06f5b9a89cb2172
BLAKE2b-256 2e6a13d47db3abe9672c63cd2c1c0fd236e47005f00cc5a716aa57b853628eba

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.2.0-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 821a6c9cadd7a53183dce68702484e855ed247d92ff4fb357cd36b0432281ad4
MD5 d0159346f24025b587fc1542d448423c
BLAKE2b-256 ed63cc45251bca0d9f570092cc3f0fb5534f21aceaf1a626fd1d91bf315a6b18

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.2.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 118362dff0a5e490395d736330f2e790463f2f7a859289ccf4b83cba0acfe7f8
MD5 cb8ca21dee4a6883585229ac6dd052f7
BLAKE2b-256 f52381c8353740093ae53a07a97cd33644ef472aed3f5cfdd4adab56e379ecb9

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.2.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
Algorithm Hash digest
SHA256 cd67342bac448a54cb2d517766b23692f681ee48e829de9e9b4f28c300e79cc0
MD5 4f087548d41936a04fe532b8246cb937
BLAKE2b-256 f9a1ffda288ed53be2a6d59f39415b8472456402a5f69bc3abdc80da1f381ba2

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.2.0-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 96706392c748bc4c26320fa7e6f28a0afa07155895c65e6974b711d1037a1124
MD5 07a5e62c320b732c6866fc24061c597f
BLAKE2b-256 99d352b05c8ff7dcdfffd9fc75f3f8f6540f8e7361c8a5bdef5110af5d70eee0

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.2.0-cp312-cp312-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 66bbab84b033428310b25d0246b3137e4a38632f23cd1a5084d3b991f7535097
MD5 af73a6b3b02d1812f416da78866666c8
BLAKE2b-256 cbd2d711695a7b6b41baa456f08358bc6a2d2822c6394d7d6b0f5bbe59b307bf

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.2.0-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 f58a30b84cf09fdc209fa3538bb4a77a9a7a81b9c45c7c8203c60dac06fe3d51
MD5 90809116bb226d3281407f2973e346c9
BLAKE2b-256 cf0c2abe4513b9f64ce4f5ec8d5cafa3e873a0cf313cef85fe8dd0971e45d289

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.2.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 53613e1539f6783b8c48f93db478c8ddadffe6d00c99b32fcd254ebc22009d02
MD5 690ae9281b70806f1584bb8e24d8f07d
BLAKE2b-256 d77fcc3fc581d4678312dff1b07f28de9f14a0fc9a5fb07101b59ddd868a4767

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.2.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
Algorithm Hash digest
SHA256 70354dcd35fc909dcc54b9f5c4ee04687d4405d72282e1be1a8f788a4d77860a
MD5 a73d16c511ebaf7e5c83166a69bef111
BLAKE2b-256 0dc8754ede1973675de2cbb2ced6cd4a2f4239e9e5305d8ee340e7b83cc8c798

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.2.0-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 f899f3e6963e7e28440629366182d4b2e0be6b213a0c5bb1997abf5d8503b7b4
MD5 d54520849b991ed2342fa81023f73ab0
BLAKE2b-256 dfbc7ac3dea11a9eda6b06f9597254242f52bd2d5af6c114f0655c6e5436f876

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.2.0-cp311-cp311-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 77ef54766b046516608b2ef684a0a373036ca9f617a7676d4be08c569acaa87d
MD5 be13268cafed7f59824eef187d5ecf9c
BLAKE2b-256 40ffc87c2ab6bb0a2654e168d47d2818b83e2089da29105fb284ef5f11c698e9

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.2.0-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 82a3a36b1fd52ea30a500f38b6a7743b52a3d525f6a1fa756ac22c525b215bfc
MD5 a589748983f048ce2030ff36252a92ef
BLAKE2b-256 56aac2a51e3a1a7381ece6c5a3ce49485697bf4de69bf33fdb1dab6cbb52062d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.2.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 609016a6b483ccd3b837f3847661bef1c59de28d0ed561750dcf89537924831e
MD5 119d9fbe56e495c0a716d4f43f5f04bc
BLAKE2b-256 d34c7c92558b0ede57eefd4b22a759698eda7fc7129cad35c545acf04148f94b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.2.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
Algorithm Hash digest
SHA256 14dbc17a9397cdbb0245e7489d5e85a27ee3fbb9cf7d6f70e6cf0901ac67d581
MD5 0131aae7912c9070263c2e1b94ab3e7e
BLAKE2b-256 26f188514925d49e8d866370111f9222bcfeeeea8a76b3963e316efc6da3e267

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.2.0-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 b2f5f97d734ed9ced1a3a8075d415e1507da39b63d6365288e4256964cddce77
MD5 3d50042575d6a384f5426cb61e4648c5
BLAKE2b-256 bf2ac1f819f524244aa031870feb73de21b244001770efd130d959bd80f97803

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.2.0-cp310-cp310-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 60a8b7673694b03ae8caf5a3de305276dd5e9e31cbfb8a1c6cc2ff7e2b05cabe
MD5 b88e181d36745dbb51c4a2059f0ccbea
BLAKE2b-256 aeb4b663d463f8606f61988336bf5d81fe204e5c70a2a806e5b5dbb20b9a64ec

See more details on using hashes here.

File details

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

File metadata

  • Download URL: graph_layout-0.2.0-cp39-cp39-win_amd64.whl
  • Upload date:
  • Size: 387.1 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.2.0-cp39-cp39-win_amd64.whl
Algorithm Hash digest
SHA256 b98d596b76e29241166499488e501bf863a3a18d04be3e766926f6f9f494dfce
MD5 9e458460bb48e0aee85a0cddfd35edd5
BLAKE2b-256 7e5d5e54f00746414f61e890ff0449aaa3de6b859e746dd61910129cf426dcac

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.2.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 9bc6bda4383da08c5a47b634d31ed45e5aaa3745796527a4e06dc29cc394959e
MD5 82e8990c8ae21c72c45f05f763841bf6
BLAKE2b-256 1482de58a5b4906c8f57e6077417a05790eac0e2899ee5ed7d137603aec82ee2

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.2.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
Algorithm Hash digest
SHA256 69ea93fca44c5a6daace54c64ddef316e6218ce7f18a1cd026f2cc06881d8332
MD5 ce3ff0b72fa78f58bb8bc6e9ffd5543f
BLAKE2b-256 ea172158bc5c0f18b97250eb99e6abed41cb7f4171cd5cf216636dadf056e5fa

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.2.0-cp39-cp39-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 2f893fe035b70d10c168159f8bc6f3756839d2c1c7a742225897ec39290e69b4
MD5 db70bf5d926b8c43e6975973628ac657
BLAKE2b-256 cbff7d44b7d6db0a35d69b9c4006714eb64dac07ae3830ab95fd64c9d7b9a024

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.2.0-cp39-cp39-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 a3f1e12784e10c3f3a6bd25edc4638884f8a7830570dbfb6aa2cf591c110699e
MD5 311bdbcab479ad8a5e29d7c51ff80613
BLAKE2b-256 774995f534aadcaa5fae31e4a200159eb931e2ab997104615b8a95173311fe2e

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