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