Skip to content
Merged
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
Binary file modified .github/gui1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added .github/gui1_old.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified .github/gui2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified .github/gui7.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified .github/gui8.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
63 changes: 24 additions & 39 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,10 @@
<a href="#-cite-us">📄 Cite us</a>
</p>

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

Expand Down Expand Up @@ -73,36 +73,40 @@ $ 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.

<p align="center"><img src=".github/gui1.png" alt="NiaAML GUI First View" title="NiaAML GUI First View"/></p>

| 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. <p align="center"><img src=".github/gui3.png" alt="NiaAML GUI Edit Dataset View" title="NiaAML GUI Edit Dataset View"/></p> |
| 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. <br> <p align="center"><img src=".github/gui3.png" alt="NiaAML GUI Edit Dataset View" title="NiaAML GUI Edit Dataset View"/></p> |
| 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

Expand All @@ -111,24 +115,9 @@ Below you can see screenshots of views during and after the optimization has fin
<p align="center"><img src=".github/gui2.png" alt="NiaAML GUI Optimization Running" title="NiaAML GUI Optimization Running"/></p>
<p align="center"><img src=".github/gui4.png" alt="NiaAML GUI Optimization Finished" title="NiaAML GUI Optimization Finished"/></p>

### 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.

<p align="center"><img src=".github/gui5.png" alt="NiaAML GUI Second View" title="NiaAML GUI Second View"/></p>

| 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.

<p align="center"><img src=".github/gui6.png" alt="NiaAML GUI Optimization Setup" title="NiaAML GUI Optimization Setup"/></p>

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

<p align="center"><img src=".github/gui9.png" alt="NiaAML GUI Run Pipeline" title="NiaAML GUI Run Pipeline"/></p>

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

<p align="center"><img src=".github/gui10.png" alt="NiaAML GUI Run Pipeline Result" title="NiaAML GUI Run Pipeline Result"/></p>

## 📝 References

<a id="1">[1]</a> 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.
Expand Down
20 changes: 20 additions & 0 deletions docs/Makefile
Original file line number Diff line number Diff line change
@@ -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)
35 changes: 35 additions & 0 deletions docs/make.bat
Original file line number Diff line number Diff line change
@@ -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
7 changes: 7 additions & 0 deletions docs/source/api.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
API Reference
=============

.. automodule:: niaaml_gui
:members:
:undoc-members:
:show-inheritance:
14 changes: 14 additions & 0 deletions docs/source/changelog.rst
Original file line number Diff line number Diff line change
@@ -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.
36 changes: 36 additions & 0 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
@@ -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('../..'))
25 changes: 25 additions & 0 deletions docs/source/contributing.rst
Original file line number Diff line number Diff line change
@@ -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
20 changes: 20 additions & 0 deletions docs/source/index.rst
Original file line number Diff line number Diff line change
@@ -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`
4 changes: 4 additions & 0 deletions docs/source/installation.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Installation
============

Instructions how to install via pip or from source, virtual environment, dependencies.
25 changes: 25 additions & 0 deletions docs/source/usage.rst
Original file line number Diff line number Diff line change
@@ -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.
Binary file added niaaml_gui/resources/icons/edit.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 0 additions & 1 deletion niaaml_gui/widgets/connection_line.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
59 changes: 51 additions & 8 deletions niaaml_gui/widgets/pipeline_canvas.py
Original file line number Diff line number Diff line change
Expand Up @@ -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():
Expand Down Expand Up @@ -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)
Expand Down
Loading
Loading