Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import numpy as np | |
| import matplotlib.pyplot as plt | |
| def create_error_plot(error_message): | |
| fig, ax = plt.subplots(figsize=(10, 6)) | |
| ax.text(0.5, 0.5, error_message, color='red', fontsize=16, ha='center', va='center', wrap=True) | |
| ax.axis('off') | |
| return fig | |
| def linear_interpolation(x, y, x_interp): | |
| return np.interp(x_interp, x, y) | |
| def quadratic_interpolation(x, y, x_interp): | |
| coeffs = np.polyfit(x, y, 2) | |
| return np.polyval(coeffs, x_interp) | |
| def lagrange_interpolation(x, y, x_interp): | |
| n = len(x) | |
| y_interp = np.zeros_like(x_interp, dtype=float) | |
| for i in range(n): | |
| p = y[i] | |
| for j in range(n): | |
| if i != j: | |
| p = p * (x_interp - x[j]) / (x[i] - x[j]) | |
| y_interp += p | |
| return y_interp | |
| def newton_forward_interpolation(x, y, x_interp): | |
| n = len(x) | |
| h = x[1] - x[0] # Assuming uniform spacing for simplicity | |
| F = [[0 for _ in range(n)] for _ in range(n)] | |
| for i in range(n): | |
| F[i][0] = y[i] | |
| for j in range(1, n): | |
| for i in range(n - j): | |
| F[i][j] = F[i+1][j-1] - F[i][j-1] | |
| def newton_forward(x_val): | |
| u = (x_val - x[0]) / h | |
| result = y[0] | |
| term = 1 | |
| for i in range(1, n): | |
| term *= (u - i + 1) / i | |
| result += term * F[0][i] | |
| return result | |
| return np.array([newton_forward(xi) for xi in x_interp]) | |
| def newton_backward_interpolation(x, y, x_interp): | |
| n = len(x) | |
| h = x[1] - x[0] # Assuming uniform spacing for simplicity | |
| F = [[0 for _ in range(n)] for _ in range(n)] | |
| for i in range(n): | |
| F[i][0] = y[i] | |
| for j in range(1, n): | |
| for i in range(n - 1, j - 1, -1): | |
| F[i][j] = F[i][j-1] - F[i-1][j-1] | |
| def newton_backward(x_val): | |
| u = (x_val - x[-1]) / h | |
| result = y[-1] | |
| term = 1 | |
| for i in range(1, n): | |
| term *= (u + i - 1) / i | |
| result += term * F[n-1][i] | |
| return result | |
| return np.array([newton_backward(xi) for xi in x_interp]) | |
| def create_and_edit_plot(x, y, x_interp, y_interp, method, plot_title, x_label, y_label, legend_position, label_size, log_x, x_predict=None, y_predict=None): | |
| fig, ax = plt.subplots(figsize=(10, 6)) | |
| if log_x: | |
| # Ensure all x-values are positive before setting log scale | |
| if np.any(np.array(x) <= 0): | |
| return create_error_plot("Error: All x values must be positive for logarithmic scale."), \ | |
| '<p style="color: red;">Error: All x values must be positive for logarithmic scale.</p>' | |
| ax.set_xscale('log') | |
| ax.scatter(x, y, color='red', label='Input points') | |
| ax.plot(x_interp, y_interp, label=f'{method} interpolant') | |
| ax.set_xlabel(x_label, fontsize=label_size) | |
| ax.set_ylabel(y_label, fontsize=label_size) | |
| ax.set_title(plot_title, fontsize=label_size + 2) | |
| ax.legend(loc=legend_position, fontsize=label_size - 2) | |
| ax.tick_params(axis='both', which='major', labelsize=label_size - 2) | |
| ax.grid(True) | |
| if x_predict is not None and y_predict is not None: | |
| ax.scatter([x_predict], [y_predict], color='green', s=100, label='Predicted point') | |
| ax.legend(loc=legend_position, fontsize=label_size - 2) | |
| return fig | |
| def interpolate_and_plot(x_input, y_input, x_predict, method, plot_title, x_label, y_label, legend_position, label_size, log_x): | |
| try: | |
| x = np.array([float(val.strip()) for val in x_input.split(',')]) | |
| y = np.array([float(val.strip()) for val in y_input.split(',')]) | |
| except ValueError: | |
| error_msg = "Error: Invalid input. Please enter comma-separated numbers." | |
| return create_error_plot(error_msg), f'<p style="color: red;">{error_msg}</p>' | |
| if len(x) != len(y): | |
| error_msg = "Error: Number of x and y values must be the same." | |
| return create_error_plot(error_msg), f'<p style="color: red;">{error_msg}</p>' | |
| if len(x) < 2: | |
| error_msg = "Error: At least two points are required for interpolation." | |
| return create_error_plot(error_msg), f'<p style="color: red;">{error_msg}</p>' | |
| x_interp = np.linspace(min(x), max(x), 100) | |
| # Interpolation method selection | |
| if method == "Linear": | |
| if len(x) < 2: | |
| error_msg = "Error: At least two points are required for linear interpolation." | |
| return create_error_plot(error_msg), f'<p style="color: red;">{error_msg}</p>' | |
| y_interp = linear_interpolation(x, y, x_interp) | |
| elif method == "Quadratic": | |
| if len(x) < 3: | |
| error_msg = "Error: At least three points are required for quadratic interpolation." | |
| return create_error_plot(error_msg), f'<p style="color: red;">{error_msg}</p>' | |
| y_interp = quadratic_interpolation(x, y, x_interp) | |
| elif method == "Lagrange": | |
| y_interp = lagrange_interpolation(x, y, x_interp) | |
| elif method == "Newton Forward": | |
| if not np.allclose(np.diff(x), x[1] - x[0]): | |
| error_msg = "Error: Newton Forward method requires uniform x spacing." | |
| return create_error_plot(error_msg), f'<p style="color: red;">{error_msg}</p>' | |
| y_interp = newton_forward_interpolation(x, y, x_interp) | |
| elif method == "Newton Backward": | |
| if not np.allclose(np.diff(x), x[1] - x[0]): | |
| error_msg = "Error: Newton Backward method requires uniform x spacing." | |
| return create_error_plot(error_msg), f'<p style="color: red;">{error_msg}</p>' | |
| y_interp = newton_backward_interpolation(x, y, x_interp) | |
| else: | |
| error_msg = "Error: Invalid interpolation method selected." | |
| return create_error_plot(error_msg), f'<p style="color: red;">{error_msg}</p>' | |
| # Predict y value for given x | |
| if x_predict is not None: | |
| try: | |
| x_predict = float(x_predict) | |
| if x_predict < min(x) or x_predict > max(x): | |
| error_msg = f"Error: Prediction x value must be between {min(x)} and {max(x)}." | |
| fig = create_and_edit_plot(x, y, x_interp, y_interp, method, plot_title, x_label, y_label, legend_position, label_size, log_x) | |
| return fig, f'<p style="color: red;">{error_msg}</p>' | |
| #return create_error_plot(error_msg), f'<p style="color: red;">{error_msg}</p>' | |
| y_predict = np.interp(x_predict, x_interp, y_interp) | |
| fig = create_and_edit_plot(x, y, x_interp, y_interp, method, plot_title, x_label, y_label, legend_position, label_size, log_x, x_predict, y_predict) | |
| return fig, f"Predicted y value for x = {x_predict}: {y_predict:.4f}" | |
| except ValueError: | |
| error_msg = "Error: Invalid input for x prediction. Please enter a number." | |
| return create_error_plot(error_msg), f'<p style="color: red;">{error_msg}</p>' | |
| fig = create_and_edit_plot(x, y, x_interp, y_interp, method, plot_title, x_label, y_label, legend_position, label_size, log_x) | |
| return fig, None | |
| def toggle_plot_options(show_options): | |
| return not show_options, gr.update(visible=not show_options) | |
| with gr.Blocks(theme=gr.themes.Base()) as iface: | |
| #gr.Markdown("# Interpolation App") | |
| gr.Markdown('<h1 style="text-align:center;">Interpolation App</h1>') | |
| gr.Markdown("Enter x and y values to see the interpolation graph") | |
| show_options = gr.State(False) | |
| with gr.Row(): | |
| with gr.Column(): | |
| x_input = gr.Textbox(label="X values (comma-separated)", value="1,2,3") | |
| y_input = gr.Textbox(label="Y values (comma-separated)", value="1,8,27") | |
| x_predict = gr.Number(label="X value to predict (optional)", value=lambda: None) | |
| method = gr.Radio(["Linear", "Quadratic", "Lagrange", "Newton Forward", "Newton Backward"], label="Interpolation Method", value="Linear") | |
| submit_btn = gr.Button("Generate Plot", variant="primary", elem_id="submit-btn") | |
| edit_plot_btn = gr.Button("Edit Plot", variant="secondary") | |
| with gr.Column(): | |
| plot_output = gr.Plot(label="Interpolation Plot") | |
| result_output = gr.HTML(label="Result or Error Message") | |
| plot_options = gr.Column(visible=False) | |
| with plot_options: | |
| plot_title = gr.Textbox(label="Plot Title", value="Interpolation Plot") | |
| x_label = gr.Textbox(label="X-axis Label", value="x") | |
| y_label = gr.Textbox(label="Y-axis Label", value="y") | |
| legend_position = gr.Dropdown(["best", "upper right", "upper left", "lower left", "lower right", "right", "center left", "center right", "lower center", "upper center", "center"], label="Legend Position", value="best") | |
| label_size = gr.Slider(minimum=8, maximum=24, step=1, label="Label Size", value=16) | |
| log_x = gr.Checkbox(label="Log scale for X-axis", value=False) | |
| edit_plot_btn.click( | |
| toggle_plot_options, | |
| inputs=[show_options], | |
| outputs=[show_options, plot_options] | |
| ) | |
| inputs = [x_input, y_input, x_predict, method, plot_title, x_label, y_label, legend_position, label_size, log_x] | |
| outputs = [plot_output, result_output] | |
| submit_btn.click(interpolate_and_plot, inputs=inputs, outputs=outputs) | |
| iface.launch() | |