Source code for geoh5py.ui_json.templates

#  Copyright (c) 2024 Mira Geoscience Ltd.
#
#  This file is part of geoh5py.
#
#  geoh5py is free software: you can redistribute it and/or modify
#  it under the terms of the GNU Lesser General Public License as published by
#  the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.
#
#  geoh5py is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU Lesser General Public License for more details.
#
#  You should have received a copy of the GNU Lesser General Public License
#  along with geoh5py.  If not, see <https://www.gnu.org/licenses/>.

# pylint: disable=R0913

from __future__ import annotations

import inspect
import uuid
from uuid import UUID

from .. import groups, objects
from ..shared import Entity

known_object_types = [
    member.default_type_uid()
    for _, member in inspect.getmembers(objects)
    if hasattr(member, "default_type_uid") and member.default_type_uid() is not None
]

known_group_types = [
    member.default_type_uid()
    for _, member in inspect.getmembers(groups)
    if hasattr(member, "default_type_uid") and member.default_type_uid() is not None
]


[docs] def optional_parameter(state: str) -> dict[str, bool]: """ Returns dictionary to make existing ui optional via .update() method. :param state: Initial state of optional parameter. Can be 'enabled' or 'disabled'. """ form_opt = {"optional": True} if state == "enabled": form_opt["enabled"] = True elif state == "disabled": form_opt["enabled"] = False else: raise ValueError( "Unrecognized state option. Must be either 'enabled' or 'disabled'." ) return form_opt
[docs] def bool_parameter( main: bool = True, label: str = "Logical data", value: bool = False ) -> dict: """ Checkbox for true/false choice. :param main: Show ui in main. :param label: Label identifier. :param value: Input value. :returns: Ui_json compliant dictionary. """ return { "main": main, "label": label, "value": value, }
[docs] def integer_parameter( main: bool = True, label: str = "Integer data", value: int = 1, vmin: int | None = None, vmax: int | None = None, optional: str | None = None, ) -> dict: """ Input box for integer value. :param main: Show ui in main. :param label: Label identifier. :param value: Input value. :param vmin: Minimum value allowed. :param vmax: Maximum value allowed. :param optional: Make optional if not None. Initial state provided by not None value. Can be either 'enabled' or 'disabled'. :returns: Ui_json compliant dictionary. """ form = {"main": main, "label": label, "value": value} for prop, val in {"vmin": vmin, "vmax": vmax}.items(): if val is not None: form[prop] = val if optional is not None: form.update(optional_parameter(optional)) return form
[docs] def float_parameter( main: bool = True, label: str = "Float data", value: float = 1.0, vmin: float | None = None, vmax: float | None = None, precision: int = 2, line_edit: bool = True, optional: str | None = None, ) -> dict: """ Input box for float value. :param main: Show form in main. :param label: Label identifier. :param value: Input value. :param vmin: Minimum value allowed. :param vmax: Maximum value allowed. :param line_edit: Allow line edit or spin box :param optional: Make optional if not None. Initial state provided by not None value. Can be either 'enabled' or 'disabled'. :returns: Ui_json compliant dictionary. """ form = { "main": main, "label": label, "value": value, "precision": precision, "lineEdit": line_edit, } for prop, val in {"vmin": vmin, "vmax": vmax}.items(): if val is not None: form[prop] = val if optional is not None: form.update(optional_parameter(optional)) return form
[docs] def string_parameter( main: bool = True, label: str = "String data", value: str = "data", optional: str | None = None, ) -> dict: """ Input box for string value. :param main: Show form in main. :param label: Label identifier. :param value: Input string value. :param optional: Make optional if not None. Initial state provided by not None value. Can be either 'enabled' or 'disabled'. :returns: Ui_json compliant dictionary. """ form = {"main": main, "label": label, "value": value} if optional is not None: form.update(optional_parameter(optional)) return form
[docs] def choice_string_parameter( choice_list: tuple = ("Option A", "Option B"), label: str = "String data", main: bool = True, multi_select: bool = False, optional: str | None = None, value: str = "Option A", ) -> dict: """ Dropdown menu of string choices. :param main: Show form in main. :param choice_list: List of options. :param label: Label identifier. :param multi_select: Option to select multiple choices. :param value: Input value. :param optional: Make optional if not None. Initial state provided by not None value. Can be either 'enabled' or 'disabled'. :returns: Ui_json compliant dictionary. """ form = { "main": main, "multiSelect": multi_select, "label": label, "value": value, "choiceList": choice_list, } if optional is not None: form.update(optional_parameter(optional)) return form
[docs] def file_parameter( main: bool = True, label: str = "File choices", file_description: tuple = (), file_type: tuple = (), value: str = "", optional: str | None = None, ) -> dict: """ File loader for specific extensions. :param main: Show form in main. :param label: Label identifier. :param value: Input value. :param file_description: Title used to describe each type. :param file_type: Extension of files to display. :param optional: Make optional if not None. Initial state provided by not None value. Can be either 'enabled' or 'disabled'. :returns: Ui_json compliant dictionary. """ form = { "fileDescription": file_description, "fileType": file_type, "main": main, "label": label, "value": value, } if optional is not None: form.update(optional_parameter(optional)) return form
[docs] def group_parameter( main: bool = True, label: str = "Object", group_type: tuple = tuple(known_group_types), value: str | None = None, optional: str | None = None, ) -> dict: """ Dropdown menu of groups of specific types. :param main: Show form in main. :param label: Label identifier. :param value: Input value. :param group_type: Type of selectable groups. :param optional: Make optional if not None. Initial state provided by not None value. Can be either 'enabled' or 'disabled'. :returns: Ui_json compliant dictionary. """ form = {"main": main, "label": label, "value": value, "groupType": group_type} if optional is not None: form.update(optional_parameter(optional)) return form
[docs] def object_parameter( main: bool = True, label: str = "Object", mesh_type: tuple = tuple(known_object_types), multi_select: bool = False, value: str | None = None, optional: str | None = None, ) -> dict: """ Dropdown menu of objects of specific types. :param main: Show form in main. :param label: Label identifier. :param value: Input value. :param multi_select: Option to select multiple choices. :param mesh_type: Type of selectable objects. :param optional: Make optional if not None. Initial state provided by not None value. Can be either 'enabled' or 'disabled'. :returns: Ui_json compliant dictionary. """ form = { "main": main, "label": label, "value": value, "multiSelect": multi_select, "meshType": mesh_type, } if optional is not None: form.update(optional_parameter(optional)) return form
[docs] def data_parameter( main: bool = True, label: str = "Data channel", association: str = "Vertex", data_type: str = "Float", data_group_type: str | None = None, parent: str = "", value: str = "", optional: str | None = None, ) -> dict: """ Dropdown menu of data from parental object. :param main: Show form in main. :param label: Label identifier. :param value: Input value. :param association: Data association type from 'Vertex' or 'Cell'. :param data_type: Type of data selectable from 'Float', 'Integer' or 'Reference'. :param data_group_type: [Optional] Select from property_groups of type. '3D vector', 'Dip direction & dip', 'Strike & dip', or 'Multi-element'. :param multi_select: Option to select multiple choices. :param parent: Parameter name corresponding to the parent object. :param optional: Make optional if not None. Initial state provided by not None value. Can be either 'enabled' or 'disabled'. :returns: Ui_json compliant dictionary. """ form = { "main": main, "association": association, "dataType": data_type, "label": label, "parent": parent, "value": value, } if data_group_type is not None and data_group_type in [ "3D vector", "Dip direction & dip", "Strike & dip", "Multi-element", ]: form["dataGroupType"] = data_group_type if optional is not None: form.update(optional_parameter(optional)) return form
[docs] def data_value_parameter( main: bool = True, label: str = "Data channel", association: str = "Vertex", data_type: str = "Float", parent: str = "", value: float = 0.0, is_value: bool = True, prop: UUID | Entity | None = None, optional: str | None = None, ) -> dict: """ Dropdown of data or input box. :param main: Show form in main. :param label: Label identifier. :param value: Input value. :param association: Data association type from 'Vertex' or 'Cell'. :param data_type: Type of data selectable from 'Float', 'Integer' or 'Reference'. :param data_group_type: [Optional] Select from property_groups of type. '3D vector', 'Dip direction & dip', 'Strike & dip', or 'Multi-element'. :param parent: Parameter name corresponding to the parent object. :param is_value: Display the input box or dropdown menu. :param prop: Data entity selected in the dropdown menu if 'is_value=False'. :param optional: Make optional if not None. Initial state provided by not None value. Can be either 'enabled' or 'disabled'. :returns: Ui_json compliant dictionary. """ form = { "main": main, "association": association, "dataType": data_type, "label": label, "parent": parent, "value": value, "isValue": is_value, "property": prop, "min": value, } if optional is not None: form.update(optional_parameter(optional)) return form
[docs] def drillhole_group_data( value: list[str] | None = None, main: bool = True, label: str = "Data channel", group_type: UUID = groups.DrillholeGroup.default_type_uid(), group_value: UUID | None = None, multiselect: bool = True, optional: str | None = None, enabled: bool = True, tooltip: str = "Select the data channel to use for the calculation.", ) -> dict: """ Dropdown of data or input box. :param main: Show form in main. :param label: Label identifier. :param value: Input value. :param group_type: The group type to select, must be drillhole group. :param group_value: The selected group UUID. :param multiselect: Allow multiple data selection. :param value: The name of the Data channel to extract. :param optional: Make optional if not None. Initial state provided by not None :param enabled: Enable or disable the form. :param tooltip: The tooltip to display when hovering over the form. :returns: Ui_json compliant dictionary. """ form = { "main": main, "label": label, "groupType": group_type, "groupValue": group_value, "multiselect": multiselect, "value": value, "optional": optional, "enabled": enabled, "tooltip": tooltip, } if optional is not None: form.update(optional_parameter(optional)) return form
[docs] def range_label_template( main: bool = True, label: str = "Range", allow_complement: bool = False, is_complement: bool = False, parent: str = "", property_: str | uuid.UUID = "", association: str = "Vertex", data_type: list[str] | str = "Float", value: list[float | int] | None = None, range_label: str = "Values", enabled: bool = True, optional: str | None = None, ) -> dict: """ Template for range label. Or it is a multiselect data on a property group if referenced data. Or they are 2 values, an upper and lower bound as float values. In the second scenario, is_complement allows to invert the range. :param main: Show form in main. :param label: The label identifier. :param allow_complement: If users can invert the range. :param is_complement: If the range is inverted. :param parent: The parent object. :param property_: The property uid associated with the range. :param association: The association type. :param data_type: The data type of the range. :param value: The value of the range. :param range_label: The label of the range. :param enabled: The state of the form. :param optional: Make optional if not None. Initial state provided by not None. :return: The form dictionary. """ form = { "main": main, "label": label, "allowComplement": allow_complement, "isComplement": is_complement, "parent": parent, "property": property_, "association": association, "dataType": data_type, "value": value, "rangeLabel": range_label, "enabled": enabled, } if optional is not None: form.update(optional_parameter(optional)) return form