diff --git a/doc/source/_static/custom.css b/doc/source/_static/custom.css index bc8e65a6..75be09fc 100644 --- a/doc/source/_static/custom.css +++ b/doc/source/_static/custom.css @@ -13,6 +13,55 @@ html[data-theme=dark] { --pst-color-secondary: var(--pst-color-primary); } +/* make sure the article container uses all available space */ +.bd-article-container { + max-width: 100% !important; +} + +.center{ + display:grid; + place-items:center; +} + +.button { + display: inline-block; + padding: 10px 18px; + background-color: #0969da; + color: #f8f8ff; + text-decoration: none; + border-radius: 6px; + cursor: pointer; +} + +.button:active, +.button:visited, +.button:visited:hover, +.button:visited:hover +{ + color: #f8f8ff; !important; +} + +.button:hover +{ + background-color: #e34234; + color: #f8f8ff; !important; +} + +.hide-header > h1:first-child { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border: 0; +} + +.bd-main .bd-content .bd-article-container{ + max-width:100%; +} + .toctree-wrapper li[class^=toctree-l]>a { font-size: medium !important; } diff --git a/doc/source/conf.py b/doc/source/conf.py index 48fc497a..4c5f1d99 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -54,6 +54,11 @@ ], } +html_sidebars = { + "index": [], + "install": [], + "example": [], +} rst_epilog = """ .. |Angstrom| replace:: :math:`\mathring{A}` @@ -65,4 +70,7 @@ .. |delete| image:: /images/delete.png :scale: 10 + +.. |options| image:: /images/settings.png + :scale: 10 """ diff --git a/doc/source/example.rst b/doc/source/example.rst index bac945d5..2dc09583 100644 --- a/doc/source/example.rst +++ b/doc/source/example.rst @@ -1,2 +1,30 @@ Examples ======== +A few examples are available in RasCAL-2 which demonstrate the supported model and calculation types. These +example projects are created from the |RAT examples| where more explanations about each example can be found. + +To open an example: + +.. image:: /images/load_examples.png + :scale: 80 + :alt: Open example project + :align: center + +1. Click **File > Open Project** in the main menu to open the load project dialog. +2. In the dialog, click the Examples tab to reveal a list of examples and click on the desired entry in the + examples list. + +This will copy the selected example project to a temporary directory so the user does not modify the original, then +open the copied project in RasCAL-2. The following examples are available in the examples list: + +1. **DSPC standard layers**: Reflectivity analysis of a floating bilayer of DSPC using standard layer model. +2. **DSPC custom layers**: Reflectivity analysis of a floating bilayer of DSPC using custom layer model. +3. **DSPC custom XY**: Reflectivity analysis of a floating bilayer of DSPC using custom XY model. +4. **domains standard layers**: Incoherent summing ('domains') from standard layer model. +5. **domains custom layers**: Incoherent summing ('domains') from custom layer model. +6. **domains custom XY**: Incoherent summing ('domains') from custom XY model. +7. **absorption**: Shows absorption (imaginary SLD) effect usually seen below the critical edge. + +.. |RAT Examples| raw:: html + + RAT API Examples diff --git a/doc/source/guide.rst b/doc/source/guide.rst index d489b869..e525b9e9 100644 --- a/doc/source/guide.rst +++ b/doc/source/guide.rst @@ -1,14 +1,56 @@ User Guide ========== - +RasCAL-2 is available for windows, linux, and macOS. Follow the instructions on the :doc:`/install` page to install and +start the software on your system. The following pages describe the user interface and features of RasCAL-2. .. toctree:: :titlesonly: - user/overview user/interface + user/structure user/control user/plot user/project user/terminal + user/features + user/settings + +Check for RasCAL-2 Updates +-------------------------- +RasCAL-2 automatically checks for updates when the software is opened. You can manually check for update by clicking +**Help > Check for Update** in the main menu + +After an update check, the software will notify the user if a new release is available and provide a hyperlink to +download the installer for the new version. + +.. image:: /images/update_dialog.png + :scale: 80 + :alt: Update Dialog showing Successful Check + :align: center + +.. note:: You can also stop the automatic update checks by unchecking the **Check for updates on startup** checkbox. + +Report Issues +------------- +When reporting a bug or crash, it is important to report the version of RasCAL-2 and provide the software logs so it is +easier to replicate and fix the issue. These information are present in the about dialog which can be opened by clicking +**Help > About** in the main menu. + +.. image:: /images/about_dialog.png + :scale: 80 + :alt: About Dialog + :align: center + +Exiting RasCAL-2 +---------------- +RasCAL-2 can be closed by clicking the **File > Exit** on the main menu in the software. If the current rasCAL-2 project +has been modified or has unsaved results, a message will pop up to prompt saving the Project. Press the **Save** button +to specify saving the project, the **Discard** button to specify not saving the project, or Cancel to abort the +operation and return to the software. + +.. image:: /images/unsaved_changes_dialog.png + :scale: 80 + :alt: Unsaved Changes Dialog + :align: center +.. note:: This dialog could look slightly different on linux or macOS. diff --git a/doc/source/images/about_dialog.png b/doc/source/images/about_dialog.png new file mode 100644 index 00000000..1a10134e Binary files /dev/null and b/doc/source/images/about_dialog.png differ diff --git a/doc/source/images/banner.png b/doc/source/images/banner.png new file mode 100644 index 00000000..07824e81 Binary files /dev/null and b/doc/source/images/banner.png differ diff --git a/doc/source/images/browse.png b/doc/source/images/browse.png new file mode 100644 index 00000000..a89ceba0 Binary files /dev/null and b/doc/source/images/browse.png differ diff --git a/doc/source/images/confirm_stop_dialog.png b/doc/source/images/confirm_stop_dialog.png new file mode 100644 index 00000000..594d324e Binary files /dev/null and b/doc/source/images/confirm_stop_dialog.png differ diff --git a/doc/source/images/load_examples.png b/doc/source/images/load_examples.png new file mode 100644 index 00000000..822e1d8a Binary files /dev/null and b/doc/source/images/load_examples.png differ diff --git a/doc/source/images/load_existing.png b/doc/source/images/load_existing.png new file mode 100644 index 00000000..bfefd464 Binary files /dev/null and b/doc/source/images/load_existing.png differ diff --git a/doc/source/images/load_rascal_1.png b/doc/source/images/load_rascal_1.png new file mode 100644 index 00000000..220261f7 Binary files /dev/null and b/doc/source/images/load_rascal_1.png differ diff --git a/doc/source/images/load_recent.png b/doc/source/images/load_recent.png new file mode 100644 index 00000000..0138ab94 Binary files /dev/null and b/doc/source/images/load_recent.png differ diff --git a/doc/source/images/new.png b/doc/source/images/new.png new file mode 100644 index 00000000..9f2f5dbe Binary files /dev/null and b/doc/source/images/new.png differ diff --git a/doc/source/images/new_project.png b/doc/source/images/new_project.png new file mode 100644 index 00000000..5c184d9c Binary files /dev/null and b/doc/source/images/new_project.png differ diff --git a/doc/source/images/redo.png b/doc/source/images/redo.png new file mode 100644 index 00000000..80d9a6ad Binary files /dev/null and b/doc/source/images/redo.png differ diff --git a/doc/source/images/save.png b/doc/source/images/save.png new file mode 100644 index 00000000..b86f515e Binary files /dev/null and b/doc/source/images/save.png differ diff --git a/doc/source/images/settings_general.png b/doc/source/images/settings_general.png new file mode 100644 index 00000000..8f99f90b Binary files /dev/null and b/doc/source/images/settings_general.png differ diff --git a/doc/source/images/settings_matlab.png b/doc/source/images/settings_matlab.png new file mode 100644 index 00000000..ff0296da Binary files /dev/null and b/doc/source/images/settings_matlab.png differ diff --git a/doc/source/images/settings_plot.png b/doc/source/images/settings_plot.png new file mode 100644 index 00000000..ee0e7d8d Binary files /dev/null and b/doc/source/images/settings_plot.png differ diff --git a/doc/source/images/startup_screen.png b/doc/source/images/startup_screen.png new file mode 100644 index 00000000..e561fcd5 Binary files /dev/null and b/doc/source/images/startup_screen.png differ diff --git a/doc/source/images/undo.png b/doc/source/images/undo.png new file mode 100644 index 00000000..89fd5064 Binary files /dev/null and b/doc/source/images/undo.png differ diff --git a/doc/source/images/undo_history.png b/doc/source/images/undo_history.png new file mode 100644 index 00000000..3b514020 Binary files /dev/null and b/doc/source/images/undo_history.png differ diff --git a/doc/source/images/unsaved_changes_dialog.png b/doc/source/images/unsaved_changes_dialog.png new file mode 100644 index 00000000..4d89840e Binary files /dev/null and b/doc/source/images/unsaved_changes_dialog.png differ diff --git a/doc/source/images/update_dialog.png b/doc/source/images/update_dialog.png new file mode 100644 index 00000000..453185e8 Binary files /dev/null and b/doc/source/images/update_dialog.png differ diff --git a/doc/source/index.rst b/doc/source/index.rst index ae6dba75..efe8c794 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -1,8 +1,18 @@ -RasCAL-2 -======== +.. rst-class:: hide-header -RasCAL-2 is a software for the analysis of multi-contrast neutron reflectometry data. -It is a graphical user interface (GUI) for the `Python RAT API `_. +Welcome to RasCAL-2 +=================== + +.. raw:: html + +

RasCAL-2 is a software for the analysis of multi-contrast neutron reflectometry data.

+

Successor to RasCAL-1 and the graphical user interface (GUI) for the Python RAT API.

+

Get Started Explore Examples

+
+ +.. image:: /images/banner.png + :scale: 100 + :align: center .. toctree:: diff --git a/doc/source/user/features.rst b/doc/source/user/features.rst new file mode 100644 index 00000000..a87eaa88 --- /dev/null +++ b/doc/source/user/features.rst @@ -0,0 +1,29 @@ +Other Features +============== +This page describes other useful features available in RasCAL-2 + +Undo and Redo +------------- +RasCAL-2 is designed so that changes made to the project, controls and results can be undone. You can undo +and redo an action by clicking the |undo| or redo |redo| buttons from the toolbar respectively. The history of +reversible actions can be viewed by clicking **Edit > Undo History**. This will open the undo history dialog which +shows a list of actions performed and the current action will be highlighted. Clicking on any entry in the list will +make that entry the current action by undoing or redoing until that action is reached. + +.. image:: /images/undo_history.png + :scale: 80 + :alt: Undo History Dialog + :align: center + +The following operations cannot be undone: + +* Visualization actions (e.g. changing the plot zoom, or arrangement of windows), +* Changes to the settings, +* Exporting plot, project or fits. + + +.. |undo| image:: /images/undo.png + :scale: 10 + +.. |redo| image:: /images/redo.png + :scale: 10 diff --git a/doc/source/user/interface.rst b/doc/source/user/interface.rst index 2b3e8b94..4282fca7 100644 --- a/doc/source/user/interface.rst +++ b/doc/source/user/interface.rst @@ -1,2 +1,77 @@ User Interface ============== +Starting the RasCAL-2 software would show a splash screen while the software is loading. When loading is complete, +the startup screen will be shown. + +.. image:: /images/startup_screen.png + :scale: 80 + :alt: RasCAL Startup Screen + :align: center + +At the top of the startup screen is the title bar which will show the name of the software and the project name and +path if a project is opened. Below the title bar is the menu bar and toolbar, which provides access to a number of +operations. At the center of the screen are options for creating or loading a RasCAL project. + +.. note:: Some operating systems can change the location and look of title and menu bar. + +Menus and Toolbar +----------------- +RasCAL-2 provides access to some actions in a menu bar under the tile bar. These actions are grouped into 5 +groups explained below. Clicking on a menu item will perform its associated action. + +.. note:: On startup, some menu items like the **Windows** menu will be disabled. These menu items will be enabled + after a project is created or loaded. + +1. **File** + * **New Project**: Create a new project. + * **Open Project**: Open a existing project or example project + * **Open RasCAL-1 Project**: Open a RasCAL-1 project. + * **Save**: Save changes to the current project. + * **Save To Folder**: Save current project to another folder. + * **Export as Script**: Export the project as a python script. + * **Export Fits**: Export the results as CSV files. + * **Settings**: Open the settings dialog. + * **Exit**: Close the RasCAL application. +2. **Edit** + * **Undo**: Undo the last action. + * **Redo**: Redo the last undone action. + * **Undo History**: View the action history. +3. **Windows** + * **Tile Windows**: Arrange windows in a tile formation. + * **Reset to Default**: Reset the windows locations and sizes to the user saved defaults. + * **Save Current Window Positions**: Save the current positions and sizes of the windows as the user default. +4. **Tools** + * **Show Sliders/Hide Sliders**: Show or hide slider view in the project window. see :ref:`about_sliders`. + * **Clear Terminal**: Clears the text in the terminal window. +5. **Help** + * **Help**: Open the documentation website in the browser. + * **Check for Update**: Check online for new RasCAL-2 version. + * **About**: Show information about RasCAL-2. + +RasCAL-2 also provides access to some actions in a toolbar below the menu bar. The toolbar actions are **New Project**, +**Open Project**, **Save**, **Undo**, **Redo**, **Settings**, and **Help**. Clicking on the appropriate icon in the +toolbar will perform its associated action. + +Window Management +----------------- +After creating or loading a project, the interface will display 4 sub-windows arranged by default in 2x2 irregular +grid. The sub-windows are + +* Plot window (top left) +* Project window (top right) +* Terminal window (bottom left) +* Controls window (bottom right) + +These sub-windows can be rearranged by clicking on the title bar of the sub-window and dragging the sub-window. The +sub-window can also be resized, minimised and maximized similar to the main window. It can be useful to make a +sub-window bigger or smaller to suit a workflow, after which the arrangement can be saved by clicking +**Windows > Save Current Window Positions** in the menu, this will make that arrangement the default and RasCAL will +use that saved arrangement whenever the software is started. + +If you move a sub-window and want to revert back to you saved arrangement, click **Windows > Reset to Default** in the +menu. If you want to revert to the original arrangement, click **Windows > Tile Windows** then click +**Windows > Save Current Window Positions** in the menu to save the arrangement. + + +.. note:: The sub-windows cannot be dragged outside the boundary of the main software window but only within the + centre area of the main window. diff --git a/doc/source/user/overview.rst b/doc/source/user/overview.rst deleted file mode 100644 index a63e1e79..00000000 --- a/doc/source/user/overview.rst +++ /dev/null @@ -1,2 +0,0 @@ -General Overview -================ diff --git a/doc/source/user/plot.rst b/doc/source/user/plot.rst index e8a00670..e9468374 100644 --- a/doc/source/user/plot.rst +++ b/doc/source/user/plot.rst @@ -107,9 +107,6 @@ The plot will be saved as png file with a white background by default, the backg by changing the **Export Background Colour** option to **none** in Settings dialog -.. |options| image:: /images/settings.png - :scale: 10 - .. |reset| image:: /images/refresh.png :scale: 10 diff --git a/doc/source/user/project.rst b/doc/source/user/project.rst index 72681818..a7463cb3 100644 --- a/doc/source/user/project.rst +++ b/doc/source/user/project.rst @@ -55,6 +55,8 @@ The project tabs help organise the components of a project, the following tabs e * :doc:`project/domains` * :doc:`project/contrasts` +.. _about_sliders: + Changing Fitted Parameter Values -------------------------------- Fitted parameters defined in the different project tabs can be modified in a single place using the slider view. diff --git a/doc/source/user/settings.rst b/doc/source/user/settings.rst new file mode 100644 index 00000000..48276a54 --- /dev/null +++ b/doc/source/user/settings.rst @@ -0,0 +1,50 @@ +Settings +======== +The settings for RasCAL-2 can be configured by clicking |options| in the toolbar or clicking File > Settings in the +main menu. The settings dialog has 3 tabs: + +1. **General**: + + .. image:: /images/settings_general.png + :scale: 80 + :alt: General Settings + :align: center + + * **Style**: This sets the active theme of RasCAL-2. The software can use the default **system** theme, a **light** + or a **dark** theme. + * **Editor Fontsize**: This is the font size of the internal custom file editor. + * **Matlab As Default Editor**: This indicates that should if Matlab should be used to open both Python and Matlab + custom files. + * **Live Recalculate**: This indicates the results should be recalculated and plotted whenever the user changes values + outside edit mode. This can be disabled if running the calculation is expensive. + * **Show Stop Calculation Warning**: This indicates a warning should be shown to user when stopping a run will lead + to result being lost. + + .. image:: /images/confirm_stop_dialog.png + :scale: 80 + :alt: Confirm Calculation Stop Dialog + :align: center + +2. **Plotting**: Setting related to plots. + + .. image:: /images/settings_plot.png + :scale: 80 + :alt: Plot Settings + :align: center + + * **Export Background Colour**: indicates if exported plot background should be white or transparent. + + +3. **Matlab**: Setting related to running Matlab custom files. + + .. image:: /images/settings_matlab.png + :scale: 80 + :alt: Matlab Settings + :align: center + + * **Current Matlab Directory**: This tells RasCAL-2 where the Matlab installation for custom files is located. On + Windows and Linux, this should be the folder path e.g *C:\\Program Files\\MATLAB\\R2023a* while on MacOS should be + the app e.g */Applications/MATLAB_R2023b.app*. The minimum supported MATLAB is 2023b. + * **Matlab RAT directory**: This tells RasCAL-2 to use the provided Matlab RAT files when running a Matlab custom + file. This could provide improved performance by avoiding switching in and out of Matlab code. Download and use + the latest version of RAT, set this to the path of the RAT folder e.g *C:\\RAT*. diff --git a/doc/source/user/structure.rst b/doc/source/user/structure.rst new file mode 100644 index 00000000..83c20793 --- /dev/null +++ b/doc/source/user/structure.rst @@ -0,0 +1,128 @@ +Project Structure +================= +A project in RasCAL-2 is a folder which contains the human-readable json files and other optional files such as +custom files required to run a calculation. A folder based project structure means projects can typically be shared by +copying the project folder. + +.. warning:: If you plan to share a project folder with custom files and/or run it on different machines, ensure that + RasCAL-2 is allowed to copy the custom files if it was outside the project folder (This is the default behaviour), + otherwise it will use an absolute path which could make the project fail to run. + +The primary files in a project folder are: + +* A *project.json* containing the model definition for the project. +* A *controls.json* containing the control procedure and configuration. + +The project folder could also have: + +* An optional *results.json* containing the result of the last run. +* Optional Custom files if RasCAL was allowed to copy them. + +Create New Project +------------------ +In the startup screen, click the **New Project** button to open the new project dialog. The new project dialog can +also be opened using the shortcut **Ctrl + N** or by clicking **File > New Project** in the main menu. + +.. tip:: You can also click the |new| icon on the toolbar. + +To create a new project: + +1. Type in the name of the project +2. Click the **Browse** button and navigate to the folder which will hold the project. This folder can have + files in it but must not contain a project already. +3. Click the **Create** button + +The new project dialog will close as soon as the project is created. + + +.. image:: /images/new_project.png + :scale: 80 + :alt: New Project Dialog + :align: center + +Load Existing Project +--------------------- +In the startup screen, click the **Import Existing Project** button to open the load project dialog. The load project +dialog can also be opened using the shortcut **Ctrl + O** or by clicking **File > Open Project** in the main menu. + +.. tip:: You can also click the |open| icon on the toolbar. + +To open an existing project: + +1. Click the **Browse** button, navigate to the project folder. +2. Click the **Load** button + +.. image:: /images/load_existing.png + :scale: 80 + :alt: Load Project Dialog + :align: center + + +To load a recently opened project (last 10), click the **Recent Projects** tab in the load project dialog, then select +the desired project from the list by clicking on the entry. + +.. image:: /images/load_recent.png + :scale: 80 + :alt: Open existing project + :align: center + +To load an example project, click the **Examples** tab in the load project dialog, then select the desired example +project from the list by clicking on the entry. + +Load RasCAL-1 Project +--------------------- +In the startup screen, click the **Import RasCAL-1 Project** button to open the load RasCAL-1 project dialog. The new +project dialog can also be opened by clicking **File > Open RasCAL-1 Project** in the main menu. + +To load a RasCAL-1 project: + +1. Click the **Browse** button, navigate to the folder with the RasCAL-1 project, and select the \*.mat file. +2. Click the **Load** button + +The load RasCAL-1 project dialog will close as soon as the project is created. + +.. note:: MATLAB is required to run RasCAL-1 custom projects so ensure it is setup properly. But RasCAL-1 standard + layers projects can be loaded and run without MATLAB. + +.. image:: /images/load_rascal_1.png + :scale: 80 + :alt: Load RasCAL-1 Project Dialog + :align: center + +Save a Project +-------------- +To save a project, press **Ctrl + S** or click **File > Save** in the main menu. + +.. tip:: You can also click the |save| icon on the toolbar. + +To save to a different folder, click **File > Save To Folder...** and navigate to the new folder in the file dialog. + +Export as Script +---------------- +The model definition of a project can be exported as a python script which can modified for further analysis. To export +as a script, click **File > Export as Script...**, navigate to the desired save location in the file dialog, enter a +name for the file and press the **Save** button. The exported script will require the ratapi python package to run so +|install ratapi| in your python environment. + +Export Fits +----------- +The resulting data from a fit can be exported for further analysis outside RasCAL-2 or for custom plotting. To export +fits, click **File > Export Fits...**, navigate to the desired save location in the file dialog, enter a name for the +file and press the **Save** button. All the data will be exported to zip which contains several comma separated value +(\*.csv) files, the name of each file will indicate the name of the data, the contrast number and domain number +(if applicable) e.g the file called **sldProfiles_contrast_1_domain_2.csv** is the sldProfiles data for contrast 1 and +domain 2 while **backgrounds_contrast_2.csv** is the background for contrast 2 and all or no specific domain. + + +.. |install ratapi| raw:: html + + install ratapi + +.. |new| image:: /images/new.png + :scale: 10 + +.. |open| image:: /images/browse.png + :scale: 10 + +.. |save| image:: /images/save.png + :scale: 10 diff --git a/rascal2/core/writer.py b/rascal2/core/writer.py index f7581906..940bcdb2 100644 --- a/rascal2/core/writer.py +++ b/rascal2/core/writer.py @@ -23,16 +23,16 @@ def write_result_to_zipped_csvs(filename, results): for i, array in enumerate(getattr(results, list_field)): text_buffer = StringIO() np.savetxt(text_buffer, array, fmt=fmt, delimiter=delimiter) - f.writestr(f"{list_field}_contrast{i}.csv", text_buffer.getvalue()) + f.writestr(f"{list_field}_contrast_{i + 1}.csv", text_buffer.getvalue()) for list_field in results_fields["double_list_fields"]: actual_list = getattr(results, list_field) for i in range(len(actual_list)): for j, array in enumerate(actual_list[i]): - domain = "" if len(actual_list[i]) == 1 else f"_domain{j}" + domain = "" if len(actual_list[i]) == 1 else f"_domain_{j + 1}" text_buffer = StringIO() np.savetxt(text_buffer, array, fmt=fmt, delimiter=delimiter) - f.writestr(f"{list_field}_contrast{i}{domain}.csv", text_buffer.getvalue()) + f.writestr(f"{list_field}_contrast_{i + 1}{domain}.csv", text_buffer.getvalue()) contrast_param_fields = [ "scalefactors", @@ -57,16 +57,16 @@ def write_result_to_zipped_csvs(filename, results): for i, array in enumerate(getattr(subclass, field)): text_buffer = StringIO() np.savetxt(text_buffer, array, fmt=fmt, delimiter=delimiter) - f.writestr(f"Bayes/{inner_class}_{field}_contrast{i}.csv", text_buffer.getvalue()) + f.writestr(f"Bayes/{inner_class}_{field}_contrast_{i + 1}.csv", text_buffer.getvalue()) for field in bayes_results_fields["double_list_fields"][inner_class]: actual_list = getattr(subclass, field) for i in range(len(actual_list)): for j, array in enumerate(actual_list[i]): - domain = "" if len(actual_list[i]) == 1 else f"_domain{j}" + domain = "" if len(actual_list[i]) == 1 else f"_domain_{j + 1}" text_buffer = StringIO() np.savetxt(text_buffer, array, fmt=fmt, delimiter=delimiter) - f.writestr(f"Bayes/{inner_class}_{field}_contrast{i}{domain}.csv", text_buffer.getvalue()) + f.writestr(f"Bayes/{inner_class}_{field}_contrast_{i + 1}{domain}.csv", text_buffer.getvalue()) for field in bayes_results_fields["array_fields"][inner_class]: array = getattr(subclass, field) diff --git a/rascal2/dialogs/settings_dialog.py b/rascal2/dialogs/settings_dialog.py index 36703431..d0be3733 100644 --- a/rascal2/dialogs/settings_dialog.py +++ b/rascal2/dialogs/settings_dialog.py @@ -158,21 +158,21 @@ def __init__(self): if not getattr(sys, "frozen", False): browse_button.setEnabled(False) desc_text = ( - "The current matlab path can only be changed when running in bundle.
" + "The current Matlab path can only be changed when running in bundle.
" "For non-bundle, You can change which Matlab to use by pip installing a " "different version
of matlabengine.
" ) matlab_dir_label.setText(f"{matlab_dir_label.text()}
{desc_text}") desc_label = QtWidgets.QLabel( - "MATLAB RAT Directory (Optional):
" - "Running fully in MATLAB can provide more performance for custom files." + "Matlab RAT directory (Optional):
" + "Running fully in Matlab can provide more performance for custom files." ) form_layout.addWidget(desc_label, 3, 0, 1, 6) self.rat_path = QtWidgets.QLineEdit(self) self.rat_path.setText(get_global_settings().value("matlab_rat_path", "")) self.rat_path.setReadOnly(True) - self.rat_path.setPlaceholderText("Select MATLAB RAT directory") + self.rat_path.setPlaceholderText("Select Matlab RAT directory") self.rat_path.setFocusPolicy(QtCore.Qt.FocusPolicy.NoFocus) browse_button = QtWidgets.QPushButton("Browse") diff --git a/rascal2/ui/presenter.py b/rascal2/ui/presenter.py index 241111e8..3badf669 100644 --- a/rascal2/ui/presenter.py +++ b/rascal2/ui/presenter.py @@ -122,7 +122,7 @@ def edit_controls(self, setting: str, value: Any): self.model.controls.model_validate({setting: value}) self.view.undo_stack.push(commands.EditControls({setting: value}, self)) - def save_project(self, save_as: bool = False, as_script: bool = False): + def save_project(self, save_as: bool = False): """Save the model. Parameters @@ -130,9 +130,6 @@ def save_project(self, save_as: bool = False, as_script: bool = False): save_as : bool Whether we are saving to the existing save path or to a specified folder. - as_script: bool - Whether we are saving the project as a script or not. - Returns ------- : bool @@ -151,14 +148,7 @@ def save_project(self, save_as: bool = False, as_script: bool = False): if not to_path: return False try: - if as_script: - filename = self.model.project.name.replace(" ", "_") - save_file = self.view.get_save_file("Save Project as Script", filename, "*.py") - if not save_file: - return - self.model.save_project_as_script(save_file) - else: - self.model.save_project(to_path) + self.model.save_project(to_path) except OSError as err: LOGGER.error(f"Failed to save project to {to_path}.\n", exc_info=err) else: @@ -181,6 +171,32 @@ def ask_to_save_project(self): return proceed + def export_as_script(self): + """Export the project as a Python script. + + Returns + ------- + : bool + Indicates if the project was saved. + """ + if self.view.project_widget.stacked_widget.currentIndex() != 0: + # User is still editing the project + self.view.show_message( + "The project window is still editing, please accept changes or cancel before saving to file." + ) + return False + + filename = self.model.project.name.replace(" ", "_") + save_file = self.view.get_save_file("Save Project as Script", filename, "*.py") + if not save_file: + return False + + try: + self.model.save_project_as_script(save_file) + except OSError as err: + LOGGER.error(f"Failed to save script to {save_file}.\n", exc_info=err) + return True + def export_fits(self): """Export results into multiple csv files in a zip file.""" if self.model.results is None: diff --git a/rascal2/ui/view.py b/rascal2/ui/view.py index a6508fbd..8ebd4605 100644 --- a/rascal2/ui/view.py +++ b/rascal2/ui/view.py @@ -134,12 +134,11 @@ def create_actions(self): self.save_as_action.setEnabled(False) self.disabled_elements.append(self.save_as_action) - self.save_as_script_action = QtGui.QAction("Save Project as &Script...", self) - self.save_as_script_action.setStatusTip("Save project as a script.") - self.save_as_script_action.setIcon(QtGui.QIcon(path_for("save-project.png"))) - self.save_as_script_action.triggered.connect(lambda: self.presenter.save_project(as_script=True)) - self.save_as_script_action.setEnabled(False) - self.disabled_elements.append(self.save_as_script_action) + self.export_as_script_action = QtGui.QAction("Export as &Script...", self) + self.export_as_script_action.setStatusTip("Export project as a script.") + self.export_as_script_action.triggered.connect(self.presenter.export_as_script) + self.export_as_script_action.setEnabled(False) + self.disabled_elements.append(self.export_as_script_action) self.undo_action = self.undo_stack.createUndoAction(self, "&Undo") self.undo_action.setStatusTip("Undo the last action") @@ -157,7 +156,7 @@ def create_actions(self): self.undo_view_action.setEnabled(False) self.disabled_elements.append(self.undo_view_action) - self.export_fits_action = QtGui.QAction("Export Fits", self) + self.export_fits_action = QtGui.QAction("Export Fits...", self) self.export_fits_action.setStatusTip("Export Result Data as CSV in a zip file.") self.export_fits_action.triggered.connect(self.presenter.export_fits) self.export_fits_action.setEnabled(False) @@ -235,8 +234,8 @@ def create_menus(self): file_menu.addSeparator() file_menu.addAction(self.save_project_action) file_menu.addAction(self.save_as_action) - file_menu.addAction(self.save_as_script_action) file_menu.addSeparator() + file_menu.addAction(self.export_as_script_action) file_menu.addAction(self.export_fits_action) file_menu.addSeparator() file_menu.addAction(self.settings_action) diff --git a/tests/core/test_writer.py b/tests/core/test_writer.py index c03f5a6f..9c3d9c11 100644 --- a/tests/core/test_writer.py +++ b/tests/core/test_writer.py @@ -42,7 +42,7 @@ def test_write_zipped_csv(result_file): if part == "Bayes": continue if part.isdigit(): - prop = prop[int(part)] + prop = prop[int(part) - 1] else: # underscore should be removed from r_stat part = part if part != "Rstat" else "R_stat" diff --git a/tests/ui/test_presenter.py b/tests/ui/test_presenter.py index 6a4c4bf2..4c63a888 100644 --- a/tests/ui/test_presenter.py +++ b/tests/ui/test_presenter.py @@ -204,14 +204,14 @@ def test_save_project(recent_projects_mock, presenter): recent_projects_mock.assert_called_with("new path/") -def test_save_project_as_script(presenter): +def test_export_project_as_script(presenter): """Test that projects can be saved as a script, optionally saved as a new folder.""" presenter.model.project = MagicMock() presenter.model.project.name = "test_name" presenter.model.controls = MagicMock() presenter.view.project_widget.stacked_widget.currentIndex = MagicMock(return_value=0) presenter.view.get_save_file = MagicMock(return_value="test_name.py") - presenter.save_project(as_script=True) + presenter.export_as_script() presenter.model.project.write_script.assert_called_once_with(script="test_name.py") diff --git a/tests/ui/test_view.py b/tests/ui/test_view.py index c3d126a0..53a5640b 100644 --- a/tests/ui/test_view.py +++ b/tests/ui/test_view.py @@ -179,9 +179,9 @@ def test_menu_element_present(test_view, submenu_name): "", "&Save", "Save To &Folder...", - "Save Project as &Script...", "", - "Export Fits", + "Export as &Script...", + "Export Fits...", "", "Settings", "",