from __future__ import annotations import numpy as np import plotly.express as px import math import plotly.graph_objects as go class Derivative: def __init__(self, start_stop_num: List[int, int, int] = [-10, 10, 200], expression: str = "x", function_name: str = None): start, stop, num = start_stop_num self.x = np.linspace(start= start, stop= stop, num = num) self.function_name = function_name if function_name else expression self.expression = expression self.h = 0.0001 self.y = None self.delta_y = None def _function(self): def _make_function(x): return eval(self.expression) self.y = _make_function(self.x) self.delta_y = _make_function(self.x + self.h) def _get_derivative(self): if self.delta_y is None or self.y is None: raise Exception("Define your y and delta_y first") self.derivative = (self.delta_y - self.y) / self.h return self.derivative def _plot_f(self): fig = px.scatter(x = self.x, y = self.y, title = self.function_name) return fig def _plot_derivative(self): fig = px.scatter(x = self.x, y = self.derivative, title = f"Derivative of {self.function_name}") return fig def get_slope_one_point(self, x): # using x and y, obtain the slope # y = eval(self.expression) math_expression = self.expression.replace("np", "math") def _make_function(x): return eval(math_expression) y = _make_function(x) delta_y = _make_function(x + self.h) slope = (delta_y - y) / self.h return slope, y def get_tangent_line_vals(self, x): slope, y = self.get_slope_one_point(x) tangent_line_y_vals = slope * (self.x - x) + y return y, tangent_line_y_vals def draw_tangent_line(self, x): y, tl_y_vals = self.get_tangent_line_vals(x) title = f"Tangent line at point({x},{round(y, 2)}) of {self.function_name}" if self.y is None: self._function() fig = go.Figure() fig.update_layout(title = title) fig.add_trace(go.Scatter(x = self.x, y = tl_y_vals, name = f"Tangent Line at ({x},{round(y, 2)})")) fig.add_trace(go.Scatter(x = self.x, y = self.y, name = self.function_name)) return fig def get_plots(self): return self._plot_f(), self._plot_derivative() def __call__(self): self._function() self._get_derivative() def get_fn(input: str): dev_obj = Derivative(expression = input) dev_obj() fn_fig, _ = dev_obj.get_plots() return fn_fig def get_dev(input: str): dev_obj = Derivative(expression = input) dev_obj() _, dev_fig = dev_obj.get_plots() return dev_fig def get_tangent_line(input_1: str, input_2: str): dev_obj = Derivative(expression = input_1) tl_fig = dev_obj.draw_tangent_line(int(input_2)) return tl_fig