Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,13 @@ For information on other coverage report formats, see https://pytest-cov.readthe

Documentation
-------------
* The documentation will be hosted on GitHub pages.
* It will be written in reStructuredText format and built via Sphinx.
The documentation is hosted using GitHub pages at [https://rascalsoftware.github.io/RasCAL-2/](https://rascalsoftware.github.io/RasCAL-2/).
The documentation should be built using the provided Sphinx make file. The reStructuredText source is in the **doc**
folder while the build will be placed in the **doc/build** folder.

cd doc
make clean
make html

Style guidelines
----------------
Expand All @@ -55,7 +60,7 @@ Style guidelines

How to build the executable
---------------------------
This script will create the executable for the software in the **packaging/bundle** folder.
The script below will create the executable for the software in the **packaging/bundle** folder.

cd packaging
python build_exe.py
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.23183417.svg)](https://doi.org/10.5281/zenodo.23183417)
[![license](https://img.shields.io/github/license/RascalSoftware/RasCAL-2.svg)](https://github.com/RascalSoftware/RasCAL-2/blob/master/LICENSE)
[![release](https://img.shields.io/github/release/RascalSoftware/RasCAL-2.svg)](https://github.com/RascalSoftware/RasCAL-2/releases)
[![Unit Tests](https://github.com/RascalSoftware/RasCAL-2/actions/workflows/unit_tests.yml/badge.svg)](https://github.com/RascalSoftware/RasCAL-2/actions/workflows/unit_tests.yml)
[![Unit Tests](https://github.com/RascalSoftware/RasCAL-2/actions/workflows/unit_tests.yaml/badge.svg)](https://github.com/RascalSoftware/RasCAL-2/actions/workflows/unit_tests.yaml)



Expand Down
1 change: 1 addition & 0 deletions rascal2/core/worker.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ def run(self):
self.job_failed.emit(e, self._args)

def stop(self):
"""Stop the worker thread."""
self.stopped = True
self.quit()
self.wait()
Expand Down
8 changes: 8 additions & 0 deletions rascal2/dialogs/settings_dialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ def reset_default_settings(self) -> None:
self.accept()

def cancel_settings(self):
"""Revert changes and close dialog."""
if SETTINGS.style != self.settings.style:
change_ui_style(SETTINGS.style)
self.reject()
Expand Down Expand Up @@ -200,6 +201,13 @@ def open_folder_selector(self) -> None:
self.changed = True

def set_matlab_rat_dir(self, clear=False):
"""Set the path of the MATLAB RAT directory.

Parameters
----------
clear : bool, default: False
Indicates current path of the RAT directory should be cleared.
"""
if clear:
self.rat_path.setText("")
get_global_settings().remove("matlab_rat_path")
Expand Down
20 changes: 19 additions & 1 deletion rascal2/dialogs/startup_dialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,13 @@ def reject(self):
self.parent().startup_dlg.setVisible(True)

def project_start_success(self, warning):
"""Update UI after successful project creation succeeds.

Parameters
----------
warning : Warning | None
A warning to display to user.
"""
self.parent().presenter.initialise_ui()

if not self.parent().toolbar.isEnabled():
Expand All @@ -197,6 +204,16 @@ def project_start_success(self, warning):
message_box.exec()

def project_start_failed(self, exception, args):
"""Log and report exception if project creation fails.

Parameters
----------
exception : Exception
The raised exception.
args : Tuple
The arguments passed into function that threw exception.

"""
folder_name = args[0]
error = str(exception).strip().replace("\n", "")
message = f"The Project ({folder_name}) could not be opened because:\n\n{error}"
Expand Down Expand Up @@ -251,6 +268,7 @@ def verify_folder(folder_path: str) -> None:
raise ValueError("Folder already contains a project.")

def verify_name(self) -> None:
"""Verify a valid project name is given and show error to user."""
if self.project_name.text() == "":
self.project_name_error.show()
self.project_name.setProperty("error", True)
Expand Down Expand Up @@ -399,7 +417,7 @@ def load_project(self, item=None):

Parameters
----------
item : Optional[QtWidgets.QListWidgetItem]
item : QtWidgets.QListWidgetItem | None
item if load project was called from list widget.
"""
if isinstance(item, QtWidgets.QListWidgetItem):
Expand Down
1 change: 1 addition & 0 deletions rascal2/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ class Settings(BaseModel, validate_assignment=True, arbitrary_types_allowed=True
)

def model_post_init(self, __context: Any):
"""Update setting properties which are unset with the global setting values."""
global_settings = get_global_settings()
unset_settings = [s for s in self.model_fields if s not in self.model_fields_set]
for setting in unset_settings:
Expand Down
7 changes: 7 additions & 0 deletions rascal2/ui/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,13 @@ def save_project_as_script(self, save_path):
self.project.write_script(script=save_path)

def is_project_example(self):
"""Check if the project is an example.

Returns
-------
bool
Indicates the project is an example.
"""
return Path(self.save_path).is_relative_to(EXAMPLES_TEMP_PATH)

def load_project(self, load_path: str):
Expand Down
1 change: 1 addition & 0 deletions rascal2/ui/presenter.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ def initialise_ui(self):
self.view.enable_elements()

def update_title(self):
"""Update the window tile with the project save path."""
suffix = " [Example]" if self.model.is_project_example() else f"[{self.model.save_path}]"
self.view.setWindowTitle(
self.view.windowTitle().split(" - ")[0] + " - " + self.model.project.name + suffix,
Expand Down
13 changes: 11 additions & 2 deletions rascal2/widgets/inputs.py
Original file line number Diff line number Diff line change
Expand Up @@ -646,8 +646,17 @@ def show_progress(self):
self.setEnabled(False)
self.setText(f"{self.progress_text} ...")

def update_progress(self, current, total):
self.setText(f"{self.progress_text} - {current} of {total}")
def update_progress(self, completed, total):
"""Update the progress text.

Parameters
----------
completed : int
The number of completed steps.
total : int
The total number of steps.
"""
self.setText(f"{self.progress_text} - {completed} of {total}")

def hide_progress(self):
"""Hides busy indicator."""
Expand Down
62 changes: 41 additions & 21 deletions rascal2/widgets/plot.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,17 @@ def plot_with_blit(self, event: ratapi.events.PlotEventData):
self.reflectivity_plot.plot_with_blit(event)

def show_bayes_plots(self):
bayes_plots = BayesPlotsDialog(self.parent, self.reflectivity_plot.get_current_plot_settings())
"""Show modal dialog with Bayesian plots."""
plot_settings = {
"x_axis": self.reflectivity_plot.x_axis.currentText(),
"y_axis": self.reflectivity_plot.y_axis.currentText(),
"show_error_bar": self.reflectivity_plot.show_error_bar.checkState(),
"show_grid": self.reflectivity_plot.show_grid.checkState(),
"show_legend": self.reflectivity_plot.show_legend.checkState(),
"slider": self.reflectivity_plot.slider.value(),
}

bayes_plots = BayesPlotsDialog(self.parent, plot_settings)
bayes_plots.exec()

def clear(self):
Expand All @@ -74,7 +84,7 @@ def clear(self):
class BayesPlotsDialog(QtWidgets.QDialog):
"""The modal dialog for the Bayes plots."""

def __init__(self, parent, initial_plot_settings: list):
def __init__(self, parent, initial_plot_settings: dict):
super().__init__(parent)
self.parent = parent
self.resize_timer = 0
Expand Down Expand Up @@ -497,19 +507,8 @@ def make_figure(self) -> matplotlib.figure.Figure:

return figure

def get_current_plot_settings(self):
plot_settings = [
self.x_axis.currentText(),
self.y_axis.currentText(),
self.show_error_bar.checkState(),
self.show_grid.checkState(),
self.show_legend.checkState(),
self.slider.value(),
]

return plot_settings

def handle_control_changed(self):
"""Replot when the controls are updated."""
if self.blit_plot is None:
self.plot_event()
else:
Expand Down Expand Up @@ -658,13 +657,20 @@ def make_toolbar_widget(self):

return self.slider

def set_plot_settings(self, plot_settings: list):
self.x_axis.setCurrentText(plot_settings[0])
self.y_axis.setCurrentText(plot_settings[1])
self.show_error_bar.setCheckState(plot_settings[2])
self.show_grid.setCheckState(plot_settings[3])
self.show_legend.setCheckState(plot_settings[4])
self.slider.setValue(plot_settings[5])
def set_plot_settings(self, plot_settings: dict):
"""Change plot settings to values in the given dictionary.

Parameters
----------
plot_settings : dict
A dict of plot settings.
"""
self.x_axis.setCurrentText(plot_settings["x_axis"])
self.y_axis.setCurrentText(plot_settings["y_axis"])
self.show_error_bar.setCheckState(plot_settings["show_error_bar"])
self.show_grid.setCheckState(plot_settings["show_grid"])
self.show_legend.setCheckState(plot_settings["show_legend"])
self.slider.setValue(plot_settings["slider"])

def plot(self, project, results: ratapi.outputs.BayesResults):
"""Plot the shaded plot."""
Expand Down Expand Up @@ -761,6 +767,15 @@ def plot(self, _, results):
self.draw_plot()

def update_ui(self, current, total):
"""Update the progress of plotting.

Parameters
----------
current : int
The index of plot being drawn.
total: int
the total number of plots.
"""
if current + 1 == total:
self.update_label.setText("")
else:
Expand All @@ -771,6 +786,10 @@ def draw_plot(self):
raise NotImplementedError

def resize_canvas(self):
"""Resize the canvas and update figure size.

This was used as a hack to ensure plots are not squashed.
"""
self.canvas.setMinimumSize(900, 600)
self.update_figure_size()

Expand Down Expand Up @@ -808,6 +827,7 @@ def make_control_layout(self):
return layout

def toggle_plot_button(self):
"""Show plot button when parameters are selected."""
self.plot_button.setEnabled(len(self.param_combobox.selected_items()) != 0)

def update_ui(self, current, total):
Expand Down
13 changes: 13 additions & 0 deletions rascal2/widgets/project/lists.py
Original file line number Diff line number Diff line change
Expand Up @@ -853,6 +853,19 @@ def compose_widget(self, i: int, data_widget: Callable[[str], QtWidgets.QWidget]
return widget

def create_data_table(self, current_data):
"""Create data table widget for an item.

Parameters
----------
current_data : np.array
Data Array

Returns
-------
QtWidgets.QTableView
The table view widget for the item.

"""
model = ArrayTableModel(current_data)
widget = QtWidgets.QTableView()
widget.setMinimumSize(450, 150)
Expand Down
14 changes: 14 additions & 0 deletions rascal2/widgets/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,20 @@ def minimumSize(self):
return size

def do_layout(self, rect, test_only):
"""Compute the height of layout and set geometry if needed.

Parameters
----------
rect : QRect
Rect with position and width of layout used to compute height.
test_only : bool
Indicates if geometry should not be set.

Returns
-------
int
height for the layout.
"""
x = rect.x()
y = rect.y()
space_x = space_y = self.spacing()
Expand Down
Loading