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.2.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.2-cp314-cp314-win_amd64.whl (418.1 kB view details)

Uploaded CPython 3.14Windows x86-64

graph_layout-0.3.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (450.3 kB view details)

Uploaded CPython 3.14manylinux: glibc 2.17+ x86-64

graph_layout-0.3.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl (433.0 kB view details)

Uploaded CPython 3.14manylinux: glibc 2.17+ ARM64

graph_layout-0.3.2-cp314-cp314-macosx_11_0_arm64.whl (392.1 kB view details)

Uploaded CPython 3.14macOS 11.0+ ARM64

graph_layout-0.3.2-cp314-cp314-macosx_10_15_x86_64.whl (406.4 kB view details)

Uploaded CPython 3.14macOS 10.15+ x86-64

graph_layout-0.3.2-cp313-cp313-win_amd64.whl (413.4 kB view details)

Uploaded CPython 3.13Windows x86-64

graph_layout-0.3.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (449.0 kB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ x86-64

graph_layout-0.3.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl (430.9 kB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ ARM64

graph_layout-0.3.2-cp313-cp313-macosx_11_0_arm64.whl (391.0 kB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

graph_layout-0.3.2-cp313-cp313-macosx_10_13_x86_64.whl (405.7 kB view details)

Uploaded CPython 3.13macOS 10.13+ x86-64

graph_layout-0.3.2-cp312-cp312-win_amd64.whl (413.3 kB view details)

Uploaded CPython 3.12Windows x86-64

graph_layout-0.3.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (448.7 kB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ x86-64

graph_layout-0.3.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl (431.4 kB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ ARM64

graph_layout-0.3.2-cp312-cp312-macosx_11_0_arm64.whl (392.0 kB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

graph_layout-0.3.2-cp312-cp312-macosx_10_13_x86_64.whl (406.5 kB view details)

Uploaded CPython 3.12macOS 10.13+ x86-64

graph_layout-0.3.2-cp311-cp311-win_amd64.whl (413.8 kB view details)

Uploaded CPython 3.11Windows x86-64

graph_layout-0.3.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (448.3 kB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ x86-64

graph_layout-0.3.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl (437.2 kB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ ARM64

graph_layout-0.3.2-cp311-cp311-macosx_11_0_arm64.whl (392.6 kB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

graph_layout-0.3.2-cp311-cp311-macosx_10_9_x86_64.whl (406.3 kB view details)

Uploaded CPython 3.11macOS 10.9+ x86-64

graph_layout-0.3.2-cp310-cp310-win_amd64.whl (413.6 kB view details)

Uploaded CPython 3.10Windows x86-64

graph_layout-0.3.2-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (447.8 kB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ x86-64

graph_layout-0.3.2-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl (437.8 kB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ ARM64

graph_layout-0.3.2-cp310-cp310-macosx_11_0_arm64.whl (393.1 kB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

graph_layout-0.3.2-cp310-cp310-macosx_10_9_x86_64.whl (406.6 kB view details)

Uploaded CPython 3.10macOS 10.9+ x86-64

graph_layout-0.3.2-cp39-cp39-win_amd64.whl (414.0 kB view details)

Uploaded CPython 3.9Windows x86-64

graph_layout-0.3.2-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (448.5 kB view details)

Uploaded CPython 3.9manylinux: glibc 2.17+ x86-64

graph_layout-0.3.2-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl (437.5 kB view details)

Uploaded CPython 3.9manylinux: glibc 2.17+ ARM64

graph_layout-0.3.2-cp39-cp39-macosx_11_0_arm64.whl (393.6 kB view details)

Uploaded CPython 3.9macOS 11.0+ ARM64

graph_layout-0.3.2-cp39-cp39-macosx_10_9_x86_64.whl (406.8 kB view details)

Uploaded CPython 3.9macOS 10.9+ x86-64

File details

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

File metadata

  • Download URL: graph_layout-0.3.2.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.2.tar.gz
Algorithm Hash digest
SHA256 f76ece1711b7f5ceaade05f2f11f8f31e63a785b2e9461af471ad4a194917523
MD5 236d5acb619be62f29ccb56b036f9399
BLAKE2b-256 fcffd53f82c129d0ea03dc7729b4e48ecfc4f04ff7deb77d654ab9173b57180f

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.3.2-cp314-cp314-win_amd64.whl
Algorithm Hash digest
SHA256 1fbd4daa137c5654669fdc0e44396c7a23f344d28363edfbe940e41071205815
MD5 4321da1022504dd72d5337449011aa91
BLAKE2b-256 3b5d4953bd3f6d3d69c8bf3f4146f4157b335860a1151e7d2ba992436dd2dcc4

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.3.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 a7bf1d07ed53bc91c434754a52c1930a928769dce596db15aaa777e3b7c8fad0
MD5 d0db4e59e474b8e9a3c44c6eb3b2a74d
BLAKE2b-256 4023efce274408b85bb59b647af5b11705689430b8cb40630a86bb7c90705345

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.3.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
Algorithm Hash digest
SHA256 d9829346ccc0934caccb1d56be377683dd6f6bb1b6129bc2521ffb56da2613fd
MD5 c77b5c9a5be80ad771f502095ab3c1ef
BLAKE2b-256 39d88ee10e70443356ae1b81b170de3c13ea04692c979eaa21c37939788a0a26

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.3.2-cp314-cp314-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 0a5fa94a879394c0a7ca1594b1e9b0a7aa7fb5fbed580cdc842561d3b5fe1110
MD5 3b2d3733e6a1f134613d2695d651a881
BLAKE2b-256 1bf2da6cb71a333fdba8f31453e7bd2dcfd53ad195b71bf5887d5144daf3d768

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.3.2-cp314-cp314-macosx_10_15_x86_64.whl
Algorithm Hash digest
SHA256 829a9f056e3beab054975c113023d25b1a1e691cbdd1645b0d24ad50ed4d2621
MD5 7687b0a3a19c1b24e9ac6804978793ad
BLAKE2b-256 780a9724e8f7b7cc140d014f1130333ddc19c24129d3b6929d9294d98db81e36

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.3.2-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 e55ac8cc4b3b1b1efd2d47da813984bb5dcd0ce72491e0455ac551467657ac97
MD5 d0b964c80e1d31286abfaedffcae792b
BLAKE2b-256 a46bc59ee381faacaa613c350e0fa8ef7face85ac367ee04be981b47f75f0c3e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.3.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 15134bc8314ec40ae2f96712da41a3ada4972964dd53032bcd3c7caf850932e5
MD5 0d1dd349711b5842ecacd659089e586d
BLAKE2b-256 eb345664de29c576fe543b2b0a37bca10687f9f3c0314999e3e10f28880aaa2d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.3.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
Algorithm Hash digest
SHA256 cb1b0a96a05556c529993b0a23ea61e9ac141b9a64c4693c44468bd765962a15
MD5 f19f29ea315b6216bafb84e42efb390d
BLAKE2b-256 ebc5370c606516d34261f59a30a3dcfab0061fbed9593c3d0617a7a72f449b72

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.3.2-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 6961514435102af939cad6211718d84e3838518dbbb665c2863fc586223a64f8
MD5 2712a54388eec295b50f06278ed41aeb
BLAKE2b-256 3457fddd1b8eaf593aaf33c86a035104f108814a520cdac02b968511312ad64f

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.3.2-cp313-cp313-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 738a64df21408f5b69379613e8bbb27a2d7ac01a96233e6ab5c1ccb7b5456ed1
MD5 8ada1dbc198d1efa24c555663e77a13d
BLAKE2b-256 368695c52b24990bc0680a77e61c3cbde5a8aba730be536215baae1c20c7a781

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.3.2-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 a592f7c905f51a7c84b0523334a6d93f8fe26a6567f27f24497cf5816f5f4358
MD5 e44520c9d948f9308b54d48e0ceadc1a
BLAKE2b-256 abe0fec4cbf3df05c14bde881296dbb52cb9bc6573e5efbbb444dd5be190a4cc

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.3.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 d947f67ad07757bb210e6caa40ed002a3f3e06a2a96eb5a3511dea8aba237845
MD5 04772c4f4568db006d5ba5b70d140b39
BLAKE2b-256 0c74021339d3df6175dceb2d2cb59f2dbeab59b2b1aa800e6ccf3be4cf540127

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.3.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
Algorithm Hash digest
SHA256 d424299471ff37a00551c39bbb403c7203ae88d92bc5b974e4559a7c69e1fd35
MD5 8a69d222a8ca02d9be3ff372fca59eca
BLAKE2b-256 e6c121ed522569ee91b99a65134dea7499aedb0084faeb45dc247337f326d29e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.3.2-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 f838317339605254dfc1877cf1cfa9b207a7a45a3670b18cd171af57fbc11f79
MD5 d606906abea7a1a22b9071c9d21e5406
BLAKE2b-256 ada0d0fed815877f7f5be15ac3ef92e898c9bb3a37f686a530b085e873082b90

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.3.2-cp312-cp312-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 867de95e439c922855d3efad947a6070a93905d65fb57311dc1ed0f90f2144d5
MD5 c5a2a4eb4313bd27cdb73c1daedf7c10
BLAKE2b-256 48cffbb7a8f9b43424735f3f10038f84fd6a446c1c30d298c6b2c720b0dd6d87

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.3.2-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 5650096930e8820be7675528baedac0de9a67ed3104723aee8989be9d0ec9cb7
MD5 8764722606eca2b80865a4d2c88fd174
BLAKE2b-256 d8522417cbdecf1c9b3f6a721f461e99a4c17a93866c0dc727087946f1a60f40

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.3.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 f15bed57433ff54227fa019cdf7ca178fc11e2e10c117d27c4e0ec853af8e263
MD5 a99609097e69d80ff2d078fb45209eba
BLAKE2b-256 b18262484928865054744066097bc1fdf8db80dadf423a3317d4d0b333ea217c

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.3.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
Algorithm Hash digest
SHA256 c499d48bc65d118cc700aaab043ddcb88324a7daeeda41c4bfc47e37f8b64422
MD5 b1801fb7dbb78ba18cf091c32753f1f1
BLAKE2b-256 ad62ff0b30fd928bfa88261f286823c619071e464c317dd46207f82850219d9a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.3.2-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 b4c5e52ceb6c87fa447463d9bc4beb6b5680ea2372c720a0f9f63551b6a83f39
MD5 513ef2857080cfb72ea92c7120b976b6
BLAKE2b-256 6a728091cb59dc1e37d4bc8064edb05bd8742c4288705c2838024c08fb4fac64

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.3.2-cp311-cp311-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 48e5ef74ae4303c52f9e83d7d1ebd57863d141f4fa54cae49a6df33b4f21c142
MD5 ea5a419bc060a86271ddab4ba5d1572a
BLAKE2b-256 e8732df95b7687bd2a72389e5b4dcc525e0b0e444371ebb12f0cf6a24d78aa72

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.3.2-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 13d238e50cccd4ff363f16443e952dae1d56fe5d54d4cbe15f4ac77a03fd5dee
MD5 7e539422887ec8f945e04f988f357af0
BLAKE2b-256 910ea8d903d773e24d2439c5da5d36382dc504d6399bb7a8934a9755ea04b49f

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.3.2-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 78c6f6aea98ab2cbf8585f21e102e0aaf3d0566d70c429d6922faec6d016f8d7
MD5 80f2cb2be9847a5e0dc746c834252a1b
BLAKE2b-256 e5ec8fda20ce4859f7f311079883e3bf19fba81971c2baa65d7c5c2383822590

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.3.2-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
Algorithm Hash digest
SHA256 91b9e88401d7f42679bc988c2c593a959dce9f51b62f3bb2aac3cac242274a3f
MD5 f2ea8738b35d381f4247ff20b124a6a0
BLAKE2b-256 b8bb1d148d2c6a078d5e9b5de3d046e7f736d8acd1c006899c64b9ededc8f9db

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.3.2-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 6fda0cea9db77b97267b30342ce70837781e36120e137a9fa581e2e63d7d0389
MD5 7f4de3331e01e0685032cddec9a8866c
BLAKE2b-256 7437b64ca81535d818527eb7460d17beeb34b4d1e17b3c50208f216e91b5480e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.3.2-cp310-cp310-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 a7d7bc78f78b145592f3df92a32217dc7b787df4c634cf3a6a324ad065587de1
MD5 23f2cefbbf8edfc95625e62eb384767f
BLAKE2b-256 60e19a38f9a3446b6a37d4b1f92f3d5a2dd896c144aea2b1933b997fa2365c2e

See more details on using hashes here.

File details

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

File metadata

  • Download URL: graph_layout-0.3.2-cp39-cp39-win_amd64.whl
  • Upload date:
  • Size: 414.0 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.2-cp39-cp39-win_amd64.whl
Algorithm Hash digest
SHA256 2ea0017580a942384ee544f990b836ec415077360fe1aff46f897574b681383a
MD5 965cf9f3c2faa66b3757426ebf4edefd
BLAKE2b-256 d35f96884b1dfdc89c83571e599519e2d7c1ac6261199440563842b6b646eb06

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.3.2-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 c9804f70e651e01eceb3b482be5a403a3413ca8b1f0ba5b08309c32f1fb16919
MD5 516857fd6b39094040e98f0d142b0d1e
BLAKE2b-256 4181f09e690dc17ff90fb6fe1e1b8f47331683db5da319eb62ecfb6410bff2cd

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.3.2-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
Algorithm Hash digest
SHA256 c57630eb7091bb8e8292f5c1773ded24038d005c6d7eae5e96d2a7b78510bf95
MD5 2d6e03fbbfbf37201d2611640e064e8c
BLAKE2b-256 b278fe54c6586101d3661ac928bff2a55190a7ba44abacf63c7b246d92ea107c

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.3.2-cp39-cp39-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 5394d3f10afb0186646dcc5b9d62784ad7d2ea44b7065cc4271e3326bcfab109
MD5 0b07f28b70558228dca4b72a7251ab07
BLAKE2b-256 70435866560cf6e09333be6f87f83cb83e2425d52c839f03f35ba22b61280191

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for graph_layout-0.3.2-cp39-cp39-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 d500d51377fcb9afed9ecc4ae91c094eca9a80bbd7f38353759e21bc685a9d84
MD5 db52e31d8e32afddb40fef80ad7f735f
BLAKE2b-256 0c451c2d4ff5dc63129b7170f61ecc55afd45b2751c0138d867ffc3bfd129406

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