Skip to content

Commit

Permalink
Merge pull request #1 from Ashwolaa/features/params_group_type
Browse files Browse the repository at this point in the history
XML behavior with parameters with children but without group type
  • Loading branch information
seb5g authored Nov 6, 2024
2 parents 95a3fca + d4c3def commit d38b153
Show file tree
Hide file tree
Showing 6 changed files with 112 additions and 57 deletions.
5 changes: 5 additions & 0 deletions src/pymodaq_gui/examples/parameter_ex.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ class ParameterEx(ParameterManager):
{'title': 'A visible group:', 'name': 'agroup', 'type': 'group', 'children': []},
{'title': 'An hidden group:', 'name': 'bgroup', 'type': 'group', 'children': [], 'visible': False}, # this
# visible option is not available in usual pyqtgraph group
{'title': 'A bool with children:', 'name': 'booleans_group', 'type': 'bool', 'value':False, 'tip': 'Any Parameter can have its own children', 'children': [
{'title': 'A bool in a bool', 'name': 'a_bool_in_a_bool', 'type': 'bool', 'value': True},
{'title': 'A push with children', 'name': 'aboolpush', 'type': 'bool_push', 'value': True, 'label': 'action','children':[
{'title': 'A string in a group', 'name': 'atte_in_a_group', 'type': 'str', 'value': 'this is a string you can edit'},
]},]},
]},

{'title': 'Numbers:', 'name': 'numbers', 'type': 'group', 'children': [
Expand Down
65 changes: 35 additions & 30 deletions src/pymodaq_gui/parameter/ioxml.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,22 +41,20 @@ def walk_parameters_to_xml(parent_elt=None, param=None):
if parent_elt is None:
opts = dict_from_param(param)
parent_elt = ET.Element(param.name(), **opts)
param_type = str(param.type())
if 'group' not in param_type: # covers 'group', custom 'groupmove', 'groupai' ...
if 'value' in param.opts:
add_text_to_elt(parent_elt, param)

params_list = param.children()
for param in params_list:

opts = dict_from_param(param)
elt = ET.Element(param.name(), **opts)
param_type = str(param.type())
if 'group' not in param_type: # covers 'group', custom 'groupmove'...
add_text_to_elt(elt, param)
else:
if param.hasChildren():
walk_parameters_to_xml(elt, param)
if 'value' in param.opts:
add_text_to_elt(elt, param)

parent_elt.append(elt)

return parent_elt


Expand Down Expand Up @@ -193,6 +191,10 @@ def dict_from_param(param):
movelist = str(param.opts['movelist'])
opts.update(dict(movelist=movelist))

if 'label' in param.opts:
label = str(param.opts['label'])
opts.update(dict(label=label))

if 'show_pb' in param.opts:
if param.opts['show_pb']:
show_pb = '1'
Expand Down Expand Up @@ -278,6 +280,10 @@ def elt_to_dict(el):
addText = str(el.get('addText'))
param.update(dict(addText=addText))

if 'label' in el.attrib.keys():
label = str(el.get('label'))
param.update(dict(label=label))

# if 'limits' in el.attrib.keys():
# try:
# values = list(eval(el.get('limits'))) # make sure the evaluated values are returned as list (in case another
Expand Down Expand Up @@ -389,37 +395,35 @@ def walk_xml_to_parameter(params=[], XML_elt=None):
raise TypeError('not valid XML element')

if len(XML_elt) == 0:
param_dict = elt_to_dict(XML_elt)
param_type = XML_elt.get('type')

if 'group' not in param_type: # covers 'group', custom 'groupmove'...
set_txt_from_elt(XML_elt, param_dict)
param_dict = set_dict_from_el(XML_elt)
params.append(param_dict)

for el in XML_elt:
param_dict = elt_to_dict(el)
param_type = el.get('type')

if 'group' not in param_type: # covers 'group', custom 'groupmove'...
set_txt_from_elt(el, param_dict)
param_dict = set_dict_from_el(el)
if param_dict['type'] not in PARAM_TYPES:
param_dict['type'] = 'group' # in case the custom group has been defined somewhere but not
# registered again in this session
if len(el) == 0:
children = []
else:
if param_type not in PARAM_TYPES:
param_dict['type'] = 'group' # in case the custom group has been defined somewhere but not
# registered again in this session
if len(el) == 0:
children = []
else:
subparams = []
children = walk_xml_to_parameter(subparams, el)
param_dict['children'] = children

param_dict['name'] = el.tag

subparams = []
children = walk_xml_to_parameter(subparams, el)
param_dict['children'] = children
params.append(param_dict)

except Exception as e: # to be able to debug when there's an issue
raise e
return params

def set_dict_from_el(el):
"""Convert an element into a dict
----------
el: xml element
param_dict: dictionnary from which the parameter will be constructed
"""
param_dict = elt_to_dict(el)
set_txt_from_elt(el, param_dict)
return param_dict

def set_txt_from_elt(el, param_dict):
"""
Expand All @@ -431,7 +435,8 @@ def set_txt_from_elt(el, param_dict):
"""
val_text = el.text
param_type = el.get('type')
param_type = param_dict['type']
# param_type = el.get('type') # Redundancy (param_dict already has this attribute)
if val_text is not None:
if param_type == 'float':
param_value = float(val_text)
Expand Down
68 changes: 46 additions & 22 deletions src/pymodaq_gui/parameter/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,37 +143,61 @@ def compareValuesParameter(param1:Parameter,param2:Parameter,)-> bool:
"""
return getValues(param1) == getValues(param2)

def iter_children(param, childlist=[]):
"""Get a list of parameters name under a given Parameter
| Returns all childrens names.
def iter_children(param, childlist=[], filter_type=(), filter_name=(), select_filter=False)-> list:

=============== ================================= ====================================
**Parameters** **Type** **Description**
*param* instance of pyqtgraph parameter the root node to be coursed
*childlist* list the child list recetion structure
=============== ================================= ====================================
"""
Get a list of parameters' name under a given Parameter (see iter_children_params)
Returns
-------
childlist : parameter list
The list of the children from the given node.
Returns
-------
list
The list of the children name from the given node.
"""
for child in param.children():
childlist.append(child.name())
if child.hasChildren():
# if 'group' in child.type():
childlist.extend(iter_children(child, []))
return childlist
return iter_children_params(param, childlist=childlist, output_type='name', filter_type=(), filter_name=(), select_filter=False)


def iter_children_params(param, childlist=[]):
"""Get a list of parameters under a given Parameter
def iter_children_params(param, childlist=[], output_type=None, filter_type=(), filter_name=(), select_filter=False)-> list:
"""
Get a list of parameters under a given Parameter.
Parameters
----------
param : Parameter (pyqtgraph)
the root node to be coursed
childlist: list
the child/output list
output_type: str
the attribute of parameter that will be added to the output list
filter_type: list
filter children sharing those types
filter_name: list
filter children sharing those names
select_filter: bool
if True, add filtered parameters to output list.
if False (default), add non-filtered parameter to output list.
Returns
-------
list
The list of the children from the given node.
"""

for child in param.children():
childlist.append(child)
# XNOR Gate
is_filtered = child.type() in filter_type or child.name() in filter_name
add_selected_child = select_filter and is_filtered
add_notselected_child = not select_filter and not is_filtered
if add_selected_child or add_notselected_child:
if output_type is not None:
try:
output = getattr(child,output_type)()
except Exception as e:
print(str(e))
else:
output = child
childlist.append(output)
if child.hasChildren():
childlist.extend(iter_children_params(child, []))
childlist.extend(iter_children_params(child, [], output_type, filter_type, filter_name, select_filter))
return childlist


Expand Down
4 changes: 2 additions & 2 deletions tests/managers/parameter_manager_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from pyqtgraph.parametertree import Parameter

from pymodaq_gui.examples.parameter_ex import ParameterEx
from pymodaq_gui.parameter.utils import (
from pymodaq_gui.parameter.utils import (getValues,getStruct,
iter_children_params, compareParameters,
compareStructureParameter, compareValuesParameter)
from pymodaq_gui.utils.widgets.table import TableModel
Expand Down Expand Up @@ -69,7 +69,7 @@ def test_load(qtbot, tmp_path):
ptree.save_settings_slot(file_path)

parameter_copy = Parameter.create(name='settings', type='group', children=ParameterEx.params)
compareValuesParameter(ptree.settings, parameter_copy)
assert compareValuesParameter(ptree.settings, parameter_copy)

parameters = iter_children_params(ptree.settings, childlist=[])
parameters_copy = iter_children_params(parameter_copy, childlist=[])
Expand Down
6 changes: 3 additions & 3 deletions tests/parameter_test/param_ioxml_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,9 @@ class TestXMLbackForth():
def test_save_load_xml(self):

param_back = ioxml.XML_string_to_pobject(ioxml.parameter_to_xml_string(self.settings))

for child, child_back in zip(putils.iter_children_params(self.settings),
putils.iter_children_params(param_back)):
children_list_in = putils.iter_children_params(self.settings)
children_list_back = putils.iter_children_params(param_back)
for child, child_back in zip(children_list_in,children_list_back):
assert child_back.name() == child.name()
assert child_back.title() == child.title()
assert child_back.value() == child.value()
Expand Down
21 changes: 21 additions & 0 deletions tests/parameter_test/param_utils_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,27 @@
P3 = Parameter(name='settings3', type='group', children=params3)
P4 = Parameter(name='settings4', type='group', children=params4)

def test_iter_children_params():
settings = Parameter.create(name='settings', type='group', children=params)
param_list = putils.iter_children_params(settings,childlist=[],filter_type=['group'])
assert all([p.type() != 'group' for p in param_list])
param_list = putils.iter_children_params(settings,childlist=[],filter_name=['axis'])
assert all([p.name() != 'axis' for p in param_list])
param_list = putils.iter_children_params(settings,childlist=[],filter_name=['axis'],select_filter=True)
assert all([p.name() == 'axis' for p in param_list])
param_list = putils.iter_children_params(settings,childlist=[],filter_type=['group'],select_filter=True)
assert all([p.type() == 'group' for p in param_list])

def test_iter_children_attributes():
settings = Parameter.create(name='settings', type='group', children=params)
param_name = putils.iter_children_params(settings, childlist=[], output_type='name')
param_type = putils.iter_children_params(settings, childlist=[], output_type='type')
param_list = putils.iter_children_params(settings, childlist=[])
for p_name,p_type,p in zip(param_name,param_type,param_list):
assert p_name == p.name()
assert p_type == p.type()


def test_get_param_path():
settings = Parameter.create(name='settings', type='group', children=params)

Expand Down

0 comments on commit d38b153

Please sign in to comment.