Newer
Older
from multikeydict.nestedmkdict import NestedMKDict
from multikeydict.visitor import NestedMKDictVisitor
from dagflow.output import Output
from typing import Union, Tuple, List, Optional
from tabulate import tabulate
from pandas import DataFrame
import pandas as pd
pd.set_option('display.max_rows', None)
pd.set_option('display.max_colwidth', 100)
from shutil import get_terminal_size
def trunc(text: str, width: int) -> str:
return '\n'.join(line[:width] for line in text.split('\n'))
class ParametersStorage(NestedMKDict):
def read_paths(self) -> None:
for key, value in self.walkitems():
labels = getattr(value, 'labels', None)
if labels is None:
continue
key = '.'.join(key)
labels.setdefault('paths', []).append(key)
def plot(
self,
*args,
close: bool=True,
show: bool=True,
**kwargs
) -> None:
from dagflow.plot import plot_auto
if close:
from matplotlib.pyplot import close
if show:
from matplotlib.pyplot import show
for key, value in self.walkitems():
if not isinstance(value, Output):
continue
plot_auto(value, *args, **kwargs)
if show: show()
if close: close()
def to_list(self, **kwargs) -> list:
return self.visit(ParametersVisitor(kwargs)).data_list
def to_dict(self, **kwargs) -> NestedMKDict:
return self.visit(ParametersVisitor(kwargs)).data_dict
def to_df(self, *, columns: Optional[List[str]]=None, **kwargs) -> DataFrame:
if columns is None:
columns = ['path', 'value', 'central', 'sigma', 'flags', 'label']
df = DataFrame(dct, columns=columns)
df.insert(4, 'sigma_rel_perc', df['sigma'])
df['sigma_rel_perc'] = df['sigma']/df['central']*100.
df['sigma_rel_perc'].mask(df['central']==0, nan, inplace=True)
for key in ('central', 'sigma', 'sigma_rel_perc'):
if df[key].isna().all():
del df[key]
else:
df[key].fillna('-', inplace=True)
df['value'].fillna('-', inplace=True)
df['flags'].fillna('', inplace=True)
df['label'].fillna('', inplace=True)
if (df['flags']=='').all():
del df['flags']
return df
def to_string(self, **kwargs) -> str:
df = self.to_df()
return df.to_string(**kwargs)
def to_table(
self,
*,
df_kwargs: dict={},
truncate: Union[int, bool] = False,
**kwargs
) -> str:
df = self.to_df(**df_kwargs)
kwargs.setdefault('headers', df.columns)
ret = tabulate(df, **kwargs)
if truncate:
if isinstance(truncate, bool):
truncate = get_terminal_size().columns
return trunc(ret, width=truncate)
return ret
def to_latex(self, *, return_df: bool=False, **kwargs) -> Union[str, Tuple[str, DataFrame]]:
df = self.to_df(label_from='latex', **kwargs)
tex = df.to_latex(escape=False)
if return_df:
return tex, df
return tex
def to_datax(self, filename: str, **kwargs) -> None:
data = self.to_dict(**kwargs)
skip = {'path', 'label', 'flags'} # TODO, add LaTeX label
odict = {'.'.join(k): v for k, v in data.walkitems() if not (k and k[-1] in skip)}
datax(filename, **odict)
class ParametersVisitor(NestedMKDictVisitor):
__slots__ = ('_kwargs', '_data_list', '_localdata', '_path')
_kwargs: dict
_data_list: List[dict]
_data_dict: NestedMKDict
_localdata: List[dict]
_paths: List[Tuple[str, ...]]
_path: Tuple[str, ...]
# _npars: List[int]
def __init__(self, kwargs: dict):
self._kwargs = kwargs
# self._npars = []
@property
def data_list(self) -> List[dict]:
return self._data_list
@property
def data_dict(self) -> NestedMKDict:
return self._data_dict
def start(self, dct):
self._data_list = []
self._data_dict = NestedMKDict({}, sep='.')
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
self._path = ()
self._paths = []
self._localdata = []
def enterdict(self, k, v):
if self._localdata:
self.exitdict(self._path, None)
self._path = k
self._paths.append(self._path)
self._localdata = []
def visit(self, key, value):
try:
dct = value.to_dict(**self._kwargs)
except AttributeError:
return
subkey = key[len(self._path):]
subkeystr = '.'.join(subkey)
if self._path:
dct['path'] = f'.. {subkeystr}'
else:
dct['path'] = subkeystr
self._localdata.append(dct)
def exitdict(self, k, v):
if self._localdata:
'path': f"group: {'.'.join(self._path)} [{len(self._localdata)}]"
})
self._data_list.extend(self._localdata)
self._localdata = []
if self._paths:
del self._paths[-1]
self._path = self._paths[-1] if self._paths else ()
def stop(self, dct):
pass