citoreh commited on
Commit
923ca8b
·
verified ·
1 Parent(s): 935f622

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +421 -0
app.py ADDED
@@ -0,0 +1,421 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import matplotlib.pyplot as plt
3
+ import numpy as np
4
+ import sympy as sp
5
+ from matplotlib.patches import Circle
6
+ import io
7
+ import base64
8
+ from PIL import Image
9
+ import warnings
10
+ warnings.filterwarnings(‘ignore’)
11
+
12
+ class MathVisualizer:
13
+ def **init**(self):
14
+ self.x = sp.Symbol(‘x’)
15
+ self.y = sp.Symbol(‘y’)
16
+ self.t = sp.Symbol(‘t’)
17
+
18
+ ```
19
+ def safe_eval(self, expression, variables):
20
+ """Safely evaluate mathematical expressions"""
21
+ try:
22
+ # Convert string to sympy expression
23
+ expr = sp.sympify(expression)
24
+ # Convert to numpy function for evaluation
25
+ func = sp.lambdify(variables, expr, 'numpy')
26
+ return func
27
+ except Exception as e:
28
+ raise ValueError(f"Invalid expression: {str(e)}")
29
+
30
+ def plot_2d_function(self, equation, x_range, y_range, color, style, grid, title):
31
+ """Plot 2D function y = f(x)"""
32
+ try:
33
+ func = self.safe_eval(equation, self.x)
34
+ x_vals = np.linspace(x_range[0], x_range[1], 1000)
35
+ y_vals = func(x_vals)
36
+
37
+ # Handle complex numbers and infinities
38
+ y_vals = np.real(y_vals)
39
+ y_vals = np.where(np.abs(y_vals) > 1e10, np.nan, y_vals)
40
+
41
+ plt.figure(figsize=(10, 8))
42
+ plt.plot(x_vals, y_vals, color=color, linewidth=2, linestyle=style)
43
+ plt.xlim(x_range)
44
+ plt.ylim(y_range)
45
+ plt.xlabel('x', fontsize=12)
46
+ plt.ylabel('y', fontsize=12)
47
+ plt.title(title or f'y = {equation}', fontsize=14)
48
+ plt.grid(grid, alpha=0.3)
49
+
50
+ return plt.gcf()
51
+
52
+ except Exception as e:
53
+ plt.figure(figsize=(10, 8))
54
+ plt.text(0.5, 0.5, f'Error: {str(e)}', ha='center', va='center',
55
+ transform=plt.gca().transAxes, fontsize=12, color='red')
56
+ plt.title('Error in equation')
57
+ return plt.gcf()
58
+
59
+ def plot_parametric(self, x_equation, y_equation, t_range, color, style, grid, title):
60
+ """Plot parametric equations x = f(t), y = g(t)"""
61
+ try:
62
+ x_func = self.safe_eval(x_equation, self.t)
63
+ y_func = self.safe_eval(y_equation, self.t)
64
+
65
+ t_vals = np.linspace(t_range[0], t_range[1], 1000)
66
+ x_vals = x_func(t_vals)
67
+ y_vals = y_func(t_vals)
68
+
69
+ # Handle complex numbers
70
+ x_vals = np.real(x_vals)
71
+ y_vals = np.real(y_vals)
72
+
73
+ plt.figure(figsize=(10, 8))
74
+ plt.plot(x_vals, y_vals, color=color, linewidth=2, linestyle=style)
75
+ plt.xlabel('x', fontsize=12)
76
+ plt.ylabel('y', fontsize=12)
77
+ plt.title(title or f'x = {x_equation}, y = {y_equation}', fontsize=14)
78
+ plt.grid(grid, alpha=0.3)
79
+ plt.axis('equal')
80
+
81
+ return plt.gcf()
82
+
83
+ except Exception as e:
84
+ plt.figure(figsize=(10, 8))
85
+ plt.text(0.5, 0.5, f'Error: {str(e)}', ha='center', va='center',
86
+ transform=plt.gca().transAxes, fontsize=12, color='red')
87
+ plt.title('Error in parametric equations')
88
+ return plt.gcf()
89
+
90
+ def plot_polar(self, equation, theta_range, color, style, grid, title):
91
+ """Plot polar equations r = f(θ)"""
92
+ try:
93
+ theta = sp.Symbol('theta')
94
+ func = self.safe_eval(equation.replace('θ', 'theta').replace('theta', 'theta'), theta)
95
+
96
+ theta_vals = np.linspace(theta_range[0], theta_range[1], 1000)
97
+ r_vals = func(theta_vals)
98
+ r_vals = np.real(r_vals)
99
+
100
+ plt.figure(figsize=(10, 8))
101
+ ax = plt.subplot(111, projection='polar')
102
+ ax.plot(theta_vals, r_vals, color=color, linewidth=2, linestyle=style)
103
+ ax.set_title(title or f'r = {equation}', fontsize=14, pad=20)
104
+ ax.grid(grid, alpha=0.3)
105
+
106
+ return plt.gcf()
107
+
108
+ except Exception as e:
109
+ plt.figure(figsize=(10, 8))
110
+ plt.text(0.5, 0.5, f'Error: {str(e)}', ha='center', va='center',
111
+ transform=plt.gca().transAxes, fontsize=12, color='red')
112
+ plt.title('Error in polar equation')
113
+ return plt.gcf()
114
+
115
+ def plot_implicit(self, equation, x_range, y_range, color, grid, title):
116
+ """Plot implicit equations F(x,y) = 0"""
117
+ try:
118
+ # Parse equation (assume it equals 0)
119
+ expr = sp.sympify(equation)
120
+
121
+ x_vals = np.linspace(x_range[0], x_range[1], 400)
122
+ y_vals = np.linspace(y_range[0], y_range[1], 400)
123
+ X, Y = np.meshgrid(x_vals, y_vals)
124
+
125
+ # Convert to numpy function
126
+ func = sp.lambdify([self.x, self.y], expr, 'numpy')
127
+ Z = func(X, Y)
128
+ Z = np.real(Z)
129
+
130
+ plt.figure(figsize=(10, 8))
131
+ plt.contour(X, Y, Z, levels=[0], colors=[color], linewidths=2)
132
+ plt.xlim(x_range)
133
+ plt.ylim(y_range)
134
+ plt.xlabel('x', fontsize=12)
135
+ plt.ylabel('y', fontsize=12)
136
+ plt.title(title or f'{equation} = 0', fontsize=14)
137
+ plt.grid(grid, alpha=0.3)
138
+
139
+ return plt.gcf()
140
+
141
+ except Exception as e:
142
+ plt.figure(figsize=(10, 8))
143
+ plt.text(0.5, 0.5, f'Error: {str(e)}', ha='center', va='center',
144
+ transform=plt.gca().transAxes, fontsize=12, color='red')
145
+ plt.title('Error in implicit equation')
146
+ return plt.gcf()
147
+
148
+ def plot_3d_surface(self, equation, x_range, y_range, color_scheme, title):
149
+ """Plot 3D surface z = f(x,y)"""
150
+ try:
151
+ func = self.safe_eval(equation, [self.x, self.y])
152
+
153
+ x_vals = np.linspace(x_range[0], x_range[1], 50)
154
+ y_vals = np.linspace(y_range[0], y_range[1], 50)
155
+ X, Y = np.meshgrid(x_vals, y_vals)
156
+ Z = func(X, Y)
157
+ Z = np.real(Z)
158
+
159
+ fig = plt.figure(figsize=(12, 10))
160
+ ax = fig.add_subplot(111, projection='3d')
161
+ surf = ax.plot_surface(X, Y, Z, cmap=color_scheme, alpha=0.8)
162
+ ax.set_xlabel('x', fontsize=12)
163
+ ax.set_ylabel('y', fontsize=12)
164
+ ax.set_zlabel('z', fontsize=12)
165
+ ax.set_title(title or f'z = {equation}', fontsize=14)
166
+ fig.colorbar(surf, shrink=0.5, aspect=5)
167
+
168
+ return fig
169
+
170
+ except Exception as e:
171
+ fig = plt.figure(figsize=(12, 10))
172
+ plt.text(0.5, 0.5, f'Error: {str(e)}', ha='center', va='center',
173
+ transform=plt.gca().transAxes, fontsize=12, color='red')
174
+ plt.title('Error in 3D equation')
175
+ return fig
176
+ ```
177
+
178
+ # Initialize visualizer
179
+
180
+ visualizer = MathVisualizer()
181
+
182
+ def generate_plot(plot_type, equation, x_equation, y_equation,
183
+ x_min, x_max, y_min, y_max, t_min, t_max, theta_min, theta_max,
184
+ color, line_style, color_scheme, show_grid, custom_title):
185
+
186
+ ```
187
+ plt.close('all') # Close any existing plots
188
+
189
+ try:
190
+ if plot_type == "2D Function (y = f(x))":
191
+ fig = visualizer.plot_2d_function(
192
+ equation, (x_min, x_max), (y_min, y_max),
193
+ color, line_style, show_grid, custom_title
194
+ )
195
+
196
+ elif plot_type == "Parametric (x = f(t), y = g(t))":
197
+ fig = visualizer.plot_parametric(
198
+ x_equation, y_equation, (t_min, t_max),
199
+ color, line_style, show_grid, custom_title
200
+ )
201
+
202
+ elif plot_type == "Polar (r = f(θ))":
203
+ fig = visualizer.plot_polar(
204
+ equation, (theta_min, theta_max),
205
+ color, line_style, show_grid, custom_title
206
+ )
207
+
208
+ elif plot_type == "Implicit (F(x,y) = 0)":
209
+ fig = visualizer.plot_implicit(
210
+ equation, (x_min, x_max), (y_min, y_max),
211
+ color, show_grid, custom_title
212
+ )
213
+
214
+ elif plot_type == "3D Surface (z = f(x,y))":
215
+ fig = visualizer.plot_3d_surface(
216
+ equation, (x_min, x_max), (y_min, y_max),
217
+ color_scheme, custom_title
218
+ )
219
+
220
+ return fig
221
+
222
+ except Exception as e:
223
+ plt.figure(figsize=(10, 8))
224
+ plt.text(0.5, 0.5, f'Error: {str(e)}', ha='center', va='center',
225
+ transform=plt.gca().transAxes, fontsize=12, color='red')
226
+ plt.title('Error generating plot')
227
+ return plt.gcf()
228
+ ```
229
+
230
+ # Example equations for different types
231
+
232
+ examples = {
233
+ “2D Function (y = f(x))”: [
234
+ “sin(x)”,
235
+ “x**2 + 2*x + 1”,
236
+ “exp(-x**2)”,
237
+ “tan(x)”,
238
+ “log(abs(x))”
239
+ ],
240
+ “Parametric (x = f(t), y = g(t))”: [
241
+ (“cos(t)”, “sin(t)”), # Circle
242
+ (“t*cos(t)”, “t*sin(t)”), # Spiral
243
+ (“cos(3*t)”, “sin(2*t)”), # Lissajous
244
+ ],
245
+ “Polar (r = f(θ))”: [
246
+ “1 + cos(theta)”, # Cardioid
247
+ “sin(4*theta)”, # Rose
248
+ “theta”, # Spiral
249
+ ],
250
+ “Implicit (F(x,y) = 0)”: [
251
+ “x**2 + y**2 - 1”, # Circle
252
+ “(x**2 + y**2)**2 - 2*(x**2 - y**2)”, # Lemniscate
253
+ “x**3 + y**3 - 3*x*y”, # Folium of Descartes
254
+ ],
255
+ “3D Surface (z = f(x,y))”: [
256
+ “sin(sqrt(x**2 + y**2))”,
257
+ “x**2 - y**2”,
258
+ “exp(-(x**2 + y**2))”,
259
+ ]
260
+ }
261
+
262
+ def load_example(plot_type, example_idx):
263
+ if plot_type in examples:
264
+ example_list = examples[plot_type]
265
+ if 0 <= example_idx < len(example_list):
266
+ example = example_list[example_idx]
267
+ if plot_type == “Parametric (x = f(t), y = g(t))”:
268
+ return example[0], example[1], “”, “”
269
+ else:
270
+ return example, “”, “”, “”
271
+ return “”, “”, “”, “”
272
+
273
+ # Create Gradio interface
274
+
275
+ with gr.Blocks(title=“Mathematical Equation Visualizer”, theme=gr.themes.Soft()) as demo:
276
+ gr.Markdown(”””
277
+ # 📊 Mathematical Equation Visualizer
278
+
279
+ ```
280
+ Generate beautiful visualizations of mathematical equations with various plot types and customization options.
281
+
282
+ **Supported functions:** sin, cos, tan, exp, log, sqrt, abs, and basic arithmetic (+, -, *, /, **)
283
+ """)
284
+
285
+ with gr.Row():
286
+ with gr.Column(scale=1):
287
+ plot_type = gr.Dropdown(
288
+ choices=[
289
+ "2D Function (y = f(x))",
290
+ "Parametric (x = f(t), y = g(t))",
291
+ "Polar (r = f(θ))",
292
+ "Implicit (F(x,y) = 0)",
293
+ "3D Surface (z = f(x,y))"
294
+ ],
295
+ value="2D Function (y = f(x))",
296
+ label="Plot Type"
297
+ )
298
+
299
+ with gr.Group():
300
+ equation = gr.Textbox(
301
+ value="sin(x)",
302
+ label="Equation",
303
+ placeholder="e.g., sin(x), x**2 + 1, etc."
304
+ )
305
+
306
+ with gr.Row(visible=False) as parametric_inputs:
307
+ x_equation = gr.Textbox(
308
+ label="x = f(t)",
309
+ placeholder="e.g., cos(t)"
310
+ )
311
+ y_equation = gr.Textbox(
312
+ label="y = g(t)",
313
+ placeholder="e.g., sin(t)"
314
+ )
315
+
316
+ with gr.Group():
317
+ gr.Markdown("### Range Settings")
318
+ with gr.Row():
319
+ x_min = gr.Number(value=-10, label="x min")
320
+ x_max = gr.Number(value=10, label="x max")
321
+ with gr.Row():
322
+ y_min = gr.Number(value=-10, label="y min")
323
+ y_max = gr.Number(value=10, label="y max")
324
+ with gr.Row():
325
+ t_min = gr.Number(value=0, label="t min")
326
+ t_max = gr.Number(value=6.28, label="t max")
327
+ with gr.Row():
328
+ theta_min = gr.Number(value=0, label="θ min")
329
+ theta_max = gr.Number(value=6.28, label="θ max")
330
+
331
+ with gr.Group():
332
+ gr.Markdown("### Style Settings")
333
+ color = gr.ColorPicker(value="#1f77b4", label="Line Color")
334
+ line_style = gr.Dropdown(
335
+ choices=["-", "--", "-.", ":"],
336
+ value="-",
337
+ label="Line Style"
338
+ )
339
+ color_scheme = gr.Dropdown(
340
+ choices=["viridis", "plasma", "inferno", "magma", "coolwarm", "RdYlBu"],
341
+ value="viridis",
342
+ label="3D Color Scheme"
343
+ )
344
+ show_grid = gr.Checkbox(value=True, label="Show Grid")
345
+ custom_title = gr.Textbox(label="Custom Title (optional)")
346
+
347
+ generate_btn = gr.Button("🎨 Generate Plot", variant="primary")
348
+
349
+ # Example buttons
350
+ gr.Markdown("### 📚 Examples")
351
+ example_dropdown = gr.Dropdown(
352
+ choices=["Select an example..."],
353
+ label="Load Example"
354
+ )
355
+
356
+ with gr.Column(scale=2):
357
+ output_plot = gr.Plot(label="Generated Plot")
358
+
359
+ # Event handlers
360
+ def update_inputs(plot_type):
361
+ parametric_visible = plot_type == "Parametric (x = f(t), y = g(t))"
362
+
363
+ # Update example dropdown
364
+ if plot_type in examples:
365
+ example_choices = ["Select an example..."] + [
366
+ f"Example {i+1}" for i in range(len(examples[plot_type]))
367
+ ]
368
+ else:
369
+ example_choices = ["Select an example..."]
370
+
371
+ return (
372
+ gr.update(visible=parametric_visible),
373
+ gr.update(choices=example_choices, value="Select an example...")
374
+ )
375
+
376
+ def load_example_equations(plot_type, example_choice):
377
+ if example_choice == "Select an example...":
378
+ return "", "", "", ""
379
+
380
+ try:
381
+ example_idx = int(example_choice.split()[-1]) - 1
382
+ return load_example(plot_type, example_idx)
383
+ except:
384
+ return "", "", "", ""
385
+
386
+ plot_type.change(
387
+ update_inputs,
388
+ inputs=[plot_type],
389
+ outputs=[parametric_inputs, example_dropdown]
390
+ )
391
+
392
+ example_dropdown.change(
393
+ load_example_equations,
394
+ inputs=[plot_type, example_dropdown],
395
+ outputs=[equation, x_equation, y_equation, custom_title]
396
+ )
397
+
398
+ generate_btn.click(
399
+ generate_plot,
400
+ inputs=[
401
+ plot_type, equation, x_equation, y_equation,
402
+ x_min, x_max, y_min, y_max, t_min, t_max, theta_min, theta_max,
403
+ color, line_style, color_scheme, show_grid, custom_title
404
+ ],
405
+ outputs=[output_plot]
406
+ )
407
+
408
+ # Auto-generate on equation change
409
+ equation.change(
410
+ generate_plot,
411
+ inputs=[
412
+ plot_type, equation, x_equation, y_equation,
413
+ x_min, x_max, y_min, y_max, t_min, t_max, theta_min, theta_max,
414
+ color, line_style, color_scheme, show_grid, custom_title
415
+ ],
416
+ outputs=[output_plot]
417
+ )
418
+ ```
419
+
420
+ if **name** == “**main**”:
421
+ demo.launch(share=True)