| import graphviz | |
| import json | |
| from tempfile import NamedTemporaryFile | |
| import os | |
| from graph_generator_utils import add_nodes_and_edges | |
| def generate_synoptic_chart(json_input: str) -> str: | |
| """ | |
| Generates a synoptic chart (horizontal flowchart) from JSON input. | |
| """ | |
| try: | |
| if not json_input.strip(): | |
| return "Error: Empty input" | |
| data = json.loads(json_input) | |
| if 'central_node' not in data or 'nodes' not in data: | |
| raise ValueError("Missing required fields: central_node or nodes") | |
| dot = graphviz.Digraph( | |
| name='SynopticChart', | |
| format='png', | |
| graph_attr={ | |
| 'rankdir': 'LR', # Left-to-Right layout (horizontal hierarchy) | |
| 'splines': 'ortho', # Straight lines | |
| 'bgcolor': 'white', # White background | |
| 'pad': '0.5', # Padding around the graph | |
| 'ranksep': '0.7', # Reduced horizontal separation between ranks (columns) | |
| 'nodesep': '0.3' # Adjusted vertical separation between nodes in the same rank | |
| } | |
| ) | |
| base_color = '#19191a' # Base color for the central node and gradient | |
| # Central node styling (rounded box, dark color) | |
| dot.node( | |
| 'central', | |
| data['central_node'], | |
| shape='box', # Rectangular shape | |
| style='filled,rounded', # Filled and rounded corners | |
| fillcolor=base_color, # Darkest color | |
| fontcolor='white', # White text for dark background | |
| fontsize='16' # Larger font for central node | |
| ) | |
| # Add child nodes and edges recursively starting from depth 1 | |
| add_nodes_and_edges(dot, 'central', data.get('nodes', []), current_depth=1, base_color=base_color) | |
| # Save to temporary file | |
| with NamedTemporaryFile(delete=False, suffix='.png') as tmp: | |
| dot.render(tmp.name, format='png', cleanup=True) | |
| return tmp.name + '.png' | |
| except json.JSONDecodeError: | |
| return "Error: Invalid JSON format" | |
| except Exception as e: | |
| return f"Error: {str(e)}" | |