Skip to content

Commit

Permalink
Plotly engine refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
alexmorev committed Jan 19, 2025
1 parent 4d9e304 commit 34893ca
Show file tree
Hide file tree
Showing 6 changed files with 150 additions and 137 deletions.
18 changes: 18 additions & 0 deletions ckanext/charts/chart_builders/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ def decode_filter_params(self) -> dict[str, list[str]]:


class BaseChartBuilder(ABC):
DEFAULT_DATETIME_FORMAT = "ISO8601"

def __init__(
self,
dataframe: pd.DataFrame,
Expand Down Expand Up @@ -172,6 +174,22 @@ def get_unique_values(self, column: pd.Series, sort: bool = True) -> list[Any]:

return sorted(result)

def _is_column_datetime(self, column_name: str) -> bool:
"""Check if string values of the certain column are convertible
to datetime type.
Args:
column (str): name of the column to check
Returns:
True if values can be converted to datetime type, otherwise - False
"""
try:
pd.to_datetime(self.df[column_name], format=self.DEFAULT_DATETIME_FORMAT)
except ValueError:
return False
return True


class BaseChartForm(ABC):
name = ""
Expand Down
16 changes: 0 additions & 16 deletions ckanext/charts/chart_builders/observable.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,22 +27,6 @@ def get_supported_forms(cls) -> list[type[Any]]:
ObservableScatterForm,
]

def _is_column_datetime(self, column: str) -> bool:
"""Check if string values of the certain column are convertable
to datetime type.
Args:
column (str): name of the column to check
Returns:
True if values can be converted to datetime type, otherwise - False
"""
try:
pd.to_datetime(self.df[column], format=self.DEFAULT_DATETIME_FORMAT)
except ValueError:
return False
return True

def _set_chart_global_settings(
self, data: dict[str, Any]) -> dict[str, Any]:
"""Set chart's global settings and plot configs.
Expand Down
34 changes: 12 additions & 22 deletions ckanext/charts/chart_builders/plotly/bar.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ def build_bar_chart(self) -> Any:
if self.settings.get("skip_null_values"):
self.df = self.df[self.df[self.settings["y"]].notna()]

# Create an instance of the scatter graph
fig = px.bar(
data_frame=self.df,
x=self.settings["x"],
Expand All @@ -26,23 +27,14 @@ def build_bar_chart(self) -> Any:
color=self.settings.get("color"),
)

# Prepare global chart settings
self._set_chart_global_settings(fig)

# Prepare additional chart settings
fig.update_xaxes(
type="category",
)

if chart_title := self.settings.get("chart_title"):
fig.update_layout(title_text=chart_title)

if x_axis_label := self.settings.get("x_axis_label"):
fig.update_xaxes(title_text=x_axis_label)
else:
fig.update_xaxes(title_text=self.settings["x"])

if y_axis_label := self.settings.get("y_axis_label"):
fig.update_yaxes(title_text=y_axis_label)
else:
fig.update_yaxes(title_text=self.settings["y"][0])

return fig.to_json()


Expand Down Expand Up @@ -91,6 +83,7 @@ def build_horizontal_bar_chart(self) -> Any:
if self.settings.get("skip_null_values"):
self.df = self.df[self.df[self.settings["y"]].notna()]

# Create an instance of the scatter graph
fig = px.bar(
data_frame=self.df,
x=self.settings["y"],
Expand All @@ -103,21 +96,18 @@ def build_horizontal_bar_chart(self) -> Any:
orientation="h",
)

# Prepare global chart settings
self._set_chart_global_settings(fig)

# Prepare additional chart settings
fig.update_yaxes(
type="category",
)

if chart_title := self.settings.get("chart_title"):
fig.update_layout(title_text=chart_title)

if x_axis_label := self.settings.get("x_axis_label"):
fig.update_xaxes(title_text=x_axis_label)
else:
if not self.settings.get("x_axis_label"):
fig.update_xaxes(title_text=self.settings["y"])

if y_axis_label := self.settings.get("y_axis_label"):
fig.update_yaxes(title_text=y_axis_label)
else:
if not self.settings.get("y_axis_label"):
fig.update_yaxes(title_text=self.settings["x"])

return fig.to_json()
Expand Down
37 changes: 37 additions & 0 deletions ckanext/charts/chart_builders/plotly/base.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from __future__ import annotations

from plotly.graph_objects import Figure
from typing import Any

from ckanext.charts.chart_builders.base import BaseChartBuilder, BaseChartForm
Expand All @@ -12,6 +13,9 @@ class PlotlyBuilder(BaseChartBuilder):
"""

DEFAULT_NAN_FILL_VALUE = 0
YEAR_DATETIME_FORMAT = "%Y"
DATETIME_TICKS_FORMAT = "%m-%d %H:%M"
ISO_DATETIME_FORMAT = "%Y-%m-%dT%H:%M:%S"

@classmethod
def get_supported_forms(cls) -> list[type[Any]]:
Expand All @@ -33,6 +37,39 @@ def get_supported_forms(cls) -> list[type[Any]]:
PlotlyChoroplethForm,
]

def _set_chart_global_settings(
self, fig: Figure) -> None:
"""Set chart's global settings and plot configs.
Args:
fig: plotly graph object Figure
Returns:
Updated plotly graph object
"""
if chart_title := self.settings.get("chart_title"):
fig.update_layout(title_text=chart_title)

if x_axis_label := self.settings.get("x_axis_label"):
fig.update_xaxes(title_text=x_axis_label)
elif isinstance(self.settings["x"], list):
fig.update_yaxes(title_text=self.settings["x"][0])
else:
fig.update_xaxes(title_text=self.settings["x"])

if y_axis_label := self.settings.get("y_axis_label"):
fig.update_yaxes(title_text=y_axis_label)
elif isinstance(self.settings["y"], list):
fig.update_yaxes(title_text=self.settings["y"][0])
else:
fig.update_yaxes(title_text=self.settings["y"])

if self.settings.get("invert_x", False):
fig.update_xaxes(autorange="reversed")

if self.settings.get("invert_y", False):
fig.update_yaxes(autorange="reversed")


class BasePlotlyForm(BaseChartForm):
pass
Loading

0 comments on commit 34893ca

Please sign in to comment.