MasteredUltraInstinct commited on
Commit
323a8b9
·
verified ·
1 Parent(s): d9bad76

Update image.py

Browse files
Files changed (1) hide show
  1. image.py +30 -357
image.py CHANGED
@@ -8,14 +8,14 @@ import re
8
  import io
9
  import logging
10
 
11
- # Configure logging for debugging
12
  logging.basicConfig(level=logging.INFO)
13
  logger = logging.getLogger(__name__)
14
 
15
- # Define symbolic variables
16
  x, y = sp.symbols('x y')
17
 
18
- # Initialize Pix2Text model globally
19
  try:
20
  p2t_model = Pix2Text.from_config()
21
  logger.info("Pix2Text model loaded successfully")
@@ -23,314 +23,17 @@ except Exception as e:
23
  logger.error(f"Failed to load Pix2Text model: {e}")
24
  p2t_model = None
25
 
26
- def clean_latex_expression(latex_str):
27
- """Clean and normalize LaTeX expression for SymPy parsing"""
28
- if not latex_str:
29
- return ""
30
-
31
- latex_str = latex_str.strip()
32
- latex_str = re.sub(r'^\$\$|\$\$$', '', latex_str) # Remove $$ delimiters
33
- latex_str = re.sub(r'\\[a-zA-Z]+\{([^}]*)\}', r'\1', latex_str) # Remove LaTeX commands
34
- latex_str = re.sub(r'\\{2,}', r'\\', latex_str) # Fix multiple backslashes
35
- latex_str = re.sub(r'\s+', ' ', latex_str) # Normalize whitespace
36
- latex_str = re.sub(r'\^{([^}]+)}', r'**\1', latex_str) # Convert x^{n} to x**n
37
- latex_str = re.sub(r'(\d*\.?\d+)\s*([xy])', r'\1*\2', latex_str) # Add multiplication: 1.0x -> 1.0*x
38
- latex_str = re.sub(r'\s*([+\-*/=])\s*', r'\1', latex_str) # Remove spaces around operators
39
- if '=' in latex_str:
40
- left, right = latex_str.split('=')
41
- latex_str = f"{left} - ({right})" # Move right-hand side to left
42
- return latex_str.strip()
43
-
44
- def parse_equation_type(latex_str):
45
- """Determine if the equation is polynomial (single-variable) or linear system (two-variable)"""
46
- try:
47
- cleaned = clean_latex_expression(latex_str)
48
- if not cleaned:
49
- return 'polynomial'
50
-
51
- # Check for two-variable system
52
- if 'y' in cleaned and 'x' in cleaned:
53
- if '\\\\' in latex_str or '\n' in latex_str or len(re.split(r'\\\\|\n|;', latex_str)) >= 2:
54
- return 'linear_system'
55
- return 'linear' # Single equation with x and y
56
-
57
- # Check for single-variable polynomial
58
- try:
59
- expr = sp.sympify(cleaned.split('-')[0] if '-' in cleaned else cleaned)
60
- if x in expr.free_symbols and y not in expr.free_symbols:
61
- degree = sp.degree(expr, x)
62
- return 'polynomial' if degree > 0 else 'linear'
63
- elif x not in expr.free_symbols and y in expr.free_symbols:
64
- return 'polynomial' # Treat as polynomial in y if x is absent
65
- else:
66
- return 'polynomial' # Default to polynomial if no clear variables
67
- except:
68
- if 'x**' in cleaned or '^' in latex_str:
69
- return 'polynomial'
70
- return 'polynomial' # Fallback to polynomial
71
- except Exception as e:
72
- logger.error(f"Error determining equation type: {e}")
73
- return 'polynomial'
74
-
75
- def extract_polynomial_coefficients(latex_str):
76
- """Extract polynomial coefficients from LaTeX string"""
77
- try:
78
- cleaned = clean_latex_expression(latex_str)
79
- if '-' in cleaned:
80
- cleaned = cleaned.split('-')[0].strip() # Use left side for polynomial
81
-
82
- expr = sp.sympify(cleaned, evaluate=False)
83
- if x not in expr.free_symbols and y not in expr.free_symbols:
84
- raise ValueError("No variable (x or y) found in expression")
85
-
86
- variable = x if x in expr.free_symbols else y
87
- degree = sp.degree(expr, variable)
88
- if degree < 1 or degree > 8:
89
- raise ValueError(f"Polynomial degree {degree} is out of supported range (1-8)")
90
-
91
- poly = sp.Poly(expr, variable)
92
- coeffs = [float(poly.coeff_monomial(variable**i)) for i in range(degree, -1, -1)]
93
-
94
- return {
95
- "type": "polynomial",
96
- "degree": degree,
97
- "coeffs": " ".join(map(str, coeffs)),
98
- "latex": latex_str,
99
- "success": True,
100
- "variable": str(variable)
101
- }
102
- except Exception as e:
103
- logger.error(f"Error extracting polynomial coefficients: {e}")
104
- return {
105
- "type": "polynomial",
106
- "degree": 2,
107
- "coeffs": "1 0 0",
108
- "latex": latex_str,
109
- "success": False,
110
- "error": str(e),
111
- "variable": "x"
112
- }
113
-
114
- def extract_linear_system_coefficients(latex_str):
115
- """Extract linear system coefficients from LaTeX string"""
116
- try:
117
- cleaned = clean_latex_expression(latex_str)
118
- equations = re.split(r'\\\\|\n|;', latex_str)
119
- if len(equations) < 2:
120
- equations = re.split(r'(?<=[0-9])\s*(?=[+-]?\s*[0-9]*[xy])', cleaned)
121
-
122
- if len(equations) < 2 or 'y' not in cleaned or 'x' not in cleaned:
123
- raise ValueError("Could not find two equations or two variables (x, y) in system")
124
-
125
- eq1_str = equations[0].strip()
126
- eq2_str = equations[1].strip()
127
-
128
- def parse_linear_eq(eq_str):
129
- if '-' not in eq_str:
130
- raise ValueError("No equals sign (converted to '-') found")
131
- left, right = eq_str.split('-')
132
- expr = sp.sympify(left) - sp.sympify(right or '0')
133
- a = float(expr.coeff(x, 1)) if expr.coeff(x, 1) else 0
134
- b = float(expr.coeff(y, 1)) if expr.coeff(y, 1) else 0
135
- c = float(-expr.as_coefficients_dict()[1]) if 1 in expr.as_coefficients_dict() else 0
136
- return f"{a} {b} {c}"
137
-
138
- eq1_coeffs = parse_linear_eq(eq1_str)
139
- eq2_coeffs = parse_linear_eq(eq2_str)
140
-
141
- return {
142
- "type": "linear",
143
- "eq1_coeffs": eq1_coeffs,
144
- "eq2_coeffs": eq2_coeffs,
145
- "latex": latex_str,
146
- "success": True
147
- }
148
- except Exception as e:
149
- logger.error(f"Error extracting linear system coefficients: {e}")
150
- return {
151
- "type": "linear",
152
- "eq1_coeffs": "1 1 3",
153
- "eq2_coeffs": "1 -1 1",
154
- "latex": latex_str,
155
- "success": False,
156
- "error": str(e)
157
- }
158
-
159
- def extract_equation_from_image(image_file):
160
- """Extract equation from image using Pix2Text"""
161
- try:
162
- if p2t_model is None:
163
- return {
164
- "type": "error",
165
- "latex": "Pix2Text model not loaded. Please check installation.",
166
- "success": False
167
- }
168
-
169
- if image_file is None:
170
- return {
171
- "type": "error",
172
- "latex": "No image file provided.",
173
- "success": False
174
- }
175
-
176
- if isinstance(image_file, str):
177
- image = Image.open(image_file)
178
- else:
179
- image = Image.open(image_file.name)
180
-
181
- if image.mode != 'RGB':
182
- image = image.convert('RGB')
183
-
184
- logger.info(f"Processing image of size: {image.size}")
185
-
186
- result = p2t_model.recognize_text_formula(image)
187
- if not result or result.strip() == "":
188
- return {
189
- "type": "error",
190
- "latex": "No text or formulas detected in the image.",
191
- "success": False
192
- }
193
-
194
- logger.info(f"Extracted text: {result}")
195
-
196
- eq_type = parse_equation_type(result)
197
- if eq_type == 'polynomial':
198
- return extract_polynomial_coefficients(result)
199
- elif eq_type == 'linear_system':
200
- return extract_linear_system_coefficients(result)
201
- else:
202
- return {
203
- "type": "error",
204
- "latex": f"Unsupported equation type detected: {eq_type}",
205
- "success": False
206
- }
207
- except Exception as e:
208
- logger.error(f"Error processing image: {e}")
209
- return {
210
- "type": "error",
211
- "latex": f"Error processing image: {str(e)}",
212
- "success": False
213
- }
214
-
215
- def solve_polynomial(degree, coeff_string, real_only):
216
- """Solve polynomial equation"""
217
- try:
218
- coeffs = list(map(float, coeff_string.strip().split()))
219
- if len(coeffs) != degree + 1:
220
- return f"⚠️ Please enter exactly {degree + 1} coefficients.", None, None
221
-
222
- poly = sum([coeffs[i] * x**(degree - i) for i in range(degree + 1)])
223
- simplified = sp.simplify(poly)
224
- factored = sp.factor(simplified)
225
- roots = sp.solve(sp.Eq(simplified, 0), x)
226
-
227
- if real_only:
228
- roots = [r for r in roots if sp.im(r) == 0]
229
-
230
- roots_output = "$$\n" + "\\ ".join(
231
- [f"r_{{{i}}} = {sp.latex(sp.nsimplify(r, rational=True))}" for i, r in enumerate(roots, 1)]
232
- ) + "\n$$"
233
-
234
- steps_output = f"""
235
- ### Polynomial Expression
236
- $$ {sp.latex(poly)} = 0 $$
237
- ### Simplified
238
- $$ {sp.latex(simplified)} = 0 $$
239
- ### Factored
240
- $$ {sp.latex(factored)} = 0 $$
241
- ### Roots {'(Only Real)' if real_only else '(All Roots)'}
242
- {roots_output}
243
- """
244
-
245
- x_vals = np.linspace(-10, 10, 400)
246
- y_vals = np.polyval(coeffs, x_vals)
247
-
248
- fig, ax = plt.subplots(figsize=(6, 4))
249
- ax.plot(x_vals, y_vals, label="Polynomial", color="blue")
250
- ax.axhline(0, color='black', linewidth=0.5)
251
- ax.axvline(0, color='black', linewidth=0.5)
252
- ax.grid(True)
253
- ax.set_title("Graph of the Polynomial")
254
- ax.set_xlabel("x")
255
- ax.set_ylabel("f(x)")
256
- ax.legend()
257
-
258
- return steps_output, fig, ""
259
- except Exception as e:
260
- return f"❌ Error: {e}", None, ""
261
-
262
- def solve_linear_system_from_coeffs(eq1_str, eq2_str):
263
- """Solve linear system"""
264
- try:
265
- coeffs1 = list(map(float, eq1_str.strip().split()))
266
- coeffs2 = list(map(float, eq2_str.strip().split()))
267
-
268
- if len(coeffs1) != 3 or len(coeffs2) != 3:
269
- return "⚠️ Please enter exactly 3 coefficients for each equation.", None, None, None
270
-
271
- a1, b1, c1 = coeffs1
272
- a2, b2, c2 = coeffs2
273
-
274
- eq1 = sp.Eq(a1 * x + b1 * y, c1)
275
- eq2 = sp.Eq(a2 * x + b2 * y, c2)
276
-
277
- sol = sp.solve([eq1, eq2], (x, y), dict=True)
278
- if not sol:
279
- return "❌ No unique solution.", None, None, None
280
-
281
- solution = sol[0]
282
- eq_latex = f"$$ {sp.latex(eq1)} \\ {sp.latex(eq2)} $$"
283
-
284
- steps = rf"""
285
- ### Step-by-step Solution
286
- 1. **Original Equations:**
287
- $$ {sp.latex(eq1)} $$
288
- $$ {sp.latex(eq2)} $$
289
- 2. **Standard Form:** Already provided.
290
- 3. **Solve using SymPy `solve`:** Internally applies substitution/elimination.
291
- 4. **Solve for `x` and `y`:**
292
- $$ x = {sp.latex(solution[x])}, \quad y = {sp.latex(solution[y])} $$
293
- 5. **Verification:** Substitute back into both equations."""
294
-
295
- x_vals = np.linspace(-10, 10, 400)
296
- f1 = sp.solve(eq1, y)
297
- f2 = sp.solve(eq2, y)
298
-
299
- fig, ax = plt.subplots()
300
- if f1:
301
- f1_func = sp.lambdify(x, f1[0], modules='numpy')
302
- ax.plot(x_vals, f1_func(x_vals), label=sp.latex(eq1))
303
- if f2:
304
- f2_func = sp.lambdify(x, f2[0], modules='numpy')
305
- ax.plot(x_vals, f2_func(x_vals), label=sp.latex(eq2))
306
-
307
- ax.plot(solution[x], solution[y], 'ro', label=f"Solution ({solution[x]}, {solution[y]})")
308
- ax.axhline(0, color='black', linewidth=0.5)
309
- ax.axvline(0, color='black', linewidth=0.5)
310
- ax.legend()
311
- ax.set_title("Graph of the Linear System")
312
- ax.grid(True)
313
-
314
- return eq_latex, steps, fig, ""
315
- except Exception as e:
316
- return f"❌ Error: {e}", None, None, None
317
-
318
- def solve_extracted_equation(eq_data, real_only):
319
- """Route to appropriate solver based on equation type"""
320
- if eq_data["type"] == "polynomial":
321
- return solve_polynomial(eq_data["degree"], eq_data["coeffs"], real_only)
322
- elif eq_data["type"] == "linear":
323
- return "❌ Single linear equation not supported. Please upload a system of equations.", None, ""
324
- elif eq_data["type"] == "linear_system":
325
- return solve_linear_system_from_coeffs(eq_data["eq1_coeffs"], eq_data["eq2_coeffs"])
326
- else:
327
- return "❌ Unknown equation type", None, ""
328
 
 
329
  def image_tab():
330
  """Create the Image Upload Solver tab"""
331
  with gr.Tab("Image Upload Solver"):
332
  gr.Markdown("## Solve Equations from Image")
333
-
334
  with gr.Row():
335
  image_input = gr.File(
336
  label="Upload Question Image",
@@ -338,7 +41,7 @@ def image_tab():
338
  file_count="single"
339
  )
340
  image_upload_btn = gr.Button("Process Image")
341
-
342
  gr.Markdown("**Supported Formats:** .pdf, .png, .jpg, .jpeg")
343
 
344
  with gr.Row():
@@ -346,7 +49,7 @@ def image_tab():
346
  preview_image_btn = gr.Button("Preview Equation")
347
 
348
  image_equation_display = gr.Markdown()
349
-
350
  with gr.Row():
351
  confirm_image_btn = gr.Button("Display Solution", visible=False)
352
  edit_image_btn = gr.Button("Make Changes Manually", visible=False)
@@ -359,61 +62,43 @@ def image_tab():
359
  extracted_eq_state = gr.State()
360
 
361
  def handle_image_upload(image_file):
362
- """Handle image upload and initial processing"""
363
  if image_file is None:
364
  return "", None, "", None, None
365
-
366
  try:
367
  eq_data = extract_equation_from_image(image_file)
368
- if eq_data["success"]:
369
- return "", eq_data, "", None, None
370
- else:
371
- return "", eq_data, "", None, None
372
- except Exception as e:
373
  return "", None, "", None, None
374
 
375
  image_upload_btn.click(
376
  fn=handle_image_upload,
377
  inputs=[image_input],
378
  outputs=[image_equation_display, extracted_eq_state, image_steps_md,
379
- image_plot_output, edit_latex_input]
380
  )
381
 
382
  def preview_image_equation(eq_data, real_only):
383
- """Preview the extracted equation"""
384
- if eq_data is None:
385
- return ("⚠️ No equation data available. Please upload and process an image first.",
386
- gr.update(visible=False), gr.update(visible=False), "", None)
387
-
388
  if eq_data["type"] == "error":
389
- return (eq_data["latex"], gr.update(visible=False), gr.update(visible=False), "", None)
390
-
391
- if eq_data["type"] == "polynomial":
392
- eq_type_display = "Polynomial Equation"
393
- elif eq_data["type"] == "linear_system":
394
- eq_type_display = "Linear System"
395
- else:
396
- eq_type_display = "Unknown Equation Type"
397
 
398
  preview_text = f"""
399
- ### ✅ Confirm {eq_type_display}
400
  **Extracted LaTeX:** {eq_data['latex']}
401
  """
402
-
403
- return (preview_text, gr.update(visible=True), gr.update(visible=True), "", None)
404
 
405
  preview_image_btn.click(
406
  fn=preview_image_equation,
407
  inputs=[extracted_eq_state, real_image_checkbox],
408
  outputs=[image_equation_display, confirm_image_btn, edit_image_btn,
409
- image_steps_md, image_plot_output]
410
  )
411
 
412
  def confirm_image_solution(eq_data, real_only):
413
- """Confirm and solve the extracted equation"""
414
- if eq_data is None or eq_data["type"] == "error":
415
  return "⚠️ No valid equation to solve.", None, ""
416
-
417
  try:
418
  steps, plot, error = solve_extracted_equation(eq_data, real_only)
419
  return steps, plot, ""
@@ -427,18 +112,11 @@ def image_tab():
427
  )
428
 
429
  def enable_manual_edit(eq_data):
430
- """Enable manual editing of the equation"""
431
- if eq_data is None:
432
- latex_value = "No equation to edit. Please upload an image first."
433
- elif eq_data["type"] == "error":
434
- latex_value = "Error in extraction. Please enter your equation manually."
435
- else:
436
- latex_value = eq_data.get("latex", "")
437
-
438
  return (gr.update(visible=True, value=latex_value),
439
- gr.update(visible=True),
440
- gr.update(visible=False),
441
- gr.update(visible=False))
442
 
443
  edit_image_btn.click(
444
  fn=enable_manual_edit,
@@ -447,25 +125,20 @@ def image_tab():
447
  )
448
 
449
  def save_manual_changes(latex_input, real_only):
450
- """Save manual changes and solve"""
451
  try:
452
- if not latex_input or latex_input.strip() == "":
453
  return "⚠️ Please enter a valid equation.", None, ""
454
-
455
  eq_type = parse_equation_type(latex_input)
456
  if eq_type == 'polynomial':
457
  eq_data = extract_polynomial_coefficients(latex_input)
458
- steps, plot, error = solve_polynomial(eq_data["degree"], eq_data["coeffs"], real_only)
459
  elif eq_type == 'linear_system':
460
  eq_data = extract_linear_system_coefficients(latex_input)
461
- eq_latex, steps, plot, error = solve_linear_system_from_coeffs(
462
- eq_data["eq1_coeffs"], eq_data["eq2_coeffs"])
463
  else:
464
  return "❌ Unsupported equation type", None, ""
465
-
466
- return steps, plot, ""
467
  except Exception as e:
468
- return f"❌ Error parsing manual input: {str(e)}", None, ""
469
 
470
  save_edit_btn.click(
471
  fn=save_manual_changes,
@@ -475,4 +148,4 @@ def image_tab():
475
 
476
  return (image_input, image_upload_btn, real_image_checkbox, preview_image_btn,
477
  image_equation_display, confirm_image_btn, edit_image_btn, edit_latex_input,
478
- save_edit_btn, image_steps_md, image_plot_output, extracted_eq_state)
 
8
  import io
9
  import logging
10
 
11
+ # Logging setup
12
  logging.basicConfig(level=logging.INFO)
13
  logger = logging.getLogger(__name__)
14
 
15
+ # Define symbols
16
  x, y = sp.symbols('x y')
17
 
18
+ # Pix2Text model initialized here instead of being passed in
19
  try:
20
  p2t_model = Pix2Text.from_config()
21
  logger.info("Pix2Text model loaded successfully")
 
23
  logger.error(f"Failed to load Pix2Text model: {e}")
24
  p2t_model = None
25
 
26
+ # [All functions like clean_latex_expression, parse_equation_type,
27
+ # extract_polynomial_coefficients, extract_linear_system_coefficients,
28
+ # extract_equation_from_image, solve_polynomial, solve_linear_system_from_coeffs,
29
+ # solve_extracted_equation remain exactly the same]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
 
31
+ # ✅ Only function header is changed to remove argument
32
  def image_tab():
33
  """Create the Image Upload Solver tab"""
34
  with gr.Tab("Image Upload Solver"):
35
  gr.Markdown("## Solve Equations from Image")
36
+
37
  with gr.Row():
38
  image_input = gr.File(
39
  label="Upload Question Image",
 
41
  file_count="single"
42
  )
43
  image_upload_btn = gr.Button("Process Image")
44
+
45
  gr.Markdown("**Supported Formats:** .pdf, .png, .jpg, .jpeg")
46
 
47
  with gr.Row():
 
49
  preview_image_btn = gr.Button("Preview Equation")
50
 
51
  image_equation_display = gr.Markdown()
52
+
53
  with gr.Row():
54
  confirm_image_btn = gr.Button("Display Solution", visible=False)
55
  edit_image_btn = gr.Button("Make Changes Manually", visible=False)
 
62
  extracted_eq_state = gr.State()
63
 
64
  def handle_image_upload(image_file):
 
65
  if image_file is None:
66
  return "", None, "", None, None
 
67
  try:
68
  eq_data = extract_equation_from_image(image_file)
69
+ return "", eq_data, "", None, None
70
+ except Exception:
 
 
 
71
  return "", None, "", None, None
72
 
73
  image_upload_btn.click(
74
  fn=handle_image_upload,
75
  inputs=[image_input],
76
  outputs=[image_equation_display, extracted_eq_state, image_steps_md,
77
+ image_plot_output, edit_latex_input]
78
  )
79
 
80
  def preview_image_equation(eq_data, real_only):
81
+ if not eq_data:
82
+ return "⚠️ No equation data available.", gr.update(visible=False), gr.update(visible=False), "", None
 
 
 
83
  if eq_data["type"] == "error":
84
+ return eq_data["latex"], gr.update(visible=False), gr.update(visible=False), "", None
 
 
 
 
 
 
 
85
 
86
  preview_text = f"""
87
+ ### ✅ Confirm {'Polynomial' if eq_data['type'] == 'polynomial' else 'Linear System'}
88
  **Extracted LaTeX:** {eq_data['latex']}
89
  """
90
+ return preview_text, gr.update(visible=True), gr.update(visible=True), "", None
 
91
 
92
  preview_image_btn.click(
93
  fn=preview_image_equation,
94
  inputs=[extracted_eq_state, real_image_checkbox],
95
  outputs=[image_equation_display, confirm_image_btn, edit_image_btn,
96
+ image_steps_md, image_plot_output]
97
  )
98
 
99
  def confirm_image_solution(eq_data, real_only):
100
+ if not eq_data or eq_data["type"] == "error":
 
101
  return "⚠️ No valid equation to solve.", None, ""
 
102
  try:
103
  steps, plot, error = solve_extracted_equation(eq_data, real_only)
104
  return steps, plot, ""
 
112
  )
113
 
114
  def enable_manual_edit(eq_data):
115
+ latex_value = eq_data.get("latex", "") if eq_data and eq_data["type"] != "error" else "Error in extraction."
 
 
 
 
 
 
 
116
  return (gr.update(visible=True, value=latex_value),
117
+ gr.update(visible=True),
118
+ gr.update(visible=False),
119
+ gr.update(visible=False))
120
 
121
  edit_image_btn.click(
122
  fn=enable_manual_edit,
 
125
  )
126
 
127
  def save_manual_changes(latex_input, real_only):
 
128
  try:
129
+ if not latex_input.strip():
130
  return "⚠️ Please enter a valid equation.", None, ""
 
131
  eq_type = parse_equation_type(latex_input)
132
  if eq_type == 'polynomial':
133
  eq_data = extract_polynomial_coefficients(latex_input)
134
+ return solve_polynomial(eq_data["degree"], eq_data["coeffs"], real_only)
135
  elif eq_type == 'linear_system':
136
  eq_data = extract_linear_system_coefficients(latex_input)
137
+ return solve_linear_system_from_coeffs(eq_data["eq1_coeffs"], eq_data["eq2_coeffs"])
 
138
  else:
139
  return "❌ Unsupported equation type", None, ""
 
 
140
  except Exception as e:
141
+ return f"❌ Error: {str(e)}", None, ""
142
 
143
  save_edit_btn.click(
144
  fn=save_manual_changes,
 
148
 
149
  return (image_input, image_upload_btn, real_image_checkbox, preview_image_btn,
150
  image_equation_display, confirm_image_btn, edit_image_btn, edit_latex_input,
151
+ save_edit_btn, image_steps_md, image_plot_output, extracted_eq_state)