ashhal commited on
Commit
f742cf9
·
verified ·
1 Parent(s): 20f2352

Create utils/diagram_generator.py

Browse files
Files changed (1) hide show
  1. utils/diagram_generator.py +145 -0
utils/diagram_generator.py ADDED
@@ -0,0 +1,145 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Diagram Generation Utilities for Power Systems
3
+ Generates SVG diagrams for power system concepts
4
+ """
5
+
6
+ import json
7
+ from typing import Dict, List, Tuple, Optional
8
+ from datetime import datetime
9
+
10
+ class DiagramGenerator:
11
+ """
12
+ Generate SVG diagrams for power systems concepts
13
+ """
14
+
15
+ def __init__(self):
16
+ self.svg_width = 800
17
+ self.svg_height = 600
18
+ self.grid_size = 20
19
+
20
+ def create_svg_header(self, width: int = None, height: int = None) -> str:
21
+ """Create SVG header with proper dimensions"""
22
+ w = width or self.svg_width
23
+ h = height or self.svg_height
24
+
25
+ return f"""<svg width="{w}" height="{h}" viewBox="0 0 {w} {h}" xmlns="http://www.w3.org/2000/svg">
26
+ <defs>
27
+ <style>
28
+ .line {{ stroke: #2563eb; stroke-width: 2; fill: none; }}
29
+ .bus {{ stroke: #dc2626; stroke-width: 4; }}
30
+ .text {{ font-family: Arial, sans-serif; font-size: 12px; fill: #374151; }}
31
+ .title {{ font-family: Arial, sans-serif; font-size: 16px; font-weight: bold; fill: #1f2937; }}
32
+ .component {{ stroke: #059669; stroke-width: 2; fill: #d1fae5; }}
33
+ .fault {{ stroke: #dc2626; stroke-width: 3; fill: #fecaca; }}
34
+ .protection {{ stroke: #7c3aed; stroke-width: 2; fill: #e9d5ff; }}
35
+ .ground {{ stroke: #374151; stroke-width: 2; }}
36
+ </style>
37
+
38
+ <!-- Marker definitions for arrows -->
39
+ <marker id="arrowhead" markerWidth="10" markerHeight="7"
40
+ refX="9" refY="3.5" orient="auto">
41
+ <polygon points="0 0, 10 3.5, 0 7" fill="#2563eb" />
42
+ </marker>
43
+
44
+ <!-- Component symbols -->
45
+ <g id="generator">
46
+ <circle cx="0" cy="0" r="15" class="component"/>
47
+ <text x="0" y="4" text-anchor="middle" class="text">G</text>
48
+ </g>
49
+
50
+ <g id="transformer">
51
+ <circle cx="-10" cy="0" r="8" class="component"/>
52
+ <circle cx="10" cy="0" r="8" class="component"/>
53
+ <text x="0" y="25" text-anchor="middle" class="text">T</text>
54
+ </g>
55
+
56
+ <g id="load">
57
+ <path d="M-10,-10 L10,-10 L5,10 L-5,10 Z" class="component"/>
58
+ <text x="0" y="25" text-anchor="middle" class="text">Load</text>
59
+ </g>
60
+
61
+ <g id="fault-symbol">
62
+ <circle cx="0" cy="0" r="8" class="fault"/>
63
+ <line x1="-6" y1="-6" x2="6" y2="6" class="fault"/>
64
+ <line x1="-6" y1="6" x2="6" y2="-6" class="fault"/>
65
+ </g>
66
+ </defs>
67
+ """
68
+
69
+ def create_svg_footer(self) -> str:
70
+ """Create SVG footer"""
71
+ return "</svg>"
72
+
73
+ def generate_single_line_diagram(self, system_config: Dict) -> str:
74
+ """Generate a single line diagram"""
75
+ svg = self.create_svg_header()
76
+
77
+ # Title
78
+ svg += f'<text x="400" y="30" text-anchor="middle" class="title">Single Line Diagram</text>\n'
79
+
80
+ # Main bus (horizontal line)
81
+ svg += f'<line x1="100" y1="100" x2="700" y2="100" class="bus"/>\n'
82
+ svg += f'<text x="400" y="85" text-anchor="middle" class="text">Main Bus (33kV)</text>\n'
83
+
84
+ # Generator
85
+ svg += f'<use href="#generator" transform="translate(150,100)"/>\n'
86
+ svg += f'<line x1="135" y1="100" x2="100" y2="100" class="line"/>\n'
87
+ svg += f'<text x="150" y="140" text-anchor="middle" class="text">Generator</text>\n'
88
+ svg += f'<text x="150" y="155" text-anchor="middle" class="text">100MVA</text>\n'
89
+
90
+ # Transformer
91
+ svg += f'<use href="#transformer" transform="translate(300,100)"/>\n'
92
+ svg += f'<line x1="290" y1="100" x2="250" y2="100" class="line"/>\n'
93
+ svg += f'<line x1="310" y1="100" x2="350" y2="100" class="line"/>\n'
94
+ svg += f'<text x="300" y="140" text-anchor="middle" class="text">Power Transformer</text>\n'
95
+ svg += f'<text x="300" y="155" text-anchor="middle" class="text">33/11kV, 50MVA</text>\n'
96
+
97
+ # Distribution lines
98
+ svg += f'<line x1="400" y1="100" x2="400" y2="200" class="line"/>\n'
99
+ svg += f'<line x1="350" y1="200" x2="450" y2="200" class="line"/>\n'
100
+ svg += f'<text x="400" y="215" text-anchor="middle" class="text">Distribution Bus (11kV)</text>\n'
101
+
102
+ # Loads
103
+ positions = [375, 425]
104
+ load_names = ["Industrial Load", "Commercial Load"]
105
+ load_powers = ["15MW", "8MW"]
106
+
107
+ for i, (pos, name, power) in enumerate(zip(positions, load_names, load_powers)):
108
+ svg += f'<use href="#load" transform="translate({pos},250)"/>\n'
109
+ svg += f'<line x1="{pos}" y1="200" x2="{pos}" y2="240" class="line"/>\n'
110
+ svg += f'<text x="{pos}" y="285" text-anchor="middle" class="text">{name}</text>\n'
111
+ svg += f'<text x="{pos}" y="300" text-anchor="middle" class="text">{power}</text>\n'
112
+
113
+ # Protection devices
114
+ svg += f'<rect x="195" y="95" width="10" height="10" class="protection"/>\n'
115
+ svg += f'<text x="200" y="120" text-anchor="middle" class="text">CB1</text>\n'
116
+
117
+ svg += f'<rect x="345" y="95" width="10" height="10" class="protection"/>\n'
118
+ svg += f'<text x="350" y="120" text-anchor="middle" class="text">CB2</text>\n'
119
+
120
+ # Legend
121
+ svg += f'<text x="50" y="450" class="title">Legend:</text>\n'
122
+ svg += f'<line x1="50" y1="470" x2="80" y2="470" class="bus"/>\n'
123
+ svg += f'<text x="90" y="475" class="text">Bus</text>\n'
124
+ svg += f'<line x1="50" y1="490" x2="80" y2="490" class="line"/>\n'
125
+ svg += f'<text x="90" y="495" class="text">Transmission Line</text>\n'
126
+ svg += f'<rect x="50" y="505" width="10" height="10" class="protection"/>\n'
127
+ svg += f'<text x="70" y="515" class="text">Circuit Breaker</text>\n'
128
+
129
+ svg += self.create_svg_footer()
130
+ return svg
131
+
132
+ def generate_fault_analysis_diagram(self, fault_type: str = "line_to_ground") -> str:
133
+ """Generate fault analysis diagram with sequence networks"""
134
+ svg = self.create_svg_header(900, 700)
135
+
136
+ # Title
137
+ svg += f'<text x="450" y="30" text-anchor="middle" class="title">Fault Analysis - {fault_type.replace("_", " ").title()}</text>\n'
138
+
139
+ if fault_type == "line_to_ground":
140
+ # Positive sequence network
141
+ svg += f'<text x="150" y="80" text-anchor="middle" class="title">Positive Sequence</text>\n'
142
+ svg += self._draw_sequence_network(150, 100, "Z1", "#059669")
143
+
144
+ # Negative sequence network
145
+ svg += f'<text x="450" y="80" text-anchor="middle" class="