Skip to content

Commit

Permalink
Fixes #1030 negative values on axes (#1183)
Browse files Browse the repository at this point in the history
* Fixes #1030 Weird labelling for y-axis in some error plots for negative values

* fix charset in inline html file

---------

Co-authored-by: DimaAmega <[email protected]>
  • Loading branch information
GwenVCX and DimaAmega authored Jul 22, 2024
1 parent a06fcfa commit bb8c809
Show file tree
Hide file tree
Showing 4 changed files with 154 additions and 128 deletions.
8 changes: 0 additions & 8 deletions src/evidently/renderers/notebook_utils.py

This file was deleted.

40 changes: 30 additions & 10 deletions src/evidently/suite/base_suite.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
from evidently.renderers.base_renderer import MetricRenderer
from evidently.renderers.base_renderer import RenderersDefinitions
from evidently.renderers.base_renderer import TestRenderer
from evidently.renderers.notebook_utils import determine_template
from evidently.tests.base_test import Test
from evidently.tests.base_test import TestParameters
from evidently.tests.base_test import TestResult
Expand All @@ -44,6 +43,8 @@
from evidently.utils.dashboard import SaveMode
from evidently.utils.dashboard import SaveModeMap
from evidently.utils.dashboard import TemplateParams
from evidently.utils.dashboard import file_html_template
from evidently.utils.dashboard import inline_iframe_html_template
from evidently.utils.dashboard import save_data_file
from evidently.utils.dashboard import save_lib_files
from evidently.utils.data_preprocessing import DataDefinition
Expand Down Expand Up @@ -124,7 +125,10 @@ def get_data_definition(
if self.engine is None:
raise ValueError("Cannot create data definition when engine is not set")
self.data_definition = self.engine.get_data_definition(
current_data, reference_data, column_mapping, categorical_features_cardinality
current_data,
reference_data,
column_mapping,
categorical_features_cardinality,
)
return self.data_definition

Expand Down Expand Up @@ -207,7 +211,7 @@ def _repr_html_(self):
dashboard_info=dashboard_info,
additional_graphs=graphs,
)
return self._render(determine_template("auto"), template_params)
return self._render(inline_iframe_html_template, template_params)

def show(self, mode="auto"):
"""
Expand All @@ -227,7 +231,7 @@ def show(self, mode="auto"):
try:
from IPython.display import HTML

return HTML(self._render(determine_template(mode), template_params))
return HTML(self._render(inline_iframe_html_template, template_params))
except ImportError as err:
raise Exception("Cannot import HTML from IPython.display, no way to show html") from err

Expand All @@ -238,9 +242,13 @@ def get_html(self):
dashboard_info=dashboard_info,
additional_graphs=graphs,
)
return self._render(determine_template("inline"), template_params)
return self._render(file_html_template, template_params)

def save_html(self, filename: Union[str, IO], mode: Union[str, SaveMode] = SaveMode.SINGLE_FILE):
def save_html(
self,
filename: Union[str, IO],
mode: Union[str, SaveMode] = SaveMode.SINGLE_FILE,
):
dashboard_id, dashboard_info, graphs = self._build_dashboard_info()
if isinstance(mode, str):
_mode = SaveModeMap.get(mode)
Expand All @@ -253,7 +261,7 @@ def save_html(self, filename: Union[str, IO], mode: Union[str, SaveMode] = SaveM
dashboard_info=dashboard_info,
additional_graphs=graphs,
)
render = self._render(determine_template("inline"), template_params)
render = self._render(file_html_template, template_params)
if isinstance(filename, str):
with open(filename, "w", encoding="utf-8") as out_file:
out_file.write(render)
Expand All @@ -275,7 +283,7 @@ def save_html(self, filename: Union[str, IO], mode: Union[str, SaveMode] = SaveM
include_js_files=[lib_file, data_file],
)
with open(filename, "w", encoding="utf-8") as out_file:
out_file.write(self._render(determine_template("inline"), template_params))
out_file.write(self._render(file_html_template, template_params))

@abc.abstractmethod
def as_dict(
Expand All @@ -296,7 +304,14 @@ def _get_json_content(
) -> dict:
"""Return all data for json representation"""
result = {"version": evidently.__version__}
result.update(self.as_dict(include_render=include_render, include=include, exclude=exclude, **kwargs))
result.update(
self.as_dict(
include_render=include_render,
include=include,
exclude=exclude,
**kwargs,
)
)
return result

def json(
Expand All @@ -307,7 +322,12 @@ def json(
**kwargs,
) -> str:
return json.dumps(
self._get_json_content(include_render=include_render, include=include, exclude=exclude, **kwargs),
self._get_json_content(
include_render=include_render,
include=include,
exclude=exclude,
**kwargs,
),
cls=NumpyEncoder,
allow_nan=True,
)
Expand Down
71 changes: 57 additions & 14 deletions src/evidently/ui/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
from evidently._pydantic_compat import PrivateAttr
from evidently._pydantic_compat import parse_obj_as
from evidently.model.dashboard import DashboardInfo
from evidently.renderers.notebook_utils import determine_template
from evidently.suite.base_suite import MetadataValueType
from evidently.suite.base_suite import ReportBase
from evidently.suite.base_suite import Snapshot
Expand Down Expand Up @@ -52,6 +51,7 @@
from evidently.ui.type_aliases import UserID
from evidently.utils import NumpyEncoder
from evidently.utils.dashboard import TemplateParams
from evidently.utils.dashboard import inline_iframe_html_template


class BlobMetadata(BaseModel):
Expand Down Expand Up @@ -237,12 +237,16 @@ def get_snapshot_metadata(self, id: SnapshotID) -> SnapshotMetadata:
return self.project_manager.get_snapshot_metadata(self._user_id, self.id, id)

def build_dashboard_info(
self, timestamp_start: Optional[datetime.datetime], timestamp_end: Optional[datetime.datetime]
self,
timestamp_start: Optional[datetime.datetime],
timestamp_end: Optional[datetime.datetime],
) -> DashboardInfo:
return self.dashboard.build(self.project_manager.data, self.id, timestamp_start, timestamp_end)

def show_dashboard(
self, timestamp_start: Optional[datetime.datetime] = None, timestamp_end: Optional[datetime.datetime] = None
self,
timestamp_start: Optional[datetime.datetime] = None,
timestamp_end: Optional[datetime.datetime] = None,
):
dashboard_info = self.build_dashboard_info(timestamp_start, timestamp_end)
template_params = TemplateParams(
Expand All @@ -254,7 +258,7 @@ def show_dashboard(
try:
from IPython.display import HTML

return HTML(determine_template("inline")(params=template_params))
return HTML(inline_iframe_html_template(params=template_params))
except ImportError as err:
raise Exception("Cannot import HTML from IPython.display, no way to show html") from err

Expand Down Expand Up @@ -286,7 +290,11 @@ def list_projects(self, project_ids: Optional[Set[ProjectID]]) -> List[Project]:

@abstractmethod
def add_snapshot(
self, project_id: ProjectID, snapshot: Snapshot, blob: "BlobMetadata", out_dataset_id: Optional[str] = None
self,
project_id: ProjectID,
snapshot: Snapshot,
blob: "BlobMetadata",
out_dataset_id: Optional[str] = None,
):
raise NotImplementedError

Expand All @@ -300,7 +308,10 @@ def search_project(self, project_name: str, project_ids: Optional[Set[ProjectID]

@abstractmethod
def list_snapshots(
self, project_id: ProjectID, include_reports: bool = True, include_test_suites: bool = True
self,
project_id: ProjectID,
include_reports: bool = True,
include_test_suites: bool = True,
) -> List[SnapshotMetadata]:
raise NotImplementedError

Expand Down Expand Up @@ -514,7 +525,10 @@ class AuthManager(ABC):
allow_default_user: bool = True

def refresh_default_roles(self):
for (default_role, entity_type), permissions in DEFAULT_ROLE_PERMISSIONS.items():
for (
default_role,
entity_type,
), permissions in DEFAULT_ROLE_PERMISSIONS.items():
role = self.get_default_role(default_role, entity_type)
if role.permissions != permissions:
role.permissions = permissions
Expand All @@ -532,7 +546,11 @@ def get_available_project_ids(

@abstractmethod
def check_entity_permission(
self, user_id: UserID, entity_type: EntityType, entity_id: EntityID, permission: Permission
self,
user_id: UserID,
entity_type: EntityType,
entity_id: EntityID,
permission: Permission,
) -> bool:
raise NotImplementedError

Expand Down Expand Up @@ -636,7 +654,12 @@ def _revoke_entity_role(self, entity_type: EntityType, entity_id: EntityID, user
raise NotImplementedError

def revoke_entity_role(
self, manager: UserID, entity_type: EntityType, entity_id: EntityID, user_id: UserID, role: Role
self,
manager: UserID,
entity_type: EntityType,
entity_id: EntityID,
user_id: UserID,
role: Role,
):
if not self.check_entity_permission(manager, entity_type, entity_id, Permission.REVOKE_ROLE):
raise NotEnoughPermissions()
Expand Down Expand Up @@ -692,7 +715,13 @@ def list_roles(self, entity_type: Optional[EntityType]) -> List[Role]:


class ProjectManager:
def __init__(self, metadata: MetadataStorage, blob: BlobStorage, data: DataStorage, auth: AuthManager):
def __init__(
self,
metadata: MetadataStorage,
blob: BlobStorage,
data: DataStorage,
auth: AuthManager,
):
self.metadata: MetadataStorage = metadata
self.blob: BlobStorage = blob
self.data: DataStorage = data
Expand All @@ -709,7 +738,10 @@ def create_project(

project = self.add_project(
Project(
name=name, description=description, dashboard=DashboardConfig(name=name, panels=[]), team_id=team_id
name=name,
description=description,
dashboard=DashboardConfig(name=name, panels=[]),
team_id=team_id,
),
user_id,
team_id,
Expand Down Expand Up @@ -782,14 +814,22 @@ def delete_snapshot(self, user_id: UserID, project_id: ProjectID, snapshot_id: S
self.metadata.delete_snapshot(project_id, snapshot_id)

def search_project(
self, user_id: UserID, project_name: str, team_id: Optional[TeamID], org_id: Optional[OrgID]
self,
user_id: UserID,
project_name: str,
team_id: Optional[TeamID],
org_id: Optional[OrgID],
) -> List[Project]:
user = self.auth.get_or_default_user(user_id)
project_ids = self.auth.get_available_project_ids(user.id, team_id, org_id)
return [p.bind(self, user.id) for p in self.metadata.search_project(project_name, project_ids)]

def list_snapshots(
self, user_id: UserID, project_id: ProjectID, include_reports: bool = True, include_test_suites: bool = True
self,
user_id: UserID,
project_id: ProjectID,
include_reports: bool = True,
include_test_suites: bool = True,
) -> List[SnapshotMetadata]:
if not self.auth.check_entity_permission(user_id, EntityType.Project, project_id, Permission.PROJECT_READ):
raise NotEnoughPermissions()
Expand All @@ -799,7 +839,10 @@ def list_snapshots(
return snapshots

def load_snapshot(
self, user_id: UserID, project_id: ProjectID, snapshot: Union[SnapshotID, SnapshotMetadata]
self,
user_id: UserID,
project_id: ProjectID,
snapshot: Union[SnapshotID, SnapshotMetadata],
) -> Snapshot:
if isinstance(snapshot, SnapshotID):
snapshot = self.get_snapshot_metadata(user_id, project_id, snapshot)
Expand Down
Loading

0 comments on commit bb8c809

Please sign in to comment.