Skip to content

Commit 5b0d288

Browse files
committed
code refactor
1 parent 6f5fd6f commit 5b0d288

File tree

1 file changed

+85
-58
lines changed

1 file changed

+85
-58
lines changed

src/main.py

Lines changed: 85 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222

2323
class FunctionPlotter(QMainWindow):
2424
"""
25-
A class representing the main window for the function plotter application.
25+
Main window for the function plotter application.
2626
2727
This class handles the GUI elements, user inputs, and plotting of mathematical functions
2828
using PySide2 for the GUI and Matplotlib for plotting.
@@ -33,100 +33,75 @@ class FunctionPlotter(QMainWindow):
3333
def __init__(self):
3434
super().__init__()
3535
self.setWindowTitle("Function Plotter")
36+
self.setup_ui()
3637

37-
# Initialize the central widget and main layout
38+
def setup_ui(self):
39+
"""Set up the user interface elements."""
3840
self.central_widget = QWidget()
3941
self.setCentralWidget(self.central_widget)
4042
self.layout = QVBoxLayout()
41-
self.input_layout = QHBoxLayout()
4243
self.central_widget.setLayout(self.layout)
4344

44-
# Initialize input fields for the function and range values
45-
self.function_input = QLineEdit()
46-
self.function_input.setPlaceholderText("Enter function of x, e.g., 5*x^3 + 2*x")
47-
self.input_layout.addWidget(self.function_input)
45+
self.input_layout = QHBoxLayout()
46+
self.function_input = self.create_line_edit(
47+
"Enter function of x, e.g., 5*x^3 + 2*x"
48+
)
49+
self.min_input = self.create_line_edit("Enter min value of x")
50+
self.max_input = self.create_line_edit("Enter max value of x")
4851

49-
self.min_input = QLineEdit()
50-
self.min_input.setPlaceholderText("Enter min value of x")
52+
self.input_layout.addWidget(self.function_input)
5153
self.input_layout.addWidget(self.min_input)
52-
53-
self.max_input = QLineEdit()
54-
self.max_input.setPlaceholderText("Enter max value of x")
5554
self.input_layout.addWidget(self.max_input)
56-
5755
self.layout.addLayout(self.input_layout)
5856

59-
# Initialize the plot button
6057
self.plot_button = QPushButton("Plot Function")
6158
self.plot_button.clicked.connect(self.plot_function)
6259
self.layout.addWidget(self.plot_button)
6360

64-
# Initialize the Matplotlib figure and canvas
6561
self.figure, self.ax = plt.subplots()
6662
self.canvas = FigureCanvas(self.figure)
6763
self.layout.addWidget(self.canvas)
6864

69-
def plot_function(self):
70-
"""
71-
Handles the plotting of the function based on user inputs.
65+
def create_line_edit(self, placeholder):
7266
"""
73-
function = self.function_input.text().replace(" ", "")
74-
min_x = self.min_input.text()
75-
max_x = self.max_input.text()
67+
Create a QLineEdit with a placeholder text.
7668
77-
# Validate inputs
78-
if not self.validate_inputs(function, min_x, max_x):
79-
return
80-
81-
try:
82-
min_x = float(min_x)
83-
# Make range from -1e20 to 1e20 whatever the input
84-
min_x = max(min(1e20, min_x), -1e20)
85-
max_x = float(max_x)
86-
# Make range from -1e20 to 1e20 whatever the input
87-
max_x = max(min(1e20, max_x), -1e20)
88-
89-
except ValueError:
90-
self.show_error_message("Min and Max values must be numbers.")
91-
return
69+
Parameters:
70+
- placeholder (str): The placeholder text for the QLineEdit.
9271
93-
if min_x >= max_x:
94-
self.show_error_message("Min value must be less than Max value.")
95-
return
72+
Returns:
73+
- QLineEdit: The created QLineEdit object.
74+
"""
75+
line_edit = QLineEdit()
76+
line_edit.setPlaceholderText(placeholder)
77+
return line_edit
9678

97-
if ("log10" in function or "sqrt" in function) and min_x < 0:
98-
self.show_error_message(
99-
"Min value must be non-negative for functions with log10 or sqrt."
100-
)
101-
return
79+
def plot_function(self):
80+
"""Handle the plotting of the function based on user inputs."""
81+
function = self.function_input.text().replace(" ", "")
82+
min_x, max_x = self.min_input.text(), self.max_input.text()
10283

103-
# deal with the case of division by zero ex(x/0)
104-
if "/0" in function:
105-
self.show_error_message("Division by zero is not allowed.")
84+
if not self.validate_inputs(function, min_x, max_x):
10685
return
10786

87+
min_x, max_x = self.parse_range(min_x, max_x)
10888
x = np.linspace(min_x, max_x, 400)
10989
if "log10" in function:
11090
x = np.where(
11191
x == 0, 1e-15, x
11292
) # Add a small value to x where x is 0 if log10 is in the function
93+
11394
try:
11495
y = eval(self.prepare_function(function, x))
11596
except Exception as e:
11697
self.show_error_message(f"Error in function evaluation: {e}")
11798
return
11899

119-
# Clear previous plot and plot new function
120-
self.ax.clear()
121-
self.ax.plot(x, y)
122-
self.ax.set_title(f"Plot of {function}")
123-
self.ax.set_xlabel("x")
124-
self.ax.set_ylabel("f(x)")
125-
self.canvas.draw()
100+
self.update_plot(x, y, function)
126101

127102
def validate_inputs(self, function, min_x, max_x):
128103
"""
129-
Validates the user inputs for the function and range values.
104+
Validate the user inputs for the function and range values.
130105
131106
Parameters:
132107
- function (str): The mathematical function entered by the user.
@@ -148,11 +123,47 @@ def validate_inputs(self, function, min_x, max_x):
148123
self.show_error_message("Min and Max values cannot be empty.")
149124
return False
150125

126+
try:
127+
min_x = float(min_x)
128+
max_x = float(max_x)
129+
except ValueError:
130+
self.show_error_message("Min and Max values must be numbers.")
131+
return False
132+
133+
if min_x >= max_x:
134+
self.show_error_message("Min value must be less than Max value.")
135+
return False
136+
137+
if ("log10" or "sqrt") in function and min_x < 0:
138+
self.show_error_message(
139+
"Min value must be non-negative for functions with log10 or sqrt."
140+
)
141+
return False
142+
143+
if "/0" in function:
144+
self.show_error_message("Division by zero is not allowed.")
145+
return False
146+
151147
return True
152148

149+
def parse_range(self, min_x, max_x):
150+
"""
151+
Parse and limit the range values to a valid range.
152+
153+
Parameters:
154+
- min_x (str): The minimum value of x entered by the user.
155+
- max_x (str): The maximum value of x entered by the user.
156+
157+
Returns:
158+
- tuple: The parsed and limited range values.
159+
"""
160+
min_x = max(min(1e20, float(min_x)), -1e20)
161+
max_x = max(min(1e20, float(max_x)), -1e20)
162+
return min_x, max_x
163+
153164
def prepare_function(self, function, x):
154165
"""
155-
Prepares the function for evaluation by replacing operators with their numpy equivalents.
166+
Prepare the function for evaluation by replacing operators with their numpy equivalents.
156167
157168
Parameters:
158169
- function (str): The mathematical function entered by the user.
@@ -164,14 +175,30 @@ def prepare_function(self, function, x):
164175
function = function.replace("^", "**")
165176
function = function.replace("log10", "np.log10")
166177
function = function.replace("sqrt", "np.sqrt")
167-
# if function is a constant (e.g. y=5)
178+
168179
if "x" not in function:
169180
function = f"{function}*np.ones_like(x)"
170181
return function
171182

183+
def update_plot(self, x, y, function):
184+
"""
185+
Update the plot with the new function.
186+
187+
Parameters:
188+
- x (np.ndarray): The array of x values.
189+
- y (np.ndarray): The array of y values.
190+
- function (str): The mathematical function entered by the user.
191+
"""
192+
self.ax.clear()
193+
self.ax.plot(x, y)
194+
self.ax.set_title(f"Plot of {function}")
195+
self.ax.set_xlabel("x")
196+
self.ax.set_ylabel("f(x)")
197+
self.canvas.draw()
198+
172199
def show_error_message(self, message):
173200
"""
174-
Displays an error message dialog.
201+
Display an error message dialog.
175202
176203
Parameters:
177204
- message (str): The error message to display.

0 commit comments

Comments
 (0)