Source code for openmdao.visualization.options_widget
"""
A widget-based representation of OptionsDictionary for use in Jupyter notebooks.
"""
try:
import ipywidgets as widgets
from ipywidgets import Layout
from IPython.display import display
except Exception:
widgets = None
from openmdao.utils.om_warnings import issue_warning
[docs]class OptionsWidget(object):
"""
Widget to set options.
Parameters
----------
opts : OptionsDictionary
Options to edit.
"""
[docs] def __init__(self, opts):
"""
Initialize.
"""
if widgets is None:
issue_warning(f"ipywidgets is required to use {self.__class__.__name__}."
"To install it run `pip install openmdao[notebooks]`.")
return
_dict = opts._dict
_widgets = []
_style = {'description_width': 'initial', 'align-items': 'center'}
messages = widgets.Output()
@messages.capture(clear_output=True)
def option_changed(change):
owner = change['owner']
newval = change['new']
name = owner.description
option = _dict[name]
# if it's an arbitrary list, parse lines of text
if option['types'] is list and option['values'] is None:
newval = newval.strip().split('\n')
try:
option['val'] = newval
except ValueError as err:
print(str(err))
for name, option in sorted(_dict.items()):
val = option['val']
types = option['types']
values = option['values']
desc = option['desc']
if values:
if types is list:
_widgets.append(widgets.SelectMultiple(
description=name,
tooltip=desc,
options=sorted(values),
value=val,
disabled=False,
style=_style
))
continue
else:
_widgets.append(widgets.Dropdown(
description=name,
tooltip=desc,
options=values,
value=val,
disabled=False,
style=_style
))
continue
upper = option['upper']
lower = option['lower']
if upper and lower:
if isinstance(val, int):
_widgets.append(widgets.IntSlider(
description=name,
tooltip=desc,
min=lower,
max=upper,
value=val,
step=1,
disabled=False,
continuous_update=False,
orientation='horizontal',
readout=True,
readout_format='d',
style=_style
))
else:
_widgets.append(widgets.FloatSlider(
description=name,
tooltip=desc,
min=lower,
max=upper,
value=val,
disabled=False,
continuous_update=False,
orientation='horizontal',
readout=True,
readout_format='f',
style=_style
))
continue
if isinstance(val, float):
_widgets.append(widgets.FloatText(
description=name,
tooltip=desc,
min=lower,
max=upper,
value=val,
disabled=False,
continuous_update=False,
orientation='horizontal',
readout=True,
readout_format='f',
style=_style
))
continue
if isinstance(val, int):
_widgets.append(widgets.IntText(
description=name,
tooltip=desc,
min=lower,
max=upper,
value=val,
step=1,
disabled=False,
continuous_update=False,
orientation='horizontal',
readout=True,
readout_format='d',
style=_style
))
continue
types = option['types']
if isinstance(types, list):
_widgets.append(widgets.Textarea(
description=name,
tooltip=desc,
value='\n'.join(val),
continuous_update=False,
rows=5,
disabled=False,
style=_style
))
continue
# unhandled option type, just show value as uneditable text
_widgets.append(widgets.Textarea(
description=name,
tooltip=desc,
value=str(val),
disabled=True,
style=_style
))
for wdgt in _widgets:
wdgt.observe(option_changed, 'value')
# sort widgets by how many rows they use
_wdgt_rows = [(wdgt.rows if getattr(wdgt, 'rows', None) else 1, wdgt) for wdgt in _widgets]
_wdgt_rows.sort(key=lambda x: x[0])
_widgets = [wdgt for _, wdgt in _wdgt_rows]
box_layout = Layout(display='flex', flex_flow='row wrap')
display(widgets.GridBox(children=_widgets, layout=box_layout))
display(messages)