File size: 5,312 Bytes
00ba522 6fc15fa 00ba522 e2d8c14 00ba522 e2d8c14 00ba522 e2d8c14 00ba522 6fc15fa e2d8c14 00ba522 e2d8c14 00ba522 6fc15fa 00ba522 e2d8c14 00ba522 6fc15fa e2d8c14 00ba522 e2d8c14 00ba522 e2d8c14 00ba522 e2d8c14 00ba522 e2d8c14 00ba522 e2d8c14 00ba522 e2d8c14 00ba522 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
import graphviz
import json
from tempfile import NamedTemporaryFile
import os
from graph_generator_utils import add_nodes_and_edges # Reusing common utility
def generate_process_flow_diagram(json_input: str, base_color: str) -> str: # base_color is now correctly used
"""
Generates a Process Flow Diagram (Flowchart) from JSON input.
Args:
json_input (str): A JSON string describing the process flow structure.
It must follow the Expected JSON Format Example below.
base_color (str): The hexadecimal color string (e.g., '#19191a') for the base
color of the nodes, from which a gradient will be generated.
Returns:
str: The filepath to the generated PNG image file.
Expected JSON Format Example:
{
"start_node": "Start Process",
"nodes": [
{
"id": "step1",
"label": "Gather Requirements",
"type": "process",
"relationship": "Next"
},
{
"id": "decision1",
"label": "Is Data Available?",
"type": "decision",
"relationship": "Check"
},
{
"id": "path_yes",
"label": "Process Data",
"type": "process",
"relationship": "Yes"
},
{
"id": "path_no",
"label": "Collect More Data",
"type": "process",
"relationship": "No"
},
{
"id": "end_node",
"label": "End Process",
"type": "end"
}
],
"connections": [
{"from": "start_node", "to": "step1", "label": "Initiate"},
{"from": "step1", "to": "decision1", "label": "Continue"},
{"from": "decision1", "to": "path_yes", "label": "Yes"},
{"from": "decision1", "to": "path_no", "label": "No"},
{"from": "path_yes", "to": "end_node", "label": "Done"},
{"from": "path_no", "to": "end_node", "label": "Done"}
]
}
"""
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='ProcessFlowDiagram',
format='png',
graph_attr={
'rankdir': 'TB', # Top-to-Bottom flow is common for flowcharts
'splines': 'ortho', # Straight lines with 90-degree bends
'bgcolor': 'white', # White background
'pad': '0.5', # Padding around the graph
'nodesep': '0.6', # Spacing between nodes on same rank
'ranksep': '0.8' # Spacing between ranks
}
)
# This line was REMOVED to ensure the passed base_color is used: base_color = '#19191a'
# Determine specific node shapes for flowchart types
node_shapes = {
"process": "box", # Rectangle for processes
"decision": "diamond", # Diamond for decisions
"start": "oval", # Oval for start
"end": "oval", # Oval for end
"io": "parallelogram", # Input/Output
"document": "note", # Document symbol
"default": "box" # Fallback
}
# Add all nodes based on JSON structure
all_nodes_data = {}
# Special handling for start_node if defined separately
if 'start_node' in data:
all_nodes_data[data['start_node']] = {"label": data['start_node'], "type": "start"}
for node_data in data.get('nodes', []):
all_nodes_data[node_data['id']] = node_data
for node_id, node_info in all_nodes_data.items():
node_type = node_info.get("type", "default")
shape = node_shapes.get(node_type, "box") # Default to box if type is unknown
# Use base_color for all nodes for consistent flowchart look
fill_color_for_node = base_color
font_color_for_node = 'white' if base_color == '#19191a' else 'black' # Keep text readable
dot.node(
node_id,
node_info['label'],
shape=shape,
style='filled,rounded', # Keep rounded corners
fillcolor=fill_color_for_node,
fontcolor=font_color_for_node,
fontsize='14'
)
# Add connections (edges)
for connection in data.get('connections', []):
dot.edge(
connection['from'],
connection['to'],
label=connection.get('label', ''),
color='#4a4a4a', # Dark gray for lines
fontcolor='#4a4a4a',
fontsize='10'
)
# 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)}"
|