Source code for orion.core.utils.format_terminal
"""
Utility functions for formatting prints to terminal
===================================================
Functions to build strings for terminal prints
"""
INFO_TEMPLATE = """\
{identification}
{commandline}
{configuration}
{algorithm}
{space}
{metadata}
{refers}
{stats}
"""
[docs]def format_info(experiment):
"""Render a string for all info of experiment"""
info_string = INFO_TEMPLATE.format(
identification=format_identification(experiment),
commandline=format_commandline(experiment),
configuration=format_config(experiment),
algorithm=format_algorithm(experiment),
space=format_space(experiment),
metadata=format_metadata(experiment),
refers=format_refers(experiment),
stats=format_stats(experiment),
)
return info_string
TITLE_TEMPLATE = """\
{title}
{empty:=<{title_len}}\
"""
[docs]def format_title(title):
"""Render a title above an horizontal bar"""
title_string = TITLE_TEMPLATE.format(title=title, title_len=len(title), empty="")
return title_string
DICT_EMPTY_LEAF_TEMPLATE = "{tab}{key}\n"
DICT_LEAF_TEMPLATE = "{tab}{key}: {value}\n"
DICT_NODE_TEMPLATE = "{tab}{key}:\n{value}\n"
[docs]def format_dict(dictionary, depth=0, width=4, templates=None):
r"""Render a dict on multiple lines
Parameters
----------
dictionary: dict
The dictionary to render
depth: int
Tab added at the beginning of every lines
width: int
Size of the tab added to each line, multiplied
by the depth of the object in the dict of dicts.
templates: dict
Templates for `empty_leaf`, `leaf` and `dict_node`.
Default is
`empty_leaf="{tab}{key}"`
`leaf="{tab}{key}: {value}\n"`
`dict_node="{tab}{key}:\n{value}\n"`
Examples
--------
>>> print(format_dict({1: {2: 3, 3: 4}, 2: {3: 4, 4: {5: 6}}}))
1:
2: 3
3: 4
2:
3: 4
4:
5: 6
>>> templates = {'leaf': '{tab}{key}={value}\n', 'dict_node': '{tab}{key}:\n{value}\n'}
>>> print(format_dict({1: {2: 3, 3: 4}, 2: {3: 4, 4: {5: 6}}}, templates=templates))
1:
2=3
3=4
2:
3=4
4:
5=6
"""
if isinstance(dictionary, (list, tuple)):
return format_list(dictionary, depth, width=width, templates=templates)
# To avoid using mutable objects as default values in function signature.
if templates is None:
templates = {}
empty_leaf_template = templates.get("empty_leaf", DICT_EMPTY_LEAF_TEMPLATE)
leaf_template = templates.get("leaf", DICT_LEAF_TEMPLATE)
node_template = templates.get("dict_node", DICT_NODE_TEMPLATE)
dict_string = ""
for key in sorted(dictionary.keys()):
tab = " " * (depth * width)
value = dictionary[key]
if isinstance(value, (dict, list, tuple)):
if not value:
dict_string += empty_leaf_template.format(tab=tab, key=key)
else:
subdict_string = format_dict(
value, depth + 1, width=width, templates=templates
)
dict_string += node_template.format(
tab=tab, key=key, value=subdict_string
)
else:
dict_string += leaf_template.format(tab=tab, key=key, value=value)
return dict_string.replace(" \n", "\n").rstrip("\n")
LIST_TEMPLATE = """\
{tab}[
{items}
{tab}]\
"""
LIST_ITEM_TEMPLATE = "{tab}{item}\n"
LIST_NODE_TEMPLATE = "{item}\n"
[docs]def format_list(a_list, depth=0, width=4, templates=None):
r"""Render a list on multiple lines
Parameters
----------
a_list: list
The list to render
depth: int
Tab added at the beginning of every lines
width: int
Size of the tab added to each line, multiplied
by the depth of the object in the list of lists.
templates: dict
Templates for `list`, `item` and `list_node`.
Default is
`list="{tab}[\n{items}\n{tab}]"`
`item="{tab}{item}\n"`
`list_node="{item}\n"`
Examples
--------
>>> print(format_list([1, [2, 3], 4, [5, 6, 7, 8]]))
[
1
[
2
3
]
4
[
5
6
7
8
]
]
>>> templates = {}
>>> templates['list'] = '{tab}\n{items}\n{tab}'
>>> templates['item'] = '{tab}- {item}\n'
>>> templates['list_node'] = '{tab}{item}\n'
>>> print(format_list([1, [2, 3], 4, [5, 6, 7, 8]], width=2, templates=templates))
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
"""
# To avoid using mutable objects as default values in function signature.
if templates is None:
templates = {}
list_template = templates.get("list", LIST_TEMPLATE)
item_template = templates.get("item", LIST_ITEM_TEMPLATE)
node_template = templates.get("list_node", LIST_NODE_TEMPLATE)
tab = " " * (depth * width)
list_string = ""
for i, item in enumerate(a_list, 1):
subtab = " " * ((depth + 1) * width)
if isinstance(item, (dict, list, tuple)):
item_string = format_dict(item, depth + 1, width=width, templates=templates)
list_string += node_template.format(tab=subtab, id=i, item=item_string)
else:
list_string += item_template.format(tab=subtab, id=i, item=item)
return list_template.format(tab=tab, items=list_string.rstrip("\n"))
ID_TEMPLATE = """\
{title}
name: {name}
version: {version}
user: {user}
"""
[docs]def format_identification(experiment):
"""Render a string for identification section"""
identification_string = ID_TEMPLATE.format(
title=format_title("Identification"),
name=experiment.name,
version=experiment.version,
user=experiment.metadata["user"],
)
return identification_string
COMMANDLINE_TEMPLATE = """\
{title}
{commandline}
"""
[docs]def format_commandline(experiment):
"""Render a string for commandline section"""
if "user_args" not in experiment.metadata:
return ""
commandline_string = COMMANDLINE_TEMPLATE.format(
title=format_title("Commandline"),
commandline=" ".join(experiment.metadata["user_args"]),
)
return commandline_string
CONFIG_TEMPLATE = """\
{title}
max trials: {experiment.max_trials}
max broken: {experiment.max_broken}
working dir: {experiment.working_dir}
"""
[docs]def format_config(experiment):
"""Render a string for config section"""
config_string = CONFIG_TEMPLATE.format(
title=format_title("Config"), experiment=experiment
)
return config_string
ALGORITHM_TEMPLATE = """\
{title}
{configuration}
"""
[docs]def format_algorithm(experiment):
"""Render a string for algorithm section"""
algorithm_string = ALGORITHM_TEMPLATE.format(
title=format_title("Algorithm"),
configuration=format_dict(experiment.configuration["algorithm"]),
)
return algorithm_string
SPACE_TEMPLATE = """\
{title}
{params}
"""
[docs]def format_space(experiment):
"""Render a string for space section"""
space_string = SPACE_TEMPLATE.format(
title=format_title("Space"),
params="\n".join(
name + ": " + experiment.space[name].get_prior_string()
for name in experiment.space.keys()
),
)
return space_string
METADATA_TEMPLATE = """\
{title}
user: {experiment.metadata[user]}
datetime: {experiment.metadata[datetime]}
orion version: {experiment.metadata[orion_version]}
VCS:
{vcs}
"""
[docs]def format_metadata(experiment):
"""Render a string for metadata section"""
metadata_string = METADATA_TEMPLATE.format(
title=format_title("Meta-data"),
experiment=experiment,
vcs=format_dict(experiment.metadata.get("VCS", {}), depth=1, width=2),
)
return metadata_string
REFERS_TEMPLATE = """\
{title}
root:{root}
parent:{parent}
adapter:{adapter}
"""
[docs]def format_refers(experiment):
"""Render a string for refers section"""
if experiment.node.root is experiment.node:
root = ""
parent = ""
adapter = ""
else:
root = experiment.node.root.name
parent = experiment.node.parent.name
adapter = "\n" + format_dict(
experiment.refers["adapter"].configuration, depth=1, width=2
)
refers_string = REFERS_TEMPLATE.format(
title=format_title("Parent experiment"),
root=(" " + root) if root else "",
parent=(" " + parent) if parent else "",
adapter=adapter,
)
return refers_string
STATS_TEMPLATE = """\
{title}
completed: {is_done}
trials completed: {stats.trials_completed}
best trial:
id: {stats.best_trials_id}
evaluation: {stats.best_evaluation}
params:
{best_params}
start time: {stats.start_time}
finish time: {stats.finish_time}
elapsed_time: {stats.elapsed_time}
"""
NO_STATS_TEMPLATE = """\
{title}
No trials executed...
"""
[docs]def format_stats(experiment):
"""Render a string for stat section
Parameters
----------
experiment: `orion.core.worker.experiment.Experiment`
templates: dict
templates for the title and `stats`.
See `format_title` for more info.
"""
stats = experiment.stats
if not stats.trials_completed:
return NO_STATS_TEMPLATE.format(title=format_title("Stats"))
best_params = get_trial_params(stats.best_trials_id, experiment)
stats_string = STATS_TEMPLATE.format(
title=format_title("Stats"),
stats=stats,
best_params=format_dict(best_params, depth=2, width=2),
is_done=experiment.is_done,
)
return stats_string
[docs]def get_trial_params(trial_id, experiment):
"""Get params from trial_id in given experiment"""
best_trial = experiment.get_trial(uid=trial_id)
if not best_trial:
return {}
return best_trial.params