Skip to content

Commit c131819

Browse files
authored
Merge pull request #39 from saroad2/support_polynomials
Support polynomials
2 parents a7ba27b + 8a3dea9 commit c131819

File tree

7 files changed

+164
-113
lines changed

7 files changed

+164
-113
lines changed

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ requires = [
1919
'--pre',
2020
'toga-chart>=0.1.0',
2121
'openpyxl>=3.0.4',
22-
'eddington>=0.0.16',
22+
'eddington>=0.0.17',
2323
]
2424

2525

src/eddington_gui/app.py

Lines changed: 65 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ class EddingtonGUI(toga.App): # pylint: disable=too-many-instance-attributes
4343
main_window: toga.Window
4444

4545
__a0: np.ndarray = None
46-
__fit_result: FittingResult = None
46+
__fitting_result: FittingResult = None
4747

4848
def startup(self):
4949
"""
@@ -57,29 +57,35 @@ def startup(self):
5757
main_box.add(HeaderBox())
5858

5959
self.input_file_box = InputFileBox(flex=1)
60-
self.input_file_box.add_handler(self.reset_fit_data)
60+
self.input_file_box.add_handler(self.reset_fitting_data)
6161
main_box.add(self.input_file_box)
6262

6363
self.fitting_function_box = FittingFunctionBox(flex=1)
64-
self.fitting_function_box.add_handler(lambda fit_func: self.reset_fit_result())
64+
self.fitting_function_box.add_handler(
65+
lambda fit_func: self.reset_fitting_result()
66+
)
6567
main_box.add(self.fitting_function_box)
6668

6769
self.initial_guess_box = InitialGuessBox()
68-
self.initial_guess_box.add_handler(lambda a0: self.reset_fit_result())
70+
self.initial_guess_box.add_handler(lambda a0: self.reset_fitting_result())
6971
self.fitting_function_box.add_handler(self.set_parameters_number)
7072
main_box.add(self.initial_guess_box)
7173

7274
self.data_columns_box = DataColumnsBox(flex=5)
73-
self.data_columns_box.add_handler(lambda fit_data: self.reset_fit_result())
75+
self.data_columns_box.add_handler(
76+
lambda fitting_data: self.reset_fitting_result()
77+
)
7478
self.input_file_box.on_csv_read = self.read_csv
7579
self.input_file_box.on_excel_read = self.read_excel
7680
self.input_file_box.on_select_file = self.select_default_sheet
7781

7882
self.plot_configuration_box = PlotConfigurationBox(flex=5)
7983
self.fitting_function_box.add_handler(
80-
self.plot_configuration_box.on_fit_function_load
84+
self.plot_configuration_box.on_fitting_function_load
85+
)
86+
self.data_columns_box.add_handler(
87+
self.plot_configuration_box.on_fitting_data_load
8188
)
82-
self.data_columns_box.add_handler(self.plot_configuration_box.on_fit_data_load)
8389

8490
main_box.add(
8591
toga.Box(
@@ -160,16 +166,16 @@ def startup(self):
160166
self.main_window.show()
161167

162168
@property
163-
def fit_result(self):
169+
def fitting_result(self):
164170
"""Getter of the fit result."""
165-
if self.__fit_result is None:
166-
self.__calculate_fit_result()
167-
return self.__fit_result
171+
if self.__fitting_result is None:
172+
self.__calculate_fitting_result()
173+
return self.__fitting_result
168174

169-
@fit_result.setter
170-
def fit_result(self, fit_result):
175+
@fitting_result.setter
176+
def fitting_result(self, fitting_result):
171177
"""Setter of the fit result."""
172-
self.__fit_result = fit_result
178+
self.__fitting_result = fitting_result
173179

174180
def read_csv(self, filepath):
175181
"""
@@ -183,7 +189,7 @@ def read_csv(self, filepath):
183189
self.data_columns_box.read_csv(filepath)
184190
except FittingDataError as error:
185191
self.main_window.error_dialog(title="Input data error", message=str(error))
186-
self.data_columns_box.fit_data = None
192+
self.data_columns_box.fitting_data = None
187193
self.input_file_box.file_path = None
188194

189195
def read_excel(self, filepath, sheet):
@@ -199,57 +205,59 @@ def read_excel(self, filepath, sheet):
199205
self.data_columns_box.read_excel(filepath, sheet)
200206
except FittingDataError as error:
201207
self.main_window.error_dialog(title="Input data error", message=str(error))
202-
self.data_columns_box.fit_data = None
208+
self.data_columns_box.fitting_data = None
203209
self.input_file_box.selected_sheet = None
204210

205211
def choose_records(self, widget): # pylint: disable=unused-argument
206212
"""Open the choose records window."""
207-
if self.data_columns_box.fit_data is None:
213+
if self.data_columns_box.fitting_data is None:
208214
self.main_window.info_dialog(
209215
title="Choose Records", message="No data been given yet"
210216
)
211217
return
212-
window = RecordsChoiceWindow(fit_data=self.data_columns_box.fit_data)
218+
window = RecordsChoiceWindow(fitting_data=self.data_columns_box.fitting_data)
213219
window.show()
214-
self.reset_fit_result()
220+
self.reset_fitting_result()
215221
self.initial_guess_box.reset_initial_guess()
216222

217223
def fit(self, widget): # pylint: disable=unused-argument
218224
"""Handler for the "fit" button."""
219225
try:
220-
if self.fit_result is None:
226+
if self.fitting_result is None:
221227
self.main_window.info_dialog(
222228
title="Fit Result", message="Nothing to fit yet"
223229
)
224230
return
225231
except EddingtonException:
226232
return
227-
self.main_window.info_dialog(title="Fit Result", message=str(self.fit_result))
233+
self.main_window.info_dialog(
234+
title="Fit Result", message=str(self.fitting_result)
235+
)
228236

229237
def plot_data(self, widget): # pylint: disable=unused-argument
230238
"""Handler for the "plot data" button."""
231-
if self.data_columns_box.fit_data is None:
239+
if self.data_columns_box.fitting_data is None:
232240
self.show_nothing_to_plot()
233241
else:
234242
self.show_figure_window(
235243
self.plot_configuration_box.plot_data(
236-
data=self.data_columns_box.fit_data
244+
data=self.data_columns_box.fitting_data
237245
)
238246
)
239247

240248
def plot_initial_guess(self, widget): # pylint: disable=unused-argument
241249
"""Handler for the "plot initial guess" button."""
242250
try:
243251
if (
244-
self.data_columns_box.fit_data is None
252+
self.data_columns_box.fitting_data is None
245253
or self.initial_guess_box.a0 is None # noqa: W503
246254
):
247255
self.show_nothing_to_plot()
248256
return
249257
self.show_figure_window(
250258
self.plot_configuration_box.plot_fitting(
251-
func=self.fitting_function_box.fit_function,
252-
data=self.data_columns_box.fit_data,
259+
func=self.fitting_function_box.fitting_function,
260+
data=self.data_columns_box.fitting_data,
253261
a=self.initial_guess_box.a0,
254262
)
255263
)
@@ -261,14 +269,14 @@ def plot_initial_guess(self, widget): # pylint: disable=unused-argument
261269
def plot(self, widget): # pylint: disable=unused-argument
262270
"""Handler for the "plot fitting" button."""
263271
try:
264-
if self.fit_result is None:
272+
if self.fitting_result is None:
265273
self.show_nothing_to_plot()
266274
return
267275
self.show_figure_window(
268276
self.plot_configuration_box.plot_fitting(
269-
func=self.fitting_function_box.fit_function,
270-
data=self.data_columns_box.fit_data,
271-
a=self.fit_result.a,
277+
func=self.fitting_function_box.fitting_function,
278+
data=self.data_columns_box.fitting_data,
279+
a=self.fitting_result.a,
272280
)
273281
)
274282
except EddingtonException as error:
@@ -279,14 +287,14 @@ def plot(self, widget): # pylint: disable=unused-argument
279287
def residuals(self, widget): # pylint: disable=unused-argument
280288
"""Handler for the "residuals" button."""
281289
try:
282-
if self.fit_result is None:
290+
if self.fitting_result is None:
283291
self.show_nothing_to_plot()
284292
return
285293
self.show_figure_window(
286294
self.plot_configuration_box.plot_residuals(
287-
func=self.fitting_function_box.fit_function,
288-
data=self.data_columns_box.fit_data,
289-
a=self.fit_result.a,
295+
func=self.fitting_function_box.fitting_function,
296+
data=self.data_columns_box.fitting_data,
297+
a=self.fitting_result.a,
290298
)
291299
)
292300
except EddingtonException as error:
@@ -307,7 +315,7 @@ def choose_output_dir(self, widget): # pylint: disable=unused-argument
307315
def save_to_output_dir(self, widget): # pylint: disable=unused-argument
308316
"""Handler for the "save to output directory" button."""
309317
try:
310-
if self.fit_result is None:
318+
if self.fitting_result is None:
311319
self.show_nothing_to_plot()
312320
return
313321
except EddingtonException:
@@ -321,17 +329,17 @@ def save_to_output_dir(self, widget): # pylint: disable=unused-argument
321329
output_dir = Path(self.output_directory_input.value)
322330
if not output_dir.exists():
323331
output_dir.mkdir()
324-
func_name = self.fitting_function_box.fit_function.name
325-
self.fit_result.save_txt(output_dir / f"{func_name}_result.txt")
332+
func_name = self.fitting_function_box.fitting_function.name
333+
self.fitting_result.save_txt(output_dir / f"{func_name}_result.txt")
326334
self.plot_configuration_box.plot_fitting(
327-
func=self.fitting_function_box.fit_function,
328-
data=self.data_columns_box.fit_data,
329-
a=self.fit_result.a,
335+
func=self.fitting_function_box.fitting_function,
336+
data=self.data_columns_box.fitting_data,
337+
a=self.fitting_result.a,
330338
).savefig(output_dir / f"{func_name}_fitting.png")
331339
self.plot_configuration_box.plot_residuals(
332-
func=self.fitting_function_box.fit_function,
333-
data=self.data_columns_box.fit_data,
334-
a=self.fit_result.a,
340+
func=self.fitting_function_box.fitting_function,
341+
data=self.data_columns_box.fitting_data,
342+
a=self.fitting_result.a,
335343
).savefig(output_dir / f"{func_name}_residuals.png")
336344
self.main_window.info_dialog(
337345
title="Save output", message="All plots have been saved successfully!"
@@ -347,13 +355,13 @@ def show_figure_window(fig):
347355
figure_window = FigureWindow(fig)
348356
figure_window.show()
349357

350-
def reset_fit_data(self):
358+
def reset_fitting_data(self):
351359
"""Set fit data to None."""
352-
self.data_columns_box.fit_data = None
360+
self.data_columns_box.fitting_data = None
353361

354-
def reset_fit_result(self):
362+
def reset_fitting_result(self):
355363
"""Set fit result to None."""
356-
self.fit_result = None
364+
self.fitting_result = None
357365

358366
def set_parameters_number(self, func):
359367
"""Set number of parameters."""
@@ -362,21 +370,21 @@ def set_parameters_number(self, func):
362370
else:
363371
self.initial_guess_box.n = func.n
364372

365-
def __calculate_fit_result(self):
373+
def __calculate_fitting_result(self):
366374
if (
367-
self.data_columns_box.fit_data is None
368-
or self.fitting_function_box.fit_function is None # noqa: W503
375+
self.data_columns_box.fitting_data is None
376+
or self.fitting_function_box.fitting_function is None # noqa: W503
369377
):
370-
self.fit_result = None
378+
self.fitting_result = None
371379
return
372380
try:
373-
self.fit_result = fit(
374-
data=self.data_columns_box.fit_data,
375-
func=self.fitting_function_box.fit_function,
381+
self.fitting_result = fit(
382+
data=self.data_columns_box.fitting_data,
383+
func=self.fitting_function_box.fitting_function,
376384
a0=self.initial_guess_box.a0,
377385
)
378386
except EddingtonException as error:
379-
self.fit_result = None
387+
self.fitting_result = None
380388
self.main_window.error_dialog(title="Fit result error", message=str(error))
381389
raise error
382390

@@ -389,15 +397,15 @@ def select_default_sheet(self):
389397
for sheet in self.input_file_box.sheets_options:
390398
if sheet != NO_VALUE:
391399
try:
392-
self.data_columns_box.fit_data = FittingData.read_from_excel(
400+
self.data_columns_box.fitting_data = FittingData.read_from_excel(
393401
Path(self.input_file_box.file_path), sheet
394402
)
395403
self.input_file_box.selected_sheet = sheet
396404
return
397405
except FittingDataError:
398406
pass
399407

400-
if self.data_columns_box.fit_data is None:
408+
if self.data_columns_box.fitting_data is None:
401409
self.main_window.error_dialog(
402410
title="Input data error",
403411
message=(

src/eddington_gui/boxes/data_columns_box.py

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ class DataColumnsBox(toga.Box): # pylint: disable=too-many-instance-attributes
2222
y_selection: toga.Selection
2323
yerr_selection: toga.Selection
2424

25-
__fit_data: Union[FittingData] = None
25+
__fitting_data: Union[FittingData] = None
2626
__handlers: List[Callable] = []
2727

2828
def __init__(self, flex):
@@ -43,23 +43,23 @@ def __init__(self, flex):
4343
)
4444

4545
@property
46-
def fit_data(self):
46+
def fitting_data(self):
4747
"""Fit data getter."""
48-
return self.__fit_data
48+
return self.__fitting_data
4949

50-
@fit_data.setter
51-
def fit_data(self, fit_data: FittingData):
50+
@fitting_data.setter
51+
def fitting_data(self, fitting_data: FittingData):
5252
"""
5353
Fit data setter.
5454
5555
If fit data is None, reset all selections
5656
"""
57-
self.__fit_data = fit_data
58-
if fit_data is None:
57+
self.__fitting_data = fitting_data
58+
if fitting_data is None:
5959
self.clear_selections()
6060
return
61-
items = list(fit_data.data.keys())
62-
used_columns = self.fit_data.used_columns
61+
items = list(fitting_data.data.keys())
62+
used_columns = self.fitting_data.used_columns
6363
self.set_items(self.x_selection, items, used_columns.x)
6464
self.set_items(self.xerr_selection, items, used_columns.xerr)
6565
self.set_items(self.y_selection, items, used_columns.y)
@@ -131,24 +131,24 @@ def set_columns(self, widget): # pylint: disable=unused-argument
131131
"""Set columns of the fit data based on the selection of the user."""
132132
if not self.selection_enabled:
133133
return
134-
self.fit_data.x_column = self.x_selection.value
135-
self.fit_data.xerr_column = self.xerr_selection.value
136-
self.fit_data.y_column = self.y_selection.value
137-
self.fit_data.yerr_column = self.yerr_selection.value
134+
self.fitting_data.x_column = self.x_selection.value
135+
self.fitting_data.xerr_column = self.xerr_selection.value
136+
self.fitting_data.y_column = self.y_selection.value
137+
self.fitting_data.yerr_column = self.yerr_selection.value
138138
self.run_handlers()
139139

140140
def run_handlers(self):
141141
"""Whenever fit data is updated, run handlers to notify other components."""
142142
for handler in self.__handlers:
143-
handler(self.fit_data)
143+
handler(self.fitting_data)
144144

145145
def read_csv(self, filepath):
146146
"""
147147
Read data from csv file.
148148
149149
:param filepath: path of the csv file
150150
"""
151-
self.fit_data = FittingData.read_from_csv(filepath)
151+
self.fitting_data = FittingData.read_from_csv(filepath)
152152

153153
def read_excel(self, filepath, sheet):
154154
"""
@@ -157,7 +157,7 @@ def read_excel(self, filepath, sheet):
157157
:param filepath: path of the excel file
158158
:param sheet: sheet from which to read the data.
159159
"""
160-
self.fit_data = FittingData.read_from_excel(filepath, sheet)
160+
self.fitting_data = FittingData.read_from_excel(filepath, sheet)
161161

162162
def __add_column_option(self, label, on_select):
163163

0 commit comments

Comments
 (0)