Skip to content

Commit

Permalink
[Issue-1501] new suite output design (#1627)
Browse files Browse the repository at this point in the history
* new suite output design
  • Loading branch information
yromanyshyn committed Jun 16, 2022
1 parent 3d532f7 commit a4c07dc
Show file tree
Hide file tree
Showing 20 changed files with 411 additions and 260 deletions.
7 changes: 5 additions & 2 deletions deepchecks/core/condition.py
Expand Up @@ -115,8 +115,11 @@ def priority(self) -> int:

def is_pass(self, fail_if_warning=True) -> bool:
"""Return true if the condition has passed."""
passed_categories = [ConditionCategory.PASS] if fail_if_warning else \
[ConditionCategory.PASS, ConditionCategory.WARN]
passed_categories = (
(ConditionCategory.PASS,)
if fail_if_warning
else (ConditionCategory.PASS, ConditionCategory.WARN)
)
return self.category in passed_categories

def get_icon(self):
Expand Down
92 changes: 89 additions & 3 deletions deepchecks/core/serialization/common.py
Expand Up @@ -31,11 +31,14 @@
from plotly.offline.offline import get_plotlyjs

from deepchecks.core import check_result as check_types
from deepchecks.core import errors
from deepchecks.utils.dataframes import un_numpy
from deepchecks.utils.strings import get_ellipsis

__all__ = [
'aggregate_conditions',
'create_results_dataframe',
'create_failures_dataframe',
'form_output_anchor',
'Html',
'normalize_widget_style',
Expand Down Expand Up @@ -105,7 +108,7 @@ def normalize_value(value: object) -> t.Any:


def aggregate_conditions(
check_results: t.Union['check_types.CheckResult', t.List['check_types.CheckResult']],
check_results: t.Union['check_types.CheckResult', t.Sequence['check_types.CheckResult']],
max_info_len: int = 3000,
include_icon: bool = True,
include_check_name: bool = False,
Expand All @@ -115,7 +118,7 @@ def aggregate_conditions(
Parameters
----------
check_results : Union['CheckResult', List['CheckResult']]
check_results : Union['CheckResult', Sequence['CheckResult']]
check results to show conditions of.
max_info_len : int
max length of the additional info.
Expand All @@ -124,7 +127,9 @@ def aggregate_conditions(
include_check_name : bool, default False
whether to include check name into dataframe or not
output_id : str
the unique id to append for the check names to create links (won't create links if None/empty).
unique identifier of the output, it will be used to
form a link (html '<a></a>' tag) to the check result
full output
Returns
-------
Expand Down Expand Up @@ -176,6 +181,87 @@ def aggregate_conditions(
return df.style.hide_index()


def create_results_dataframe(
results: t.Sequence['check_types.CheckResult'],
output_id: t.Optional[str] = None,
) -> pd.DataFrame:
"""Create dataframe with check results.
Parameters
----------
results : Sequence['CheckResult']
check results
output_id : str
unique identifier of the output, it will be used to
form a link (html '<a></a>' tag) to the check result
full output
Returns
-------
pd.Dataframe:
the condition table.
"""
data = []

for check_result in results:
check_header = check_result.get_header()
if output_id and check_result.display:
href = f'href="#{check_result.get_check_id(output_id)}"'
header = f'<a {href}>{check_header}</a>'
else:
header = check_header
summary = check_result.get_metadata(with_doc_link=True)['summary']
data.append([header, summary])

return pd.DataFrame(
data=data,
columns=['Check', 'Summary']
)


def create_failures_dataframe(
failures: t.Sequence[t.Union['check_types.CheckFailure', 'check_types.CheckResult']]
) -> pd.DataFrame:
"""Create dataframe with check failures.
Parameters
----------
failures : Sequence[Union[CheckFailure, CheckResult]]
check failures
Returns
-------
pd.Dataframe:
the condition table.
"""
data = []

for it in failures:
if isinstance(it, check_types.CheckResult):
data.append([it.get_header(), 'Nothing found', 2])
elif isinstance(it, check_types.CheckFailure):
message = (
it.exception.html
if isinstance(it.exception, errors.DeepchecksBaseError)
else str(it.exception)
)
error_types = (
errors.DatasetValidationError,
errors.ModelValidationError,
errors.DeepchecksProcessError,
)
if isinstance(it.exception, error_types):
message = f'{type(it.exception).__name__}: {message}'
data.append((it.header, message, 1))
else:
raise TypeError(f'Unknown result type - {type(it).__name__}')

df = pd.DataFrame(data=data, columns=['Check', 'Reason', 'priority'])
df.sort_values(by=['priority'], inplace=True)
df.drop('priority', axis=1, inplace=True)
return df


def requirejs_script(connected: bool = True):
"""Return requirejs script tag.
Expand Down
30 changes: 4 additions & 26 deletions deepchecks/core/serialization/suite_result/html.py
Expand Up @@ -13,16 +13,13 @@
import typing as t
import warnings

import pandas as pd

from deepchecks.core import check_result as check_types
from deepchecks.core import errors, suite
from deepchecks.core.errors import DeepchecksBaseError
from deepchecks.core import suite
from deepchecks.core.serialization.abc import HtmlSerializer
from deepchecks.core.serialization.check_result.html import CheckResultSection
from deepchecks.core.serialization.check_result.html import CheckResultSerializer as CheckResultHtmlSerializer
from deepchecks.core.serialization.common import (Html, aggregate_conditions, form_output_anchor, plotlyjs_script,
requirejs_script)
from deepchecks.core.serialization.common import (Html, aggregate_conditions, create_failures_dataframe,
form_output_anchor, plotlyjs_script, requirejs_script)
from deepchecks.core.serialization.dataframe.html import DataFrameSerializer as DataFrameHtmlSerializer

__all__ = ['SuiteResultSerializer']
Expand Down Expand Up @@ -332,26 +329,7 @@ def prepare_failures_list(self) -> str:
if not results:
return ''

data = [] # type List[Tuple[check-header:str, message:str, priority:int]]

for it in results:
if not isinstance(it, check_types.CheckFailure):
data.append([it.get_header(), 'Nothing found', 2])
else:
message = it.exception.html if isinstance(it.exception, DeepchecksBaseError) else str(it.exception)
error_types = (
errors.DatasetValidationError,
errors.ModelValidationError,
errors.DeepchecksProcessError,
)
if isinstance(it.exception, error_types):
message = f'{type(it.exception).__name__}: {message}'

data.append((it.header, message, 1))

df = pd.DataFrame(data=data, columns=['Check', 'Reason', 'priority'])
df.sort_values(by=['priority'], inplace=True)
df.drop('priority', axis=1, inplace=True)
df = create_failures_dataframe(results)

with warnings.catch_warnings():
warnings.simplefilter(action='ignore', category=FutureWarning)
Expand Down

0 comments on commit a4c07dc

Please sign in to comment.