diff --git a/.github/gui1.png b/.github/gui1.png index 2bd11f3..c85ac0d 100644 Binary files a/.github/gui1.png and b/.github/gui1.png differ diff --git a/.github/gui1_old.png b/.github/gui1_old.png new file mode 100644 index 0000000..2bd11f3 Binary files /dev/null and b/.github/gui1_old.png differ diff --git a/.github/gui2.png b/.github/gui2.png index 8bc1327..2893711 100644 Binary files a/.github/gui2.png and b/.github/gui2.png differ diff --git a/.github/gui7.png b/.github/gui7.png index 0e8a3dc..d19493c 100644 Binary files a/.github/gui7.png and b/.github/gui7.png differ diff --git a/.github/gui8.png b/.github/gui8.png index ad571b5..cf60367 100644 Binary files a/.github/gui8.png and b/.github/gui8.png differ diff --git a/README.md b/README.md index 3a0656f..32d1ceb 100644 --- a/README.md +++ b/README.md @@ -41,10 +41,10 @@ đź“„ Cite us

-This is a basic graphical user interface intended for users of the [NiaAML](https://github.com/firefly-cpp/NiaAML) Python package. +A graphical user interface for building and running machine learning pipelines using the [NiaAML](https://github.com/firefly-cpp/NiaAML) framework. This GUI now supports **block-based pipeline composition**, drag-and-drop components, visual connections, and CSV editing. * **Free software:** MIT license -* **Python versions:** 3.9.x, 3.10.x, 3.11.x, 3.12.x +* **Python versions:** 3.10.x, 3.11.x, 3.12.x, 3.13.x ## 📦 Installation @@ -73,14 +73,14 @@ $ dnf install NiaAML-GUI To install `NiaAML-GUI` on Alpine Linux, enable Community repository and use: ```sh -$ apk add niaaml-gui +$ apk add niaaml-gui ``` ## 🚀 Usage NiaAML GUI application allows you to use the main features of the [NiaAML](https://github.com/firefly-cpp/NiaAML) framework. There are two views in the application. In the first one, you can prepare an environment for a pipeline optimization process. The purpose of the second one is to allow you to use an existing pipeline from a file. **The application currently supports data input in the form of CSV files.** -### Optimization View +### Pipeline Canvas View Below is a screenshot of the first view with labeled components and you can find a description for each component under the screenshot. @@ -88,21 +88,25 @@ Below is a screenshot of the first view with labeled components and you can find | Component | Description | |:----------|:------------| -| 1 | Tabbed view for choosing components for the optimization. Clicked components get transferred to their corresponding brackets (labels **5**, **6** and **7**). | -| 2 | Input CSV dataset's file selection widget. After the dataset has been selected, you can also view and edit it using the edit button next to the `Select file` button. **Also make sure you check the `CSV has header` checkbox in case the selected CSV file has a header row.** Below you can see a screenshot of the CSV file's editing window.

NiaAML GUI Edit Dataset View

| -| 3 | Dropdown widget for categorical features' encoder selection. It will be ignored if the dataset contains no categorical features. | -| 4 | Dropdown widget for missing data imputer selection. It will be ignored if the dataset contains no missing values. | -| 5 | List of selected feature selection algorithms (optional). | -| 6 | List of selected feature transform algorithms (optional). | -| 7 | List of selected classifiers. | -| 8 | Dropdown widget for the selection of components' selection optimization algorithm. | -| 9 | Dropdown widget for the selection of hyperparameters' tuning optimization algorithm. Defaults to **8** if none is selected. | -| 10 | Population size for the components' selection process. | -| 11 | Population size for the hyperparameters' tuning process. | -| 12 | Number of evaluations during the components' selection process. | -| 13 | Number of evaluations during the hyperparameters' tuning process. | -| 14 | Dropdown widget for the selection of a fitness function to use during the pipeline evaluation step. | -| 15 | Destination of the optimization's result (pipeline and text file). | +| 1 | Tabbed view for choosing components to be added to the canvas. Components can be dragged and dropped onto the canvas to visually build the pipeline. | +| 2 | The canvas area where blocks (components) are placed and connected. Users can construct the pipeline visually by drawing arrows between valid components. | +| 3 | "Select CSV File" block. Input dataset selection. Includes a file browser, CSV header checkbox, and an edit button to view/modify the CSV content.

NiaAML GUI Edit Dataset View

| +| 4 | "Categorical Encoder" block. Allows selection of encoding method for categorical features. Dropdown populated dynamically. | +| 5 | "Missing Imputer" block. Allows selection of imputation method to handle missing values. | +| 6 | "Feature Selection" block. Multi-selection dialog allows the user to choose one or more feature selection algorithms. | +| 7 | "Feature Transform" block. Multi-selection dialog allows choosing one or more feature transformation algorithms. | +| 8 | "Classifier" block. Multi-selection dialog for selecting one or more classification models. | +| 9 | "Optimization Algorithm (Selection)" block. Dropdown for choosing the optimization algorithm used in component selection. | +| 10 | "Optimization Algorithm (Tuning)" block. Dropdown for choosing the algorithm used for hyperparameter tuning. | +| 11 | "Population Size (Components Selection)" block. Numeric input for specifying the population size during component selection. | +| 12 | "Population Size (Parameter Tuning)" block. Numeric input for specifying the population size for hyperparameter tuning. | +| 13 | "Number of Evaluations (Component Selection)" block. Sets the number of allowed evaluations during selection. | +| 14 | "Number of Evaluations (Parameter Tuning)" block. Sets the number of evaluations for hyperparameter tuning. | +| 15 | "Fitness Function" block. Dropdown for selecting the fitness function used during evaluation of each candidate pipeline. | +| 16 | "Pipeline Output Folder" block. Defines the target folder where output files (pipeline, logs, results) are saved. | +| 17 | Arrow connections between blocks. Only valid connections are allowed. When drawing, green/red highlights show whether the target is acceptable. | +| 18 | Validation system. Before running optimization, the system checks whether all required components are present and properly configured. | + #### Optimization @@ -111,24 +115,9 @@ Below you can see screenshots of views during and after the optimization has fin

NiaAML GUI Optimization Running

NiaAML GUI Optimization Finished

-### Usage View - -Below is a screenshot of the second view with labeled components and you can find a description for each component under the screenshot. - -

NiaAML GUI Second View

- -| Component | Description | -|:----------|:------------| -| 1 | Pipeline file selection widget. | -| 2 | Input CSV file selection widget. The file should contain the same headers (if any) as the dataset in the optimization process and there should be no classes (expected results) present. After the dataset has been selected, you can also view and edit it using the edit button next to the `Select file` button. **Also make sure you check the** `CSV has header` **checkbox in case the selected CSV file has a header row.** | - -#### Run - -You get a similar output than in the optimization process, but this time there is an array of predicted values present. - ## đź““ Example -Let's say we want to find an optimal classification pipeline for the [Ecoli dataset](https://archive.ics.uci.edu/ml/datasets/ecoli) [[1]](#1). You can see the optimization setup in the screenshot below. +Let's say we want to find an optimal classification pipeline for the Example dataset. You can see the optimization setup in the screenshot below.

NiaAML GUI Optimization Setup

@@ -144,10 +133,6 @@ Now we can use the exported pipeline file for further classification on the unse

NiaAML GUI Run Pipeline

-The result for 5 individuals is shown on the screenshot below. - -

NiaAML GUI Run Pipeline Result

- ## 📝 References [1] Dua, D. and Graff, C. (2019). [UCI Machine Learning Repository](http://archive.ics.uci.edu/ml). Irvine, CA: University of California, School of Information and Computer Science. diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 0000000..d0c3cbf --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = source +BUILDDIR = build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/make.bat b/docs/make.bat new file mode 100644 index 0000000..dc1312a --- /dev/null +++ b/docs/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=source +set BUILDDIR=build + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.https://www.sphinx-doc.org/ + exit /b 1 +) + +if "%1" == "" goto help + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd diff --git a/docs/source/api.rst b/docs/source/api.rst new file mode 100644 index 0000000..3e2c453 --- /dev/null +++ b/docs/source/api.rst @@ -0,0 +1,7 @@ +API Reference +============= + +.. automodule:: niaaml_gui + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/changelog.rst b/docs/source/changelog.rst new file mode 100644 index 0000000..ec08490 --- /dev/null +++ b/docs/source/changelog.rst @@ -0,0 +1,14 @@ +Changelog +========= + +Version 4.1 +----------- + +- Fixed pipeline subprocess execution. +- Improved connection validation between blocks. +- Added Sphinx documentation. + +Older versions +-------------- + +See GitHub commit history for earlier changes. diff --git a/docs/source/conf.py b/docs/source/conf.py new file mode 100644 index 0000000..1116a96 --- /dev/null +++ b/docs/source/conf.py @@ -0,0 +1,36 @@ +# Configuration file for the Sphinx documentation builder. +# +# For the full list of built-in configuration values, see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +# -- Project information ----------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information + +project = 'NiaAML-GUI' +copyright = '2025, Aljaž Rant, Luka Pečnik' +author = 'Aljaž Rant, Luka Pečnik' +release = '4.1' + +# -- General configuration --------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration + +extensions = [] + +templates_path = ['_templates'] +exclude_patterns = [] + + + +# -- Options for HTML output ------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output + +html_theme = 'alabaster' +html_static_path = ['_static'] + +extensions = [ + 'sphinx.ext.autodoc', + 'sphinx.ext.napoleon', +] +import os +import sys +sys.path.insert(0, os.path.abspath('../..')) \ No newline at end of file diff --git a/docs/source/contributing.rst b/docs/source/contributing.rst new file mode 100644 index 0000000..58b17f5 --- /dev/null +++ b/docs/source/contributing.rst @@ -0,0 +1,25 @@ +Contributing +============ + +We welcome contributions! Here’s how you can help: + +- Fork the repository and create your feature branch. +- Make changes and test locally. +- Run the GUI with: + + .. code-block:: bash + + poetry run niaaml-gui + +- Submit a pull request. + +For larger changes, please open an issue first to discuss. + +Development Setup +----------------- + +.. code-block:: bash + + git clone https://github.com/firefly-cpp/NiaAML-GUI + cd NiaAML-GUI + poetry install diff --git a/docs/source/index.rst b/docs/source/index.rst new file mode 100644 index 0000000..0343bc4 --- /dev/null +++ b/docs/source/index.rst @@ -0,0 +1,20 @@ +.. NiaAML-GUI documentation master file + +Welcome to NiaAML-GUI's documentation! +======================================= + +.. toctree:: + :maxdepth: 2 + :caption: Contents: + + usage + contributing + changelog + installation + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/docs/source/installation.rst b/docs/source/installation.rst new file mode 100644 index 0000000..3a5027a --- /dev/null +++ b/docs/source/installation.rst @@ -0,0 +1,4 @@ +Installation +============ + +Instructions how to install via pip or from source, virtual environment, dependencies. diff --git a/docs/source/usage.rst b/docs/source/usage.rst new file mode 100644 index 0000000..2c885e4 --- /dev/null +++ b/docs/source/usage.rst @@ -0,0 +1,25 @@ +Usage +===== + +To run the GUI, first install the package via pip or from source: + +.. code-block:: bash + + pip install niaaml-gui + +Then run: + +.. code-block:: bash + + poetry run niaaml-gui + +The GUI allows you to build and optimize machine learning pipelines visually by dragging and connecting blocks. + +Components +---------- + +- **Data input**: Select a CSV file and define the output folder. +- **Preprocessing**: Includes encoders and imputers. +- **Feature Engineering**: Feature selection and transform blocks. +- **Modeling**: Classifiers and optimization algorithms. +- **Fitness Function**: Determines the pipeline’s quality. diff --git a/niaaml_gui/resources/icons/edit.png b/niaaml_gui/resources/icons/edit.png new file mode 100644 index 0000000..027565b Binary files /dev/null and b/niaaml_gui/resources/icons/edit.png differ diff --git a/niaaml_gui/widgets/connection_line.py b/niaaml_gui/widgets/connection_line.py index 1b6a6c9..81e9040 100644 --- a/niaaml_gui/widgets/connection_line.py +++ b/niaaml_gui/widgets/connection_line.py @@ -31,7 +31,6 @@ def __init__(self, source_block, target_block): self.update_path() def mousePressEvent(self, event): - """Ob kliku samo izberi povezavo – ne izbriši.""" self.setSelected(True) super().mousePressEvent(event) diff --git a/niaaml_gui/widgets/pipeline_canvas.py b/niaaml_gui/widgets/pipeline_canvas.py index 80f9dc8..5a0077d 100644 --- a/niaaml_gui/widgets/pipeline_canvas.py +++ b/niaaml_gui/widgets/pipeline_canvas.py @@ -339,14 +339,57 @@ def mouseReleaseEvent(self, event): def _is_valid_connection(self, source, target) -> bool: if source is target: return False - source_label = getattr(source, "label", "").lower() - target_label = getattr(target, "label", "").lower() - if "csv" in source_label and not any(k in target_label for k in ["encoder", "imputer"]): + + source_label = getattr(source, "label", "").strip().lower() + target_label = getattr(target, "label", "").strip().lower() + + categories = [ + ("data", {"select csv file", "pipeline output folder"}), + ("pre-processing", {"categorical encoder", "missing imputer"}), + ("feature eng.", {"feature selection", "feature transform"}), + ("modeling", {"classifier", "optimization algorithm (selection)", "optimization algorithm (tuning)"}), + ("population", {"population size (components selection)", "population size (parameter tuning)"}), + ("evaluation", {"number of evaluations (component selection)", "number of evaluations (parameter tuning)"}), + ("fitness", {"fitness function"}) + ] + + def find_category(label: str) -> str | None: + for cat, items in categories: + if label in items: + return cat + return None + + source_cat = find_category(source_label) + target_cat = find_category(target_label) + + if not source_cat or not target_cat: return False - for conn in source.connections: - if conn.target_block is target: - return False - return True + + + if source_label == "pipeline output folder": + return False + + if target_label == "select csv file": + return False + + if source_cat == "fitness" and target_label == "pipeline output folder": + return True + + if source_cat == target_cat: + return True + + cat_order = [cat for cat, _ in categories] + try: + source_idx = cat_order.index(source_cat) + target_idx = cat_order.index(target_cat) + if target_idx == source_idx + 1: + return True + except ValueError: + return False + + return False + + def _highlight_connection_targets(self, source_block): for item in self.scene.items(): @@ -606,7 +649,7 @@ def _add_csv_helpers(self): ) icon_dir = os.path.join(os.path.dirname(os.path.dirname(__file__)), "resources", "icons") - edit_icon = os.path.join(icon_dir, "placeholder.png") + edit_icon = os.path.join(icon_dir, "edit.png") btn = QPushButton(); btn.setIcon(QIcon(edit_icon)); btn.setIconSize(QSize(18, 18)) btn.setFixedSize(24, 24) p_btn = QGraphicsProxyWidget(self); p_btn.setWidget(btn) diff --git a/poetry.lock b/poetry.lock index 13cd3ad..b16aafc 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,15 @@ -# This file is automatically @generated by Poetry 1.8.5 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. + +[[package]] +name = "alabaster" +version = "0.7.16" +description = "A light, configurable Sphinx theme" +optional = false +python-versions = ">=3.9" +files = [ + {file = "alabaster-0.7.16-py3-none-any.whl", hash = "sha256:b46733c07dce03ae4e150330b975c75737fa60f0a7c591b6c8bf4928a28e2c92"}, + {file = "alabaster-0.7.16.tar.gz", hash = "sha256:75a8b99c28a5dad50dd7f8ccdd447a121ddb3892da9e53d1ca5cca3106d58d65"}, +] [[package]] name = "autoflake" @@ -15,6 +26,20 @@ files = [ pyflakes = ">=3.0.0" tomli = {version = ">=2.0.1", markers = "python_version < \"3.11\""} +[[package]] +name = "babel" +version = "2.17.0" +description = "Internationalization utilities" +optional = false +python-versions = ">=3.8" +files = [ + {file = "babel-2.17.0-py3-none-any.whl", hash = "sha256:4d0b53093fdfb4b21c92b5213dba5a1b23885afa8383709427046b21c366e5f2"}, + {file = "babel-2.17.0.tar.gz", hash = "sha256:0c54cffb19f690cdcc52a3b50bcbf71e07a808d1c80d549f2459b9d2cf0afb9d"}, +] + +[package.extras] +dev = ["backports.zoneinfo", "freezegun (>=1.0,<2.0)", "jinja2 (>=3.0)", "pytest (>=6.0)", "pytest-cov", "pytz", "setuptools", "tzdata"] + [[package]] name = "black" version = "23.12.1" @@ -402,6 +427,17 @@ files = [ {file = "docopt-0.6.2.tar.gz", hash = "sha256:49b3a825280bd66b3aa83585ef59c4a8c82f2c8a522dbe754a8bc8d08c85c491"}, ] +[[package]] +name = "docutils" +version = "0.21.2" +description = "Docutils -- Python Documentation Utilities" +optional = false +python-versions = ">=3.9" +files = [ + {file = "docutils-0.21.2-py3-none-any.whl", hash = "sha256:dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2"}, + {file = "docutils-0.21.2.tar.gz", hash = "sha256:3a6b18732edf182daa3cd12775bbb338cf5691468f91eeeb109deff6ebfa986f"}, +] + [[package]] name = "emoji" version = "2.14.1" @@ -552,6 +588,17 @@ files = [ [package.extras] all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] +[[package]] +name = "imagesize" +version = "1.4.1" +description = "Getting image size from png/jpeg/jpeg2000/gif file" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "imagesize-1.4.1-py2.py3-none-any.whl", hash = "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b"}, + {file = "imagesize-1.4.1.tar.gz", hash = "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a"}, +] + [[package]] name = "iniconfig" version = "2.1.0" @@ -563,6 +610,23 @@ files = [ {file = "iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7"}, ] +[[package]] +name = "jinja2" +version = "3.1.6" +description = "A very fast and expressive template engine." +optional = false +python-versions = ">=3.7" +files = [ + {file = "jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67"}, + {file = "jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d"}, +] + +[package.dependencies] +MarkupSafe = ">=2.0" + +[package.extras] +i18n = ["Babel (>=2.7)"] + [[package]] name = "joblib" version = "1.5.1" @@ -705,6 +769,76 @@ profiling = ["gprof2dot"] rtd = ["jupyter_sphinx", "mdit-py-plugins", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"] testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] +[[package]] +name = "markupsafe" +version = "3.0.2" +description = "Safely add untrusted strings to HTML/XML markup." +optional = false +python-versions = ">=3.9" +files = [ + {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:38a9ef736c01fccdd6600705b09dc574584b89bea478200c5fbf112a6b0d5579"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bbcb445fa71794da8f178f0f6d66789a28d7319071af7a496d4d507ed566270d"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57cb5a3cf367aeb1d316576250f65edec5bb3be939e9247ae594b4bcbc317dfb"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3809ede931876f5b2ec92eef964286840ed3540dadf803dd570c3b7e13141a3b"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e07c3764494e3776c602c1e78e298937c3315ccc9043ead7e685b7f2b8d47b3c"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b424c77b206d63d500bcb69fa55ed8d0e6a3774056bdc4839fc9298a7edca171"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-win32.whl", hash = "sha256:fcabf5ff6eea076f859677f5f0b6b5c1a51e70a376b0579e0eadef8db48c6b50"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:6af100e168aa82a50e186c82875a5893c5597a0c1ccdb0d8b40240b1f28b969a"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9025b4018f3a1314059769c7bf15441064b2207cb3f065e6ea1e7359cb46db9d"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:93335ca3812df2f366e80509ae119189886b0f3c2b81325d39efdb84a1e2ae93"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2cb8438c3cbb25e220c2ab33bb226559e7afb3baec11c4f218ffa7308603c832"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a123e330ef0853c6e822384873bef7507557d8e4a082961e1defa947aa59ba84"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e084f686b92e5b83186b07e8a17fc09e38fff551f3602b249881fec658d3eca"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d8213e09c917a951de9d09ecee036d5c7d36cb6cb7dbaece4c71a60d79fb9798"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:5b02fb34468b6aaa40dfc198d813a641e3a63b98c2b05a16b9f80b7ec314185e"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-win32.whl", hash = "sha256:6c89876f41da747c8d3677a2b540fb32ef5715f97b66eeb0c6b66f5e3ef6f59d"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:70a87b411535ccad5ef2f1df5136506a10775d267e197e4cf531ced10537bd6b"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-win32.whl", hash = "sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-win32.whl", hash = "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-win32.whl", hash = "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:eaa0a10b7f72326f1372a713e73c3f739b524b3af41feb43e4921cb529f5929a"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:48032821bbdf20f5799ff537c7ac3d1fba0ba032cfc06194faffa8cda8b560ff"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a9d3f5f0901fdec14d8d2f66ef7d035f2157240a433441719ac9a3fba440b13"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88b49a3b9ff31e19998750c38e030fc7bb937398b1f78cfa599aaef92d693144"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cfad01eed2c2e0c01fd0ecd2ef42c492f7f93902e39a42fc9ee1692961443a29"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:1225beacc926f536dc82e45f8a4d68502949dc67eea90eab715dea3a21c1b5f0"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:3169b1eefae027567d1ce6ee7cae382c57fe26e82775f460f0b2778beaad66c0"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:eb7972a85c54febfb25b5c4b4f3af4dcc731994c7da0d8a0b4a6eb0640e1d178"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-win32.whl", hash = "sha256:8c4e8c3ce11e1f92f6536ff07154f9d49677ebaaafc32db9db4620bc11ed480f"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:6e296a513ca3d94054c2c881cc913116e90fd030ad1c656b3869762b754f5f8a"}, + {file = "markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0"}, +] + [[package]] name = "matplotlib" version = "3.10.3" @@ -1478,19 +1612,18 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] [[package]] name = "rich" -version = "14.0.0" +version = "14.1.0" description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" optional = false python-versions = ">=3.8.0" files = [ - {file = "rich-14.0.0-py3-none-any.whl", hash = "sha256:1c9491e1951aac09caffd42f448ee3d04e58923ffe14993f6e83068dc395d7e0"}, - {file = "rich-14.0.0.tar.gz", hash = "sha256:82f1bc23a6a21ebca4ae0c45af9bdbc492ed20231dcb63f297d6d1021a9d5725"}, + {file = "rich-14.1.0-py3-none-any.whl", hash = "sha256:536f5f1785986d6dbdea3c75205c473f970777b4a0d6c6dd1b696aa05a3fa04f"}, + {file = "rich-14.1.0.tar.gz", hash = "sha256:e497a48b844b0320d45007cdebfeaeed8db2a4f4bcf49f15e455cfc4af11eaa8"}, ] [package.dependencies] markdown-it-py = ">=2.2.0" pygments = ">=2.13.0,<3.0.0" -typing-extensions = {version = ">=4.0.0,<5.0", markers = "python_version < \"3.11\""} [package.extras] jupyter = ["ipywidgets (>=7.5.1,<9)"] @@ -1630,6 +1763,146 @@ files = [ {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"}, ] +[[package]] +name = "snowballstemmer" +version = "3.0.1" +description = "This package provides 32 stemmers for 30 languages generated from Snowball algorithms." +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*" +files = [ + {file = "snowballstemmer-3.0.1-py3-none-any.whl", hash = "sha256:6cd7b3897da8d6c9ffb968a6781fa6532dce9c3618a4b127d920dab764a19064"}, + {file = "snowballstemmer-3.0.1.tar.gz", hash = "sha256:6d5eeeec8e9f84d4d56b847692bacf79bc2c8e90c7f80ca4444ff8b6f2e52895"}, +] + +[[package]] +name = "sphinx" +version = "7.4.7" +description = "Python documentation generator" +optional = false +python-versions = ">=3.9" +files = [ + {file = "sphinx-7.4.7-py3-none-any.whl", hash = "sha256:c2419e2135d11f1951cd994d6eb18a1835bd8fdd8429f9ca375dc1f3281bd239"}, + {file = "sphinx-7.4.7.tar.gz", hash = "sha256:242f92a7ea7e6c5b406fdc2615413890ba9f699114a9c09192d7dfead2ee9cfe"}, +] + +[package.dependencies] +alabaster = ">=0.7.14,<0.8.0" +babel = ">=2.13" +colorama = {version = ">=0.4.6", markers = "sys_platform == \"win32\""} +docutils = ">=0.20,<0.22" +imagesize = ">=1.3" +Jinja2 = ">=3.1" +packaging = ">=23.0" +Pygments = ">=2.17" +requests = ">=2.30.0" +snowballstemmer = ">=2.2" +sphinxcontrib-applehelp = "*" +sphinxcontrib-devhelp = "*" +sphinxcontrib-htmlhelp = ">=2.0.0" +sphinxcontrib-jsmath = "*" +sphinxcontrib-qthelp = "*" +sphinxcontrib-serializinghtml = ">=1.1.9" +tomli = {version = ">=2", markers = "python_version < \"3.11\""} + +[package.extras] +docs = ["sphinxcontrib-websupport"] +lint = ["flake8 (>=6.0)", "importlib-metadata (>=6.0)", "mypy (==1.10.1)", "pytest (>=6.0)", "ruff (==0.5.2)", "sphinx-lint (>=0.9)", "tomli (>=2)", "types-docutils (==0.21.0.20240711)", "types-requests (>=2.30.0)"] +test = ["cython (>=3.0)", "defusedxml (>=0.7.1)", "pytest (>=8.0)", "setuptools (>=70.0)", "typing_extensions (>=4.9)"] + +[[package]] +name = "sphinxcontrib-applehelp" +version = "2.0.0" +description = "sphinxcontrib-applehelp is a Sphinx extension which outputs Apple help books" +optional = false +python-versions = ">=3.9" +files = [ + {file = "sphinxcontrib_applehelp-2.0.0-py3-none-any.whl", hash = "sha256:4cd3f0ec4ac5dd9c17ec65e9ab272c9b867ea77425228e68ecf08d6b28ddbdb5"}, + {file = "sphinxcontrib_applehelp-2.0.0.tar.gz", hash = "sha256:2f29ef331735ce958efa4734873f084941970894c6090408b079c61b2e1c06d1"}, +] + +[package.extras] +lint = ["mypy", "ruff (==0.5.5)", "types-docutils"] +standalone = ["Sphinx (>=5)"] +test = ["pytest"] + +[[package]] +name = "sphinxcontrib-devhelp" +version = "2.0.0" +description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp documents" +optional = false +python-versions = ">=3.9" +files = [ + {file = "sphinxcontrib_devhelp-2.0.0-py3-none-any.whl", hash = "sha256:aefb8b83854e4b0998877524d1029fd3e6879210422ee3780459e28a1f03a8a2"}, + {file = "sphinxcontrib_devhelp-2.0.0.tar.gz", hash = "sha256:411f5d96d445d1d73bb5d52133377b4248ec79db5c793ce7dbe59e074b4dd1ad"}, +] + +[package.extras] +lint = ["mypy", "ruff (==0.5.5)", "types-docutils"] +standalone = ["Sphinx (>=5)"] +test = ["pytest"] + +[[package]] +name = "sphinxcontrib-htmlhelp" +version = "2.1.0" +description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" +optional = false +python-versions = ">=3.9" +files = [ + {file = "sphinxcontrib_htmlhelp-2.1.0-py3-none-any.whl", hash = "sha256:166759820b47002d22914d64a075ce08f4c46818e17cfc9470a9786b759b19f8"}, + {file = "sphinxcontrib_htmlhelp-2.1.0.tar.gz", hash = "sha256:c9e2916ace8aad64cc13a0d233ee22317f2b9025b9cf3295249fa985cc7082e9"}, +] + +[package.extras] +lint = ["mypy", "ruff (==0.5.5)", "types-docutils"] +standalone = ["Sphinx (>=5)"] +test = ["html5lib", "pytest"] + +[[package]] +name = "sphinxcontrib-jsmath" +version = "1.0.1" +description = "A sphinx extension which renders display math in HTML via JavaScript" +optional = false +python-versions = ">=3.5" +files = [ + {file = "sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8"}, + {file = "sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", hash = "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178"}, +] + +[package.extras] +test = ["flake8", "mypy", "pytest"] + +[[package]] +name = "sphinxcontrib-qthelp" +version = "2.0.0" +description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp documents" +optional = false +python-versions = ">=3.9" +files = [ + {file = "sphinxcontrib_qthelp-2.0.0-py3-none-any.whl", hash = "sha256:b18a828cdba941ccd6ee8445dbe72ffa3ef8cbe7505d8cd1fa0d42d3f2d5f3eb"}, + {file = "sphinxcontrib_qthelp-2.0.0.tar.gz", hash = "sha256:4fe7d0ac8fc171045be623aba3e2a8f613f8682731f9153bb2e40ece16b9bbab"}, +] + +[package.extras] +lint = ["mypy", "ruff (==0.5.5)", "types-docutils"] +standalone = ["Sphinx (>=5)"] +test = ["defusedxml (>=0.7.1)", "pytest"] + +[[package]] +name = "sphinxcontrib-serializinghtml" +version = "2.0.0" +description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)" +optional = false +python-versions = ">=3.9" +files = [ + {file = "sphinxcontrib_serializinghtml-2.0.0-py3-none-any.whl", hash = "sha256:6e2cb0eef194e10c27ec0023bfeb25badbbb5868244cf5bc5bdc04e4464bf331"}, + {file = "sphinxcontrib_serializinghtml-2.0.0.tar.gz", hash = "sha256:e9d912827f872c029017a53f0ef2180b327c3f7fd23c87229f7a8e8b70031d4d"}, +] + +[package.extras] +lint = ["mypy", "ruff (==0.5.5)", "types-docutils"] +standalone = ["Sphinx (>=5)"] +test = ["pytest"] + [[package]] name = "threadpoolctl" version = "3.6.0" @@ -1775,4 +2048,4 @@ dev = ["black (>=19.3b0)", "pytest (>=4.6.2)"] [metadata] lock-version = "2.0" python-versions = ">=3.10,<3.14" -content-hash = "15900bffdfedaaba703ed7fd2efd6da11d4f17b2dc76c55fd1f3935328d0f620" +content-hash = "c4fd36fa434594b0862f8284ba1cfdfac0082560414b5997c8c444f0ca8b9871" diff --git a/pyproject.toml b/pyproject.toml index 61b7583..3a12c4b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -25,6 +25,7 @@ coveralls = "^3.3.1" black = "^23.11.0" autoflake = "^2.2.1" pre-commit = "^3.5.0" +sphinx = "<8.0.0" [tool.poetry.scripts] NiaAML-GUI = 'niaaml_gui.main:run'