Data set examples

Basic example

Source code :

# -*- coding: utf-8 -*-

import guidata
import guidata.dataset as gds

# Note: the following line is not required if a QApplication has already been created
_app = guidata.qapplication()


class Processing(gds.DataSet):
    """Example"""

    a = gds.FloatItem("Parameter #1", default=2.3)
    b = gds.IntItem("Parameter #2", min=0, max=10, default=5)
    type = gds.ChoiceItem("Processing algorithm", ("type 1", "type 2", "type 3"))


param = Processing()
param.edit()
print(param)  # Showing param contents
param.b = 4  # Modifying item value
param.view()

# Alternative way for creating a DataSet instance:
param = Processing.create(a=7.323, b=4)
print(param)
_images/basic_example.png

Other examples

A lot of examples are available in the guidata test module

from guidata import tests
tests.run()

The two lines above execute the guidata test launcher :

_images/__init__.png

All guidata items demo


import atexit
import datetime
import shutil
import tempfile

import numpy as np

import guidata.dataset as gds
from guidata.env import execenv
from guidata.qthelpers import qt_app_context

# Creating temporary files and registering cleanup functions
TEMPDIR = tempfile.mkdtemp(prefix="test_")
atexit.register(shutil.rmtree, TEMPDIR)
FILE_ETA = tempfile.NamedTemporaryFile(suffix=".eta", dir=TEMPDIR)
atexit.register(FILE_ETA.close)
FILE_CSV = tempfile.NamedTemporaryFile(suffix=".csv", dir=TEMPDIR)
atexit.register(FILE_CSV.close)


class Parameters(gds.DataSet):
    """
    DataSet test
    The following text is the DataSet 'comment': <br>Plain text or
    <b>rich text<sup>2</sup></b> are both supported,
    as well as special characters (α, β, γ, δ, ...)
    """

    dir = gds.DirectoryItem("Directory", TEMPDIR)
    fname = gds.FileOpenItem("Open file", ("csv", "eta"), FILE_CSV.name)
    fnames = gds.FilesOpenItem("Open files", "csv", FILE_CSV.name)
    fname_s = gds.FileSaveItem("Save file", "eta", FILE_ETA.name)
    string = gds.StringItem("String")
    text = gds.TextItem("Text")
    float_slider = gds.FloatItem(
        "Float (with slider)", default=0.5, min=0, max=1, step=0.01, slider=True
    )
    integer = gds.IntItem("Integer", default=5, min=3, max=16, slider=True).set_pos(
        col=1
    )
    dtime = gds.DateTimeItem("Date/time", default=datetime.datetime(2010, 10, 10))
    date = gds.DateItem("Date", default=datetime.date(2010, 10, 10)).set_pos(col=1)
    bool1 = gds.BoolItem("Boolean option without label")
    bool2 = gds.BoolItem("Boolean option with label", "Label")
    _bg = gds.BeginGroup("A sub group")
    color = gds.ColorItem("Color", default="red")
    choice = gds.ChoiceItem(
        "Single choice 1",
        [("16", "first choice"), ("32", "second choice"), ("64", "third choice")],
    )
    mchoice2 = gds.ImageChoiceItem(
        "Single choice 2",
        [
            ("rect", "first choice", "gif.png"),
            ("ell", "second choice", "txt.png"),
            ("qcq", "third choice", "file.png"),
        ],
    )
    _eg = gds.EndGroup("A sub group")
    floatarray = gds.FloatArrayItem(
        "Float array", default=np.ones((50, 5), float), format=" %.2e "
    ).set_pos(col=1)
    mchoice3 = gds.MultipleChoiceItem(
        "MC type 1", [str(i) for i in range(12)]
    ).horizontal(4)
    mchoice1 = (
        gds.MultipleChoiceItem(
            "MC type 2", ["first choice", "second choice", "third choice"]
        )
        .vertical(1)
        .set_pos(col=1)
    )
    dictionary = gds.DictItem(
        "Dictionary",
        default={
            "lkl": 2,
            "tototo": 3,
            "zzzz": "lklk",
            "bool": True,
            "float": 1.234,
            "list": [1, 2.5, 3, "str", False, 5, {"lkl": 2, "l": [1, 2, 3]}],
        },
        help="This is a dictionary",
    )


def test_all_items():
    """Test all DataItem objects"""
    with qt_app_context():
        prm = Parameters()

        prm.floatarray[:, 0] = np.linspace(-5, 5, 50)
        execenv.print(prm)
        if prm.edit():
            execenv.print(prm)
        prm.view()
        execenv.print("OK")


if __name__ == "__main__":
    test_all_items()
_images/all_items.png

Embedding guidata objects in GUI layouts


import numpy as np
from qtpy.QtWidgets import QMainWindow, QSplitter

import guidata.dataset as gds
from guidata.configtools import get_icon
from guidata.dataset.qtwidgets import DataSetEditGroupBox, DataSetShowGroupBox
from guidata.env import execenv
from guidata.qthelpers import (
    add_actions,
    create_action,
    get_std_icon,
    qt_app_context,
    win32_fix_title_bar_background,
)
from guidata.tests.dataset.test_activable_dataset import Parameters
from guidata.widgets import about


class AnotherDataSet(gds.DataSet):
    """
    Example 2
    <b>Simple dataset example</b>
    """

    param0 = gds.ChoiceItem("Choice", ["deazdazk", "aeazee", "87575757"])
    param1 = gds.FloatItem("Foobar 1", default=0, min=0)
    a_group = gds.BeginGroup("A group")
    param2 = gds.FloatItem("Foobar 2", default=0.93)
    param3 = gds.FloatItem("Foobar 3", default=123)
    _a_group = gds.EndGroup("A group")


class ExampleMultiGroupDataSet(gds.DataSet):
    """Example DS with multiple groups"""

    choices = gds.MultipleChoiceItem("Choices", ["a", "b", "c", "d", "e"])
    dictionary = gds.DictItem("Dictionary", {"a": 1, "b": 2, "c": 3})
    param0 = gds.ChoiceItem("Choice", ["deazdazk", "aeazee", "87575757"])
    param1 = gds.FloatItem("Foobar 1", default=0, min=0)
    t_group = gds.BeginTabGroup("T group")
    a_group = gds.BeginGroup("A group")
    param2 = gds.FloatItem("Foobar 2", default=0.93)
    dir1 = gds.DirectoryItem("Directory 1")
    file1 = gds.FileOpenItem("File 1")
    _a_group = gds.EndGroup("A group")
    b_group = gds.BeginGroup("B group")
    param3 = gds.FloatItem("Foobar 3", default=123)
    param4 = gds.BoolItem("Boolean")
    _b_group = gds.EndGroup("B group")
    c_group = gds.BeginGroup("C group")
    param5 = gds.FloatItem("Foobar 4", default=250)
    param6 = gds.DateItem("Date").set_prop("display", format="dd.MM.yyyy")
    param7 = gds.ColorItem("Color")
    _c_group = gds.EndGroup("C group")
    _t_group = gds.EndTabGroup("T group")


class OtherDataSet(gds.DataSet):
    """Another example dataset"""

    title = gds.StringItem("Title", default="Title")
    icon = gds.ChoiceItem(
        "Icon",
        (
            ("python.png", "Python"),
            ("guidata.svg", "guidata"),
            ("settings.png", "Settings"),
        ),
    )
    opacity = gds.FloatItem("Opacity", default=1.0, min=0.1, max=1)
    transform = gds.FloatArrayItem("Transform", default=np.array([1, 2, 3, 4, 5, 6]))


class MainWindow(QMainWindow):
    """Main window"""

    def __init__(self):
        QMainWindow.__init__(self)
        win32_fix_title_bar_background(self)
        self.setWindowIcon(get_icon("python.png"))
        self.setWindowTitle("Application example")

        # Instantiate dataset-related widgets:
        self.groupbox1 = DataSetShowGroupBox(
            "Activable dataset", Parameters, comment=""
        )
        self.groupbox2 = DataSetShowGroupBox(
            "Standard dataset", AnotherDataSet, comment=""
        )
        self.groupbox3 = DataSetEditGroupBox(
            "Standard dataset", OtherDataSet, comment=""
        )
        self.groupbox4 = DataSetEditGroupBox(
            "Standard dataset", ExampleMultiGroupDataSet, comment=""
        )
        self.groupbox3.SIG_APPLY_BUTTON_CLICKED.connect(self.update_window)
        self.update_groupboxes()

        splitter = QSplitter(self)
        splitter.addWidget(self.groupbox1)
        splitter.addWidget(self.groupbox2)
        splitter.addWidget(self.groupbox3)
        splitter.addWidget(self.groupbox4)
        self.setCentralWidget(splitter)
        self.setContentsMargins(10, 5, 10, 5)

        # File menu
        file_menu = self.menuBar().addMenu("File")
        quit_action = create_action(
            self,
            "Quit",
            shortcut="Ctrl+Q",
            icon=get_std_icon("DialogCloseButton"),
            tip="Quit application",
            triggered=self.close,
        )
        add_actions(file_menu, (quit_action,))

        # Edit menu
        edit_menu = self.menuBar().addMenu("Edit")
        editparam1_action = create_action(
            self, "Edit dataset 1", triggered=self.edit_dataset1
        )
        editparam2_action = create_action(
            self, "Edit dataset 2", triggered=self.edit_dataset2
        )
        editparam4_action = create_action(
            self, "Edit dataset 4", triggered=self.edit_dataset4
        )
        ro_param4_action = create_action(
            self, "Dataset 4: read-only", toggled=self.ro_dataset4
        )
        add_actions(
            edit_menu,
            (editparam1_action, editparam2_action, editparam4_action, ro_param4_action),
        )

        # ? menu
        help_menu = self.menuBar().addMenu("?")
        about_action = create_action(
            self,
            "About guidata",
            icon=get_std_icon("MessageBoxInformation"),
            triggered=about.show_about_dialog,
        )
        add_actions(help_menu, (about_action,))

    def update_window(self):
        """Update window"""
        dataset = self.groupbox3.dataset
        self.setWindowTitle(dataset.title)
        self.setWindowIcon(get_icon(dataset.icon))
        self.setWindowOpacity(dataset.opacity)

    def update_groupboxes(self):
        """Update groupboxes"""
        self.groupbox1.dataset.set_activable(False)  # This is an activable dataset
        self.groupbox1.get()
        self.groupbox2.get()
        self.groupbox4.get()

    def ro_dataset4(self, readonly: bool):
        self.groupbox4.dataset.set_readonly(readonly)
        self.groupbox4.get()

    def edit_dataset1(self):
        """Edit dataset 1"""
        self.groupbox1.dataset.set_activable(True)  # This is an activable dataset
        if self.groupbox1.dataset.edit(self):
            self.update_groupboxes()

    def edit_dataset2(self):
        """Edit dataset 2"""
        if self.groupbox2.dataset.edit(self):
            self.update_groupboxes()

    def edit_dataset4(self):
        """Edit dataset 4"""
        if self.groupbox4.dataset.edit(self):
            self.update_groupboxes()


def test_editgroupbox():
    """Test editgroupbox"""
    with qt_app_context(exec_loop=True):
        window = MainWindow()
        window.show()
        execenv.print("OK")


if __name__ == "__main__":
    test_editgroupbox()
_images/editgroupbox.png

Data item groups and group selection


import guidata.dataset as gds
from guidata.env import execenv
from guidata.qthelpers import qt_app_context

prop1 = gds.ValueProp(False)
prop2 = gds.ValueProp(False)


class Parameters(gds.DataSet):
    """
    Group selection test
    <b>Group selection example:</b>
    """

    g1 = gds.BeginGroup("group 1")
    enable1 = gds.BoolItem(
        "Enable parameter set #1",
        help="If disabled, the following parameters will be ignored",
        default=False,
    ).set_prop("display", store=prop1)
    prm11 = gds.FloatItem("Prm 1.1", default=0, min=0).set_prop("display", active=prop1)
    prm12 = gds.FloatItem("Prm 1.2", default=0.93).set_prop("display", active=prop1)
    _g1 = gds.EndGroup("group 1")
    g2 = gds.BeginGroup("group 2")
    enable2 = gds.BoolItem(
        "Enable parameter set #2",
        help="If disabled, the following parameters will be ignored",
        default=True,
    ).set_prop("display", store=prop2)
    prm21 = gds.FloatItem("Prm 2.1", default=0, min=0).set_prop("display", active=prop2)
    prm22 = gds.FloatItem("Prm 2.2", default=0.93).set_prop("display", active=prop2)
    _g2 = gds.EndGroup("group 2")


def test_bool_selector():
    """Test bool selector"""
    with qt_app_context():
        prm = Parameters()
        prm.edit()
        execenv.print(prm)
        execenv.print("OK")


if __name__ == "__main__":
    test_bool_selector()
_images/bool_selector.png

Activable data sets



class Parameters(gds.ActivableDataSet):
    """
    Example
    <b>Activable dataset example</b>
    """

    def __init__(self, title=None, comment=None, icon=""):
        gds.ActivableDataSet.__init__(self, title, comment, icon)

    enable = gds.BoolItem(
        "Enable parameter set",
        help="If disabled, the following parameters will be ignored",
        default=False,
    )
    param0 = gds.ChoiceItem("Param 0", ["choice #1", "choice #2", "choice #3"])
    param1 = gds.FloatItem("Param 1", default=0, min=0)
    param2 = gds.FloatItem("Param 2", default=0.93)
    color = gds.ColorItem("Color", default="red")


Parameters.active_setup()


def test_activable_dataset():
    """Test activable dataset"""
    with qt_app_context():
        prm = Parameters()
        prm.set_activable(True)
        prm.edit()
        prm.set_activable(False)
        prm.edit()
        prm.set_readonly()
        prm.edit()
        prm.set_readonly(False)
        prm.edit()
        execenv.print("OK")


if __name__ == "__main__":
    test_activable_dataset()
_images/activable_dataset.png

Data set groups


from guidata.dataset import DataSetGroup
from guidata.env import execenv
from guidata.qthelpers import qt_app_context
from guidata.tests.dataset.test_all_features import Parameters


def test_dataset_group():
    """Test DataSetGroup"""
    with qt_app_context():
        e1 = Parameters("DataSet #1")
        e2 = Parameters("DataSet #2")

        g = DataSetGroup([e1, e2], title="Parameters group")
        g.edit()
        execenv.print(e1)
        g.edit()
        execenv.print("OK")

        g = DataSetGroup([e1, e2], title="Parameters group in table mode")
        g.edit(mode="table")
        execenv.print(e1)
        g.edit()
        execenv.print("OK")

        g.edit()
        execenv.print(e1)
        g.edit()
        execenv.print("OK")


if __name__ == "__main__":
    test_dataset_group()
_images/datasetgroup.png

Utilities

Update/restore a dataset from/to a dictionary


import numpy as np

from guidata.dataset.conv import restore_dataset, update_dataset
from guidata.tests.dataset.test_all_items import Parameters


def test_update_restore_dataset():
    """Test update/restore dataset from/to another dataset or dictionary"""
    dataset = Parameters()
    dsdict = {
        "integer": 1,
        "float_slider": 1.0,
        "bool1": True,
        "string": "test",
        "floatarray": np.array([1, 2, 3]),
        "dictionary": {"a": 1, "b": 2},
    }
    # Update dataset from dictionary
    update_dataset(dataset, dsdict)
    # Check dataset values
    assert dataset.integer == dsdict["integer"]
    assert dataset.float_slider == dsdict["float_slider"]
    assert dataset.bool1 == dsdict["bool1"]
    assert dataset.string == dsdict["string"]
    assert np.all(dataset.floatarray == dsdict["floatarray"])
    assert dataset.dictionary == dsdict["dictionary"]
    # Update dataset from another dataset
    dataset2 = Parameters()
    update_dataset(dataset2, dataset)
    # Check dataset values
    assert dataset2.integer == dataset.integer
    assert dataset2.float_slider == dataset.float_slider
    assert dataset2.bool1 == dataset.bool1
    assert dataset2.string == dataset.string
    assert np.all(dataset2.floatarray == dataset.floatarray)
    assert dataset2.dictionary == dataset.dictionary
    # Restore dataset from dictionary
    restore_dataset(dataset, dsdict)
    # Check dataset values
    assert dataset.integer == dsdict["integer"]
    assert dataset.float_slider == dsdict["float_slider"]
    assert dataset.bool1 == dsdict["bool1"]
    assert dataset.string == dsdict["string"]
    assert np.all(dataset.floatarray == dsdict["floatarray"])
    assert dataset.dictionary == dsdict["dictionary"]


if __name__ == "__main__":
    test_update_restore_dataset()

Create a dataset class from a function signature


from __future__ import annotations

import numpy as np

from guidata.dataset import create_dataset_from_func
from guidata.env import execenv


def func_ok(
    a: int, b: float, c: str = "test", d: dict[str, int] = {"x": 1, "y": 3}
) -> None:
    """A function with type annotations"""
    pass


def func_no_type(a, b, c="test"):
    """A function without type annotations"""
    pass


def func_no_default(a: int, b: float, c: str, data: np.ndarray) -> None:
    """A function without default values"""
    pass


def test_dataset_from_func():
    """Test generate dataset class from function"""
    for func in (func_ok, func_no_default):
        execenv.print(func.__name__)
        dataset = create_dataset_from_func(func)
        execenv.print(dataset)
        execenv.print(dataset.create(a=1, b=2.0))
        execenv.print("")
    func = func_no_type
    try:
        create_dataset_from_func(func)
        assert False, "Should have raised a ValueError"
    except ValueError:
        # This is expected
        pass


if __name__ == "__main__":
    test_dataset_from_func()

Create a dataset class from a function dictionary


import numpy as np

from guidata.dataset import create_dataset_from_dict
from guidata.env import execenv

TEST_DICT1 = {
    "a": 1,
    "b": 2.0,
    "c": "test",
    "d": {"x": 1, "y": 3},
    "data": np.array([1, 2, 3]),
}
TEST_DICT2 = {
    "a": 1,
    "unsupported": [2.0, 3.0],
}


def test_dataset_from_dict():
    """Test generate dataset class from a dictionary"""
    for dictionary in (TEST_DICT1,):
        execenv.print(dictionary)
        dataset = create_dataset_from_dict(dictionary)
        execenv.print(dataset)
        execenv.print(dataset.create())
        execenv.print("")
    try:
        create_dataset_from_dict(TEST_DICT2)
        assert False, "Should have raised a ValueError"
    except ValueError:
        # This is expected
        pass


if __name__ == "__main__":
    test_dataset_from_dict()

Data set HDF5 serialization/deserialization


import os

from guidata.env import execenv
from guidata.io import HDF5Reader, HDF5Writer
from guidata.qthelpers import qt_app_context
from guidata.tests.dataset.test_all_items import Parameters


def test_loadsave_hdf5():
    """Test HDF5 I/O"""
    fname = "test.h5"
    with qt_app_context():
        if os.path.exists(fname):
            os.unlink(fname)

        e = Parameters()
        if execenv.unattended or e.edit():
            writer = HDF5Writer(fname)
            e.serialize(writer)
            writer.close()

            e = Parameters()
            reader = HDF5Reader(fname)
            e.deserialize(reader)
            reader.close()
            e.edit()
            os.unlink(fname)
        execenv.print("OK")


if __name__ == "__main__":
    test_loadsave_hdf5()

Data set JSON serialization/deserialization


import os

from guidata.env import execenv
from guidata.io import JSONReader, JSONWriter
from guidata.qthelpers import qt_app_context
from guidata.tests.dataset.test_all_items import Parameters


def test_loadsave_json():
    """Test JSON I/O"""
    fname = "test.json"
    with qt_app_context():
        if os.path.exists(fname):
            os.unlink(fname)

        e = Parameters()
        if execenv.unattended or e.edit():
            writer = JSONWriter(fname)
            e.serialize(writer)
            writer.save()

            e = Parameters()
            reader = JSONReader(fname)
            e.deserialize(reader)
            e.edit()
            os.unlink(fname)
        execenv.print("OK")


if __name__ == "__main__":
    test_loadsave_json()