Skip to main content

A graph maker for computational geometry and network visualization

Project description

Graphizy

A powerful graph maker for computational geometry and network visualization, specializing in multiple graph types and memory-enhanced analysis.

Detection to Graph

Figure: Positions are converted to graphs in just a few milliseconds for hundreds of individuals using OpenCV.
Graph analytics are accessible in real time by interfacing with igraph.

🎯 Key Features

📊 Graph Construction Types

  • 🔺 Delaunay Triangulation: Optimal triangular meshes from point sets
  • 📡 Proximity Graphs: Connect nearby points based on distance thresholds
  • 🔗 K-Nearest Neighbors: Connect each point to its k closest neighbors
  • 🌲 Minimum Spanning Tree: Minimal connected graph with shortest total edge length
  • 🔵 Gabriel Graph: Geometric proximity graph (subset of Delaunay triangulation)
  • 🧠 Memory-Enhanced Graphs: Any graph type + historical connection tracking

🧮 Graph Analysis

  • igraph Integration: Full access to igraph's powerful analytics
  • Comprehensive API: Call any igraph method with error handling
  • Real-time Statistics: Vertex count, edge count, connectivity, clustering, centrality

🎨 Visualization & Design

  • Flexible Configuration: Runtime-configurable parameters using dataclasses
  • Multiple Output Formats: Save as images or display interactively with OpenCV
  • Memory Visualization: Age-based edge coloring for temporal analysis
  • Command Line Interface: Easy-to-use CLI for common operations
  • Interactive Demos: Real-time Brownian motion simulation with graph evolution

🔧 Technical Excellence

  • Robust Error Handling: Detailed exceptions and validation
  • Performance Monitoring: Built-in timing and optimization tracking
  • Memory Management: Configurable connection history with aging
  • Type Safety: Full type hints and dataclass configuration

🚀 Installation

pip install graphizy

Or for development:

git clone https://github.com/cfosseprez/graphizy.git
cd graphizy
pip install -e .

⚡ Quick Start

Basic Graph Creation

import numpy as np
from graphizy import Graphing, GraphizyConfig, generate_positions

# Generate random points
positions = generate_positions(800, 800, 100)
particle_ids = np.arange(len(positions))
data = np.column_stack((particle_ids, positions))

# Create grapher with configuration
config = GraphizyConfig()
config.graph.dimension = (800, 800)
grapher = Graphing(config=config)

# Create different graph types
delaunay_graph = grapher.make_delaunay(data)
proximity_graph = grapher.make_proximity(data, proximity_thresh=50.0)
knn_graph = grapher.make_knn(data, k=4)  # Connect to 4 nearest neighbors
mst_graph = grapher.make_mst(data)       # Minimum spanning tree
gabriel_graph = grapher.make_gabriel(data)  # Gabriel graph

# Visualize and save
delaunay_image = grapher.draw_graph(delaunay_graph)
grapher.save_graph(delaunay_image, "delaunay.jpg")
# Or display interactively
grapher.show_graph(delaunay_image, "Delaunay Triangulation")

# Get comprehensive statistics
info = grapher.get_graph_info(delaunay_graph)
print(f"Graph: {info['vertex_count']} vertices, {info['edge_count']} edges")
print(f"Density: {info['density']:.3f}, Connected: {info['is_connected']}")

🧠 Memory-Enhanced Graphs

Memory graphs track connections over time, allowing analysis of temporal patterns:

# Initialize memory manager
grapher.init_memory_manager(max_memory_size=50, track_edge_ages=True)

# Simulate evolution over time
for iteration in range(100):
    # Update positions (e.g., particle movement)
    data[:, 1:3] += np.random.normal(0, 2, (len(data), 2))
    
    # Create current graph and update memory
    current_graph = grapher.make_proximity(data, proximity_thresh=60.0)
    grapher.update_memory_with_graph(current_graph)
    
    # Create memory-enhanced graph (current + historical connections)
    memory_graph = grapher.make_memory_graph(data)
    
    # Visualize with age-based coloring
    if iteration % 10 == 0:
        memory_image = grapher.draw_memory_graph(
            memory_graph, 
            use_age_colors=True,  # Older connections fade out
            alpha_range=(0.3, 1.0)
        )
        grapher.save_graph(memory_image, f"memory_frame_{iteration:03d}.jpg")

# Get memory statistics
stats = grapher.get_memory_stats()
print(f"Memory contains {stats['total_connections']} historical connections")
print(f"Average edge age: {stats['edge_age_stats']['avg_age']:.1f} iterations")

📊 Graph Types Comparison

Graph Type Connectivity Edge Count Use Case Memory Compatible
Proximity Variable ~distance² Local neighborhoods
Delaunay Always ~3n Natural triangulation
K-NN Variable k×n Fixed degree networks
MST Always n-1 Minimal connectivity
Gabriel Variable Subset of Delaunay Geometric proximity
Memory Variable Historical Temporal analysis -

🎮 Interactive Demo

Experience real-time graph evolution with the interactive Brownian motion simulator:

# Basic proximity graph simulation
python examples/improved_brownian.py 1

# Delaunay triangulation with memory tracking
python examples/improved_brownian.py 2 --memory

# Minimum spanning tree evolution
python examples/improved_brownian.py 4 --memory --particles 100

# Compare all graph types side-by-side
python examples/improved_brownian.py 5 --memory

# Interactive controls:
# ESC - Exit, SPACE - Pause, R - Reset, M - Toggle memory
# 1-5 - Switch graph types, +/- - Adjust memory size

⚙️ Configuration

Graphizy uses dataclasses for type-safe, runtime-configurable parameters:

from graphizy import GraphizyConfig

# Create and customize configuration
config = GraphizyConfig()

# Drawing configuration
config.drawing.line_color = (255, 0, 0)  # Red lines (B, G, R)
config.drawing.point_color = (0, 255, 255)  # Yellow points  
config.drawing.line_thickness = 3
config.drawing.point_radius = 12

# Graph configuration
config.graph.dimension = (1200, 800)
config.graph.proximity_threshold = 75.0
config.graph.distance_metric = "euclidean"  # or "manhattan", "chebyshev"

# Memory configuration
config.memory.max_memory_size = 100
config.memory.auto_update_from_proximity = True

# Create grapher with custom config
grapher = Graphing(config=config)

# Runtime configuration updates
grapher.update_config(
    drawing={"line_thickness": 5},
    graph={"proximity_threshold": 100.0}
)

🔬 Advanced Analysis

Graph Metrics and Centrality

# Basic graph properties
info = grapher.get_graph_info(graph)
print(f"Density: {info['density']:.3f}")
print(f"Average path length: {info['average_path_length']:.2f}")
print(f"Clustering coefficient: {info['transitivity']:.3f}")

# Node centrality measures
degree_centrality = grapher.call_method(graph, 'degree')
betweenness = grapher.call_method(graph, 'betweenness')
closeness = grapher.call_method(graph, 'closeness')

# Find most central nodes
central_nodes = sorted(betweenness.items(), key=lambda x: x[1], reverse=True)[:5]
print(f"Top 5 central nodes: {central_nodes}")

# Direct igraph access for advanced analysis
components = grapher.call_method_raw(graph, 'connected_components')
diameter = grapher.call_method_raw(graph, 'diameter')

Custom Graph Types

# Create custom connection function
def create_distance_band_graph(positions, inner_radius=30, outer_radius=80):
    """Connect points within a distance band (ring)"""
    from scipy.spatial.distance import pdist, squareform
    
    graph = grapher.make_proximity(positions, proximity_thresh=float('inf'))
    graph.delete_edges(graph.es)  # Start empty
    
    distances = squareform(pdist(positions[:, 1:3]))
    edges = []
    
    for i in range(len(positions)):
        for j in range(i+1, len(positions)):
            dist = distances[i, j]
            if inner_radius <= dist <= outer_radius:
                edges.append((i, j))
    
    if edges:
        graph.add_edges(edges)
    return graph

# Use with memory system
custom_graph = create_distance_band_graph(data, 40, 100)
grapher.update_memory_with_graph(custom_graph)

📚 API Reference

Main Classes

  • Graphing: Primary interface for graph creation and analysis
  • GraphizyConfig: Type-safe configuration management
  • MemoryManager: Historical connection tracking
  • DataInterface: Flexible data format handling

Graph Creation Methods

  • make_delaunay(data): Delaunay triangulation
  • make_proximity(data, proximity_thresh, metric): Distance-based connections
  • make_knn(data, k): K-nearest neighbors (requires scipy)
  • make_mst(data, metric): Minimum spanning tree
  • make_gabriel(data): Gabriel graph
  • make_memory_graph(data): Memory-enhanced graph

Memory Management

  • init_memory_manager(max_size, max_iterations, track_ages): Initialize memory
  • update_memory_with_graph(graph): Add graph connections to memory
  • update_memory_with_proximity(data, threshold): Add proximity connections
  • get_memory_stats(): Memory usage statistics

Visualization

  • draw_graph(graph, radius, thickness): Standard graph drawing
  • draw_memory_graph(graph, use_age_colors, alpha_range): Memory visualization
  • show_graph(image, title): Interactive display
  • save_graph(image, filename): Save to file

🧪 Examples

Batch Analysis

# Analyze multiple datasets
results = []
for size in [50, 100, 200, 500]:
    positions = generate_positions(800, 800, size)
    data = np.column_stack((np.arange(size), positions))
    
    # Compare graph types
    for graph_type, create_func in [
        ('delaunay', lambda d: grapher.make_delaunay(d)),
        ('proximity', lambda d: grapher.make_proximity(d, 60)),
        ('mst', lambda d: grapher.make_mst(d)),
        ('gabriel', lambda d: grapher.make_gabriel(d))
    ]:
        graph = create_func(data)
        info = grapher.get_graph_info(graph)
        results.append({
            'size': size,
            'type': graph_type,
            'density': info['density'],
            'avg_path_length': info['average_path_length']
        })

# Analyze results
import pandas as pd
df = pd.DataFrame(results)
print(df.groupby('type')['density'].mean())

Time Series Analysis

# Track graph evolution over time
time_series = []
grapher.init_memory_manager(max_memory_size=200)

for t in range(500):
    # Simulate system evolution  
    data[:, 1:3] += np.random.normal(0, 1, (len(data), 2))
    
    # Create snapshot
    current_graph = grapher.make_delaunay(data)
    grapher.update_memory_with_graph(current_graph)
    
    # Record metrics
    info = grapher.get_graph_info(current_graph)
    memory_stats = grapher.get_memory_stats()
    
    time_series.append({
        'time': t,
        'current_edges': info['edge_count'],
        'memory_edges': memory_stats['total_connections'],
        'clustering': info['transitivity']
    })

# Visualize time series
import matplotlib.pyplot as plt
ts_df = pd.DataFrame(time_series)
ts_df.plot(x='time', y=['current_edges', 'memory_edges'])
plt.title('Graph Evolution Over Time')
plt.show()

🔧 Development

Requirements

  • Python >= 3.8
  • NumPy >= 1.20.0
  • OpenCV >= 4.5.0
  • python-igraph >= 0.9.0
  • SciPy >= 1.7.0 (for KNN and MST)

Running Tests

# Install development dependencies
pip install pytest pytest-cov black flake8

# Run tests with coverage
pytest tests/ --cov=graphizy --cov-report=html

# Test specific functionality
python test_mst.py          # Test MST functionality
python test_fixes.py        # Test configuration fixes

Code Quality

# Format code
black src/

# Lint code  
flake8 src/

# Type checking (if mypy installed)
mypy src/graphizy/

📄 License

GPL-2.0-or-later License - see LICENSE file for details.

🤝 Contributing

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Add tests for new functionality
  4. Ensure all tests pass (pytest tests/)
  5. Commit changes (git commit -m 'Add amazing feature')
  6. Push to branch (git push origin feature/amazing-feature)
  7. Open a Pull Request

👨‍💻 Author

Charles Fosseprez
📧 Email: charles.fosseprez.pro@gmail.com
🐙 GitHub: @cfosseprez

📈 Changelog

v0.1.4 (Current)

  • ✨ Added Minimum Spanning Tree (MST) graph type
  • ✨ Added K-Nearest Neighbors (KNN) graph type
  • 🧠 Enhanced memory system with age-based visualization
  • 🎮 Interactive Brownian motion simulator
  • 🐛 Fixed configuration initialization issues
  • 📚 Comprehensive documentation improvements
  • ✅ Added MST and memory functionality tests

v0.1.0

  • 🎉 Initial release
  • 🔺 Delaunay triangulation support
  • 📡 Proximity graph creation
  • ⚙️ Configurable drawing parameters
  • 🖥️ Command line interface
  • ✅ Comprehensive test suite
  • 🛡️ Error handling and validation

Built with ❤️ for computational geometry and network analysis

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

graphizy-0.1.5.tar.gz (67.8 kB view details)

Uploaded Source

Built Distribution

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

graphizy-0.1.5-py3-none-any.whl (43.5 kB view details)

Uploaded Python 3

File details

Details for the file graphizy-0.1.5.tar.gz.

File metadata

  • Download URL: graphizy-0.1.5.tar.gz
  • Upload date:
  • Size: 67.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.1.3 CPython/3.9.13 Windows/10

File hashes

Hashes for graphizy-0.1.5.tar.gz
Algorithm Hash digest
SHA256 3cf773e13ede05ea029446d0e8c3f9a1fb727fb29c55e08a846fe29859f43b5e
MD5 cc7ef3b14e05c06dbcebbf804c7e0e92
BLAKE2b-256 7210e21048870a9a1e85610579470e4fa8653e99d31709c5aec3301328a63807

See more details on using hashes here.

File details

Details for the file graphizy-0.1.5-py3-none-any.whl.

File metadata

  • Download URL: graphizy-0.1.5-py3-none-any.whl
  • Upload date:
  • Size: 43.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.1.3 CPython/3.9.13 Windows/10

File hashes

Hashes for graphizy-0.1.5-py3-none-any.whl
Algorithm Hash digest
SHA256 70918aeda77ea8f9e42de93f4c14bd00bd5bc2bd2de1fdbba45d21e808731039
MD5 fd279231a21d41e28ab5492d5c2fac1c
BLAKE2b-256 402a740f5f74ffd4fe2c6b66b708e38faa1fb974506a023985b5727fa4436b3f

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