rlogh commited on
Commit
fb8683b
·
verified ·
1 Parent(s): 6e1bcf4

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +360 -0
app.py ADDED
@@ -0,0 +1,360 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Gradio Interface for DC Circuit Analysis Calculator
3
+ A user-friendly interface for electrical engineering calculations with AI-powered result explanations.
4
+ """
5
+
6
+ import gradio as gr
7
+ import json
8
+ from circuit_calculator import Resistor, CircuitConfiguration, DCCircuitAnalyzer
9
+ import os
10
+
11
+
12
+ def explain_results(results: dict) -> str:
13
+ """
14
+ Generate a human-readable explanation of the calculation results using a simple template-based approach.
15
+ In a production environment, this would use an LLM API.
16
+ """
17
+ if results['status'] != 'success':
18
+ return f"❌ **Calculation Error**\n\n{results.get('error_message', 'Unknown error occurred')}"
19
+
20
+ # Extract key results
21
+ equivalent = results['equivalent_circuit']
22
+ series = results['series_analysis']
23
+ parallel = results['parallel_analysis']
24
+ power = results['power_analysis']
25
+ safety = results['safety_analysis']
26
+ validation = results['validation']
27
+
28
+ # Create explanation
29
+ explanation = f"""
30
+ ## ⚡ **DC Circuit Analysis Results**
31
+
32
+ ### **Key Findings:**
33
+ - **Total Resistance:** {equivalent['total_resistance_ohms']:.2f} Ω
34
+ - **Total Current:** {equivalent['total_current_A']:.3f} A
35
+ - **Total Power:** {equivalent['total_power_W']:.3f} W
36
+
37
+ ### **Circuit Safety Assessment:**
38
+ {'✅ **SAFE** - All components within ratings' if safety['all_safe'] else '⚠️ **UNSAFE** - Some components exceed ratings'}
39
+
40
+ **Power Utilization:**
41
+ - **Critical Issues:** {len(safety['critical_issues'])} component(s) exceeding power ratings
42
+ - **Warnings:** {len(safety['warnings'])} component(s) near power limits
43
+
44
+ ### **Engineering Interpretation:**
45
+
46
+ **Circuit Behavior:**
47
+ The circuit draws {equivalent['total_current_A']:.3f} A from the {results['circuit_configuration']['voltage_source_V']:.1f}V source, consuming {equivalent['total_power_W']:.3f} W total power. {'This is a safe operating condition.' if safety['all_safe'] else 'Some components may overheat and fail.'}
48
+
49
+ **Series Section Analysis:**
50
+ The series resistors (total {series['total_resistance']:.1f} Ω) carry the full circuit current of {series['total_current']:.3f} A, dissipating {series['total_power']:.3f} W total.
51
+
52
+ **Parallel Section Analysis:**
53
+ The parallel branches share the voltage drop of {parallel['voltage_across_parallel']:.2f} V. {'Each branch carries current proportional to its resistance.' if parallel['branches'] else 'No parallel branches present.'}
54
+
55
+ **Power Distribution:**
56
+ - Series section: {power['series_power']:.3f} W ({power['series_power']/power['total_power_supplied']*100:.1f}%)
57
+ - Parallel section: {power['parallel_power']:.3f} W ({power['parallel_power']/power['total_power_supplied']*100:.1f}%)
58
+ - Power balance error: {power['power_balance_error']:.6f} W
59
+
60
+ ### **Design Recommendations:**
61
+ """
62
+
63
+ # Add recommendations based on results
64
+ if not safety['all_safe']:
65
+ explanation += "\n- **CRITICAL:** Replace or reduce power in components exceeding ratings\n"
66
+ for issue in safety['critical_issues']:
67
+ explanation += f" - {issue}\n"
68
+
69
+ if safety['has_warnings']:
70
+ explanation += "\n- **WARNING:** Monitor components near power limits\n"
71
+ for warning in safety['warnings']:
72
+ explanation += f" - {warning}\n"
73
+
74
+ if safety['all_safe']:
75
+ explanation += "\n- ✅ All components operating within safe limits\n"
76
+ if power['efficiency_percent'] > 95:
77
+ explanation += "- Circuit efficiency is excellent\n"
78
+ elif power['efficiency_percent'] < 80:
79
+ explanation += "- Consider optimizing circuit for better efficiency\n"
80
+
81
+ explanation += f"""
82
+ ### **Technical Details:**
83
+ - **Circuit Efficiency:** {power['efficiency_percent']:.1f}%
84
+ - **Power Balance Error:** {power['power_balance_error']:.6f} W
85
+ - **Series Resistors:** {len(series['resistors'])} components
86
+ - **Parallel Branches:** {len(parallel['branches'])} branches
87
+
88
+ ---
89
+ *This analysis assumes ideal components and DC steady-state conditions. For AC or transient analysis, consult additional tools.*
90
+ """
91
+
92
+ return explanation
93
+
94
+
95
+ def calculate_circuit_analysis(voltage_source,
96
+ r1_resistance, r1_power_rating,
97
+ r2_resistance, r2_power_rating,
98
+ r3_resistance, r3_power_rating,
99
+ r4_resistance, r4_power_rating):
100
+ """
101
+ Main calculation function called by Gradio interface
102
+ """
103
+ try:
104
+ # Create resistors
105
+ series_resistors = [
106
+ Resistor("R1", float(r1_resistance), float(r1_power_rating)),
107
+ Resistor("R4", float(r4_resistance), float(r4_power_rating))
108
+ ]
109
+
110
+ parallel_branches = [
111
+ [Resistor("R2", float(r2_resistance), float(r2_power_rating))],
112
+ [Resistor("R3", float(r3_resistance), float(r3_power_rating))]
113
+ ]
114
+
115
+ # Create circuit configuration
116
+ config = CircuitConfiguration(
117
+ voltage_source=float(voltage_source),
118
+ series_resistors=series_resistors,
119
+ parallel_branches=parallel_branches
120
+ )
121
+
122
+ # Perform analysis
123
+ analyzer = DCCircuitAnalyzer(config)
124
+ results = analyzer.perform_analysis()
125
+
126
+ # Format numerical results
127
+ if results['status'] == 'success':
128
+ equivalent = results['equivalent_circuit']
129
+ series = results['series_analysis']
130
+ parallel = results['parallel_analysis']
131
+ power = results['power_analysis']
132
+
133
+ numerical_results = f"""
134
+ ## 📊 **Circuit Analysis Results**
135
+
136
+ ### **Equivalent Circuit:**
137
+ - **Total Resistance:** {equivalent['total_resistance_ohms']:.2f} Ω
138
+ - **Total Current:** {equivalent['total_current_A']:.3f} A
139
+ - **Total Power:** {equivalent['total_power_W']:.3f} W
140
+
141
+ ### **Series Resistors:**
142
+ - **R1:** {series['resistors'][0]['voltage_drop']:.2f}V, {series['resistors'][0]['current']:.3f}A, {series['resistors'][0]['power_dissipated']:.3f}W
143
+ - **R4:** {series['resistors'][1]['voltage_drop']:.2f}V, {series['resistors'][1]['current']:.3f}A, {series['resistors'][1]['power_dissipated']:.3f}W
144
+
145
+ ### **Parallel Branches:**
146
+ - **Branch 1 (R2):** {parallel['branches'][0]['resistors'][0]['voltage_drop']:.2f}V, {parallel['branches'][0]['resistors'][0]['current']:.3f}A, {parallel['branches'][0]['resistors'][0]['power_dissipated']:.3f}W
147
+ - **Branch 2 (R3):** {parallel['branches'][1]['resistors'][0]['voltage_drop']:.2f}V, {parallel['branches'][1]['resistors'][0]['current']:.3f}A, {parallel['branches'][1]['resistors'][0]['power_dissipated']:.3f}W
148
+
149
+ ### **Power Analysis:**
150
+ - **Series Power:** {power['series_power']:.3f} W
151
+ - **Parallel Power:** {power['parallel_power']:.3f} W
152
+ - **Efficiency:** {power['efficiency_percent']:.1f}%
153
+ """
154
+ else:
155
+ numerical_results = f"❌ **Calculation Error:** {results.get('error_message', 'Unknown error')}"
156
+
157
+ # Generate explanation
158
+ explanation = explain_results(results)
159
+
160
+ return numerical_results, explanation
161
+
162
+ except Exception as e:
163
+ error_msg = f"❌ **Error:** {str(e)}"
164
+ return error_msg, "Please check your input values and try again."
165
+
166
+
167
+ def create_interface():
168
+ """Create the Gradio interface"""
169
+
170
+ with gr.Blocks(
171
+ title="DC Circuit Analysis Calculator",
172
+ theme=gr.themes.Soft(),
173
+ css="""
174
+ .gradio-container {
175
+ max-width: 1200px !important;
176
+ }
177
+ .result-box {
178
+ background-color: #f8f9fa;
179
+ border: 1px solid #dee2e6;
180
+ border-radius: 8px;
181
+ padding: 15px;
182
+ margin: 10px 0;
183
+ }
184
+ """
185
+ ) as interface:
186
+
187
+ gr.Markdown("""
188
+ # ⚡ DC Circuit Analysis Calculator
189
+
190
+ A deterministic, first-principles calculator for series-parallel DC circuit analysis.
191
+ This tool performs electrical engineering calculations and provides AI-powered explanations of the results.
192
+
193
+ **Circuit Topology:** Voltage Source → R1 (series) → [R2, R3] (parallel) → R4 (series)
194
+
195
+ **How to use:**
196
+ 1. Enter voltage source and resistor values
197
+ 2. Click "Calculate" to perform the analysis
198
+ 3. Review numerical results and detailed explanations
199
+ """)
200
+
201
+ with gr.Row():
202
+ with gr.Column(scale=1):
203
+ gr.Markdown("### 🔋 Voltage Source")
204
+ voltage_source = gr.Number(
205
+ label="Voltage Source (V)",
206
+ value=12.0,
207
+ minimum=0.1,
208
+ maximum=1000,
209
+ step=0.1,
210
+ info="DC voltage source"
211
+ )
212
+
213
+ gr.Markdown("### 🔌 Series Resistors")
214
+ r1_resistance = gr.Number(
215
+ label="R1 Resistance (Ω)",
216
+ value=100,
217
+ minimum=1,
218
+ maximum=1000000,
219
+ step=1,
220
+ info="First series resistor"
221
+ )
222
+ r1_power_rating = gr.Number(
223
+ label="R1 Power Rating (W)",
224
+ value=0.25,
225
+ minimum=0.01,
226
+ maximum=1000,
227
+ step=0.01,
228
+ info="Power rating for R1"
229
+ )
230
+ r4_resistance = gr.Number(
231
+ label="R4 Resistance (Ω)",
232
+ value=50,
233
+ minimum=1,
234
+ maximum=1000000,
235
+ step=1,
236
+ info="Second series resistor"
237
+ )
238
+ r4_power_rating = gr.Number(
239
+ label="R4 Power Rating (W)",
240
+ value=0.5,
241
+ minimum=0.01,
242
+ maximum=1000,
243
+ step=0.01,
244
+ info="Power rating for R4"
245
+ )
246
+
247
+ gr.Markdown("### 🔀 Parallel Resistors")
248
+ r2_resistance = gr.Number(
249
+ label="R2 Resistance (Ω)",
250
+ value=200,
251
+ minimum=1,
252
+ maximum=1000000,
253
+ step=1,
254
+ info="First parallel resistor"
255
+ )
256
+ r2_power_rating = gr.Number(
257
+ label="R2 Power Rating (W)",
258
+ value=0.25,
259
+ minimum=0.01,
260
+ maximum=1000,
261
+ step=0.01,
262
+ info="Power rating for R2"
263
+ )
264
+ r3_resistance = gr.Number(
265
+ label="R3 Resistance (Ω)",
266
+ value=300,
267
+ minimum=1,
268
+ maximum=1000000,
269
+ step=1,
270
+ info="Second parallel resistor"
271
+ )
272
+ r3_power_rating = gr.Number(
273
+ label="R3 Power Rating (W)",
274
+ value=0.25,
275
+ minimum=0.01,
276
+ maximum=1000,
277
+ step=0.01,
278
+ info="Power rating for R3"
279
+ )
280
+
281
+ calculate_btn = gr.Button("⚡ Calculate", variant="primary", size="lg")
282
+
283
+ with gr.Column(scale=1):
284
+ gr.Markdown("### 📊 Numerical Results")
285
+ numerical_output = gr.Markdown(
286
+ value="Enter parameters and click 'Calculate' to see results.",
287
+ elem_classes=["result-box"]
288
+ )
289
+
290
+ gr.Markdown("### 🤖 AI Explanation")
291
+ explanation_output = gr.Markdown(
292
+ value="Detailed explanation will appear here after calculation.",
293
+ elem_classes=["result-box"]
294
+ )
295
+
296
+ # Example buttons
297
+ gr.Markdown("### 📋 Quick Examples")
298
+ with gr.Row():
299
+ example_basic = gr.Button("Basic Circuit", variant="secondary")
300
+ example_high_power = gr.Button("High Power Circuit", variant="secondary")
301
+ example_low_voltage = gr.Button("Low Voltage Circuit", variant="secondary")
302
+
303
+ # Event handlers
304
+ calculate_btn.click(
305
+ fn=calculate_circuit_analysis,
306
+ inputs=[
307
+ voltage_source,
308
+ r1_resistance, r1_power_rating,
309
+ r2_resistance, r2_power_rating,
310
+ r3_resistance, r3_power_rating,
311
+ r4_resistance, r4_power_rating
312
+ ],
313
+ outputs=[numerical_output, explanation_output]
314
+ )
315
+
316
+ # Example handlers
317
+ def load_basic_example():
318
+ return (12.0, 100, 0.25, 200, 0.25, 300, 0.25, 50, 0.5)
319
+
320
+ def load_high_power_example():
321
+ return (24.0, 50, 1.0, 100, 0.5, 150, 0.5, 25, 1.0)
322
+
323
+ def load_low_voltage_example():
324
+ return (3.3, 220, 0.125, 470, 0.125, 680, 0.125, 330, 0.125)
325
+
326
+ example_basic.click(
327
+ fn=load_basic_example,
328
+ outputs=[voltage_source, r1_resistance, r1_power_rating, r2_resistance, r2_power_rating,
329
+ r3_resistance, r3_power_rating, r4_resistance, r4_power_rating]
330
+ )
331
+
332
+ example_high_power.click(
333
+ fn=load_high_power_example,
334
+ outputs=[voltage_source, r1_resistance, r1_power_rating, r2_resistance, r2_power_rating,
335
+ r3_resistance, r3_power_rating, r4_resistance, r4_power_rating]
336
+ )
337
+
338
+ example_low_voltage.click(
339
+ fn=load_low_voltage_example,
340
+ outputs=[voltage_source, r1_resistance, r1_power_rating, r2_resistance, r2_power_rating,
341
+ r3_resistance, r3_power_rating, r4_resistance, r4_power_rating]
342
+ )
343
+
344
+ # Footer
345
+ gr.Markdown("""
346
+ ---
347
+ **⚠️ Disclaimer:** This calculator is for educational and preliminary design purposes only.
348
+ For final circuit design, consult a licensed electrical engineer.
349
+
350
+ **🔬 Methodology:** Based on Ohm's Law, Kirchhoff's Laws, and series-parallel circuit analysis for DC steady-state conditions.
351
+ """)
352
+
353
+ return interface
354
+
355
+
356
+ # For Hugging Face Spaces deployment
357
+ if __name__ == "__main__":
358
+ # Create and launch the interface
359
+ interface = create_interface()
360
+ interface.launch()