Skip to content

Commit

Permalink
tagged with crumb
Browse files Browse the repository at this point in the history
  • Loading branch information
scottvr committed Jan 14, 2025
1 parent 8682b32 commit be93bb6
Show file tree
Hide file tree
Showing 16 changed files with 2,418 additions and 2,402 deletions.
199 changes: 100 additions & 99 deletions examples/chess_masters.py
Original file line number Diff line number Diff line change
@@ -1,99 +1,100 @@
"""
World Chess Championship visualization example.
This example demonstrates PHART's ability to handle complex real-world graphs
by visualizing World Chess Championship games from 1886-1985.
Data source: https://chessproblem.my-free-games.com/chess/games/Download-PGN.php
Original example adapted from NetworkX gallery:
https://networkx.org/documentation/latest/auto_examples/drawing/plot_chess_masters.html
"""

import bz2
from pathlib import Path
import networkx as nx
from phart import ASCIIRenderer, NodeStyle

# Tag names specifying game info to store in edge data
GAME_DETAILS = ["Event", "Date", "Result", "ECO", "Site"]


def load_chess_games(pgn_file="WCC.pgn.bz2") -> nx.MultiDiGraph:
"""
Read chess games in PGN format.
Parameters
----------
pgn_file : str
Path to PGN file (can be bz2 compressed)
Returns
-------
NetworkX MultiDiGraph
Graph where nodes are players and edges represent games
"""
G = nx.MultiDiGraph()
game = {}

with bz2.BZ2File(pgn_file) as datafile:
lines = [line.decode().rstrip("\r\n") for line in datafile]

for line in lines:
if line.startswith("["):
tag, value = line[1:-1].split(" ", 1)
game[str(tag)] = value.strip('"')
else:
# Empty line after tag set indicates end of game info
if game:
white = game.pop("White")
black = game.pop("Black")
G.add_edge(white, black, **game)
game = {}
return G


def main():
# Check if data file exists
data_file = Path(__file__).parent / "WCC.pgn.bz2"
if not data_file.exists():
print(f"Please download WCC.pgn.bz2 to {data_file}")
print(
"from: https://chessproblem.my-free-games.com/chess/games/Download-PGN.php"
)
return

# Load and analyze the data
G = load_chess_games(data_file)
print(
f"Loaded {G.number_of_edges()} chess games between {G.number_of_nodes()} players\n"
)

# Convert to undirected graph for visualization
H = nx.Graph(G)

# Create ASCII visualization
renderer = ASCIIRenderer(
H,
node_style=NodeStyle.SQUARE, # Square brackets for player names
node_spacing=4, # Space between nodes
layer_spacing=1, # Compact vertical spacing
)

# Save to file and display
renderer.write_to_file("chess_masters.txt")
print(renderer.render())

# Print some interesting statistics
print("\nMost frequent openings:")
openings = {}
for _, _, game_info in G.edges(data=True):
if "ECO" in game_info:
eco = game_info["ECO"]
openings[eco] = openings.get(eco, 0) + 1

for eco, count in sorted(openings.items(), key=lambda x: x[1], reverse=True)[:5]:
print(f"ECO {eco}: {count} games")


if __name__ == "__main__":
main()
"""
World Chess Championship visualization example.
This example demonstrates PHART's ability to handle complex real-world graphs
by visualizing World Chess Championship games from 1886-1985.
Data source: https://chessproblem.my-free-games.com/chess/games/Download-PGN.php
Original example adapted from NetworkX gallery:
https://networkx.org/documentation/latest/auto_examples/drawing/plot_chess_masters.html
"""
# src path: examples\chess_masters.py

import bz2
from pathlib import Path
import networkx as nx
from phart import ASCIIRenderer, NodeStyle

# Tag names specifying game info to store in edge data
GAME_DETAILS = ["Event", "Date", "Result", "ECO", "Site"]


def load_chess_games(pgn_file="WCC.pgn.bz2") -> nx.MultiDiGraph:
"""
Read chess games in PGN format.
Parameters
----------
pgn_file : str
Path to PGN file (can be bz2 compressed)
Returns
-------
NetworkX MultiDiGraph
Graph where nodes are players and edges represent games
"""
G = nx.MultiDiGraph()
game = {}

with bz2.BZ2File(pgn_file) as datafile:
lines = [line.decode().rstrip("\r\n") for line in datafile]

for line in lines:
if line.startswith("["):
tag, value = line[1:-1].split(" ", 1)
game[str(tag)] = value.strip('"')
else:
# Empty line after tag set indicates end of game info
if game:
white = game.pop("White")
black = game.pop("Black")
G.add_edge(white, black, **game)
game = {}
return G


def main():
# Check if data file exists
data_file = Path(__file__).parent / "WCC.pgn.bz2"
if not data_file.exists():
print(f"Please download WCC.pgn.bz2 to {data_file}")
print(
"from: https://chessproblem.my-free-games.com/chess/games/Download-PGN.php"
)
return

# Load and analyze the data
G = load_chess_games(data_file)
print(
f"Loaded {G.number_of_edges()} chess games between {G.number_of_nodes()} players\n"
)

# Convert to undirected graph for visualization
H = nx.Graph(G)

# Create ASCII visualization
renderer = ASCIIRenderer(
H,
node_style=NodeStyle.SQUARE, # Square brackets for player names
node_spacing=4, # Space between nodes
layer_spacing=1, # Compact vertical spacing
)

# Save to file and display
renderer.write_to_file("chess_masters.txt")
print(renderer.render())

# Print some interesting statistics
print("\nMost frequent openings:")
openings = {}
for _, _, game_info in G.edges(data=True):
if "ECO" in game_info:
eco = game_info["ECO"]
openings[eco] = openings.get(eco, 0) + 1

for eco, count in sorted(openings.items(), key=lambda x: x[1], reverse=True)[:5]:
print(f"ECO {eco}: {count} games")


if __name__ == "__main__":
main()
149 changes: 75 additions & 74 deletions examples/dependency_tree.py
Original file line number Diff line number Diff line change
@@ -1,74 +1,75 @@
"""
Example of using PHART to visualize package dependencies.
"""

import networkx as nx
from phart import ASCIIRenderer, NodeStyle


def create_sample_dependencies():
"""Create a sample package dependency graph."""
G = nx.DiGraph()

# Main package dependencies
dependencies = {
"my-app": ["flask", "sqlalchemy", "celery"],
"flask": ["werkzeug", "jinja2", "click"],
"sqlalchemy": ["greenlet"],
"celery": ["click", "redis"],
"jinja2": ["markupsafe"],
}

# Add all edges
for package, deps in dependencies.items():
for dep in deps:
G.add_edge(package, dep)

return G


def create_circular_deps():
"""Create a dependency graph with circular references."""
G = nx.DiGraph()

# Circular dependency example
dependencies = {
"package_a": ["package_b", "requests"],
"package_b": ["package_c"],
"package_c": ["package_a"], # Creates cycle
"requests": ["urllib3", "certifi"],
}

for package, deps in dependencies.items():
for dep in deps:
G.add_edge(package, dep)

return G


def main():
print("Package Dependency Examples")
print("=========================")

# Simple dependency tree
print("\nTypical Package Dependencies:")
G = create_sample_dependencies()
renderer = ASCIIRenderer(G, node_style=NodeStyle.MINIMAL)
print(renderer.render())

# Circular dependencies
print("\nCircular Dependencies:")
G = create_circular_deps()
renderer = ASCIIRenderer(G)
print(renderer.render())

# Detect and print cycles
cycles = list(nx.simple_cycles(G))
if cycles:
print("\nDetected dependency cycles:")
for cycle in cycles:
print(" -> ".join(cycle + [cycle[0]]))


if __name__ == "__main__":
main()
"""
Example of using PHART to visualize package dependencies.
"""
# src path: examples\dependency_tree.py

import networkx as nx
from phart import ASCIIRenderer, NodeStyle


def create_sample_dependencies():
"""Create a sample package dependency graph."""
G = nx.DiGraph()

# Main package dependencies
dependencies = {
"my-app": ["flask", "sqlalchemy", "celery"],
"flask": ["werkzeug", "jinja2", "click"],
"sqlalchemy": ["greenlet"],
"celery": ["click", "redis"],
"jinja2": ["markupsafe"],
}

# Add all edges
for package, deps in dependencies.items():
for dep in deps:
G.add_edge(package, dep)

return G


def create_circular_deps():
"""Create a dependency graph with circular references."""
G = nx.DiGraph()

# Circular dependency example
dependencies = {
"package_a": ["package_b", "requests"],
"package_b": ["package_c"],
"package_c": ["package_a"], # Creates cycle
"requests": ["urllib3", "certifi"],
}

for package, deps in dependencies.items():
for dep in deps:
G.add_edge(package, dep)

return G


def main():
print("Package Dependency Examples")
print("=========================")

# Simple dependency tree
print("\nTypical Package Dependencies:")
G = create_sample_dependencies()
renderer = ASCIIRenderer(G, node_style=NodeStyle.MINIMAL)
print(renderer.render())

# Circular dependencies
print("\nCircular Dependencies:")
G = create_circular_deps()
renderer = ASCIIRenderer(G)
print(renderer.render())

# Detect and print cycles
cycles = list(nx.simple_cycles(G))
if cycles:
print("\nDetected dependency cycles:")
for cycle in cycles:
print(" -> ".join(cycle + [cycle[0]]))


if __name__ == "__main__":
main()
Loading

0 comments on commit be93bb6

Please sign in to comment.