Skip to content
3 changes: 3 additions & 0 deletions src/vuecore/engines/plotly/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
from .box import build as build_box
from .saver import save

# Import build_utils to ensure it's available
from . import plot_builder # noqa: F401

# Register the functions with the central dispatcher
register_builder(
plot_type=PlotType.SCATTER, engine=EngineType.PLOTLY, func=build_scatter
Expand Down
59 changes: 25 additions & 34 deletions src/vuecore/engines/plotly/bar.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,24 @@

from vuecore.schemas.basic.bar import BarConfig
from .theming import apply_bar_theme
from .plot_builder import build_plot

# Define parameters handled by the theme script
THEMING_PARAMS = [
"opacity",
"barmode",
"log_x",
"log_y",
"range_x",
"range_y",
"title",
"x_title",
"y_title",
"subtitle",
"template",
"width",
"height",
]


def build(data: pd.DataFrame, config: BarConfig) -> go.Figure:
Expand All @@ -31,37 +49,10 @@ def build(data: pd.DataFrame, config: BarConfig) -> go.Figure:
go.Figure
A `plotly.graph_objects.Figure` object representing the bar plot.
"""
# Get all parameters from the config model, including extras
all_config_params = config.model_dump()

# Define parameters handled by the theme script
theming_params = [
"opacity",
"barmode",
"log_x",
"log_y",
"range_x",
"range_y",
"title",
"x_title",
"y_title",
"subtitle",
"template",
"width",
"height",
]

# Create the dictionary of arguments for px.bar
plot_args = {
k: v
for k, v in all_config_params.items()
if k not in theming_params and v is not None
}

# Create the base figure using only the arguments relevant to px.bar
fig = px.bar(data, **plot_args)

# Apply theme and additional styling to the generated figure.
fig = apply_bar_theme(fig, config)

return fig
return build_plot(
data=data,
config=config,
px_function=px.bar,
theming_function=apply_bar_theme,
theming_params=THEMING_PARAMS,
)
61 changes: 26 additions & 35 deletions src/vuecore/engines/plotly/box.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,25 @@

from vuecore.schemas.basic.box import BoxConfig
from .theming import apply_box_theme
from .plot_builder import build_plot

# Define parameters handled by the theme script
THEMING_PARAMS = [
"boxmode",
"log_x",
"log_y",
"range_x",
"range_y",
"notched",
"points",
"title",
"x_title",
"y_title",
"subtitle",
"template",
"width",
"height",
]


def build(data: pd.DataFrame, config: BoxConfig) -> go.Figure:
Expand All @@ -31,38 +50,10 @@ def build(data: pd.DataFrame, config: BoxConfig) -> go.Figure:
go.Figure
A `plotly.graph_objects.Figure` object representing the box plot.
"""
# Get all parameters from the config model, including extras
all_config_params = config.model_dump()

# Define parameters handled by the theme script
theming_params = [
"boxmode",
"log_x",
"log_y",
"range_x",
"range_y",
"notched",
"points",
"title",
"x_title",
"y_title",
"subtitle",
"template",
"width",
"height",
]

# Create the dictionary of arguments for px.box
plot_args = {
k: v
for k, v in all_config_params.items()
if k not in theming_params and v is not None
}

# Create the base figure using only the arguments relevant to px.box
fig = px.box(data, **plot_args)

# Apply theme and additional styling to the generated figure.
fig = apply_box_theme(fig, config)

return fig
return build_plot(
data=data,
config=config,
px_function=px.box,
theming_function=apply_box_theme,
theming_params=THEMING_PARAMS,
)
59 changes: 25 additions & 34 deletions src/vuecore/engines/plotly/line.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,24 @@

from vuecore.schemas.basic.line import LineConfig
from .theming import apply_line_theme
from .plot_builder import build_plot

# Define parameters handled by the theme script
THEMING_PARAMS = [
"markers",
"log_x",
"log_y",
"range_x",
"range_y",
"line_shape",
"title",
"x_title",
"y_title",
"subtitle",
"template",
"width",
"height",
]


def build(data: pd.DataFrame, config: LineConfig) -> go.Figure:
Expand All @@ -31,37 +49,10 @@ def build(data: pd.DataFrame, config: LineConfig) -> go.Figure:
go.Figure
A `plotly.graph_objects.Figure` object representing the line plot.
"""
# Get all parameters from the config model, including extras
all_config_params = config.model_dump()

# Define parameters handled by the theme script
theming_params = [
"markers",
"log_x",
"log_y",
"range_x",
"range_y",
"line_shape",
"title",
"x_title",
"y_title",
"subtitle",
"template",
"width",
"height",
]

# Create the dictionary of arguments for px.line
plot_args = {
k: v
for k, v in all_config_params.items()
if k not in theming_params and v is not None
}

# Create the base figure using only the arguments for px.line
fig = px.line(data, **plot_args)

# Apply theme and additional styling
fig = apply_line_theme(fig, config)

return fig
return build_plot(
data=data,
config=config,
px_function=px.line,
theming_function=apply_line_theme,
theming_params=THEMING_PARAMS,
)
65 changes: 65 additions & 0 deletions src/vuecore/engines/plotly/plot_builder.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# vuecore/engines/plotly/plot_builder.py
from typing import Any, Optional, List, Callable
import pandas as pd
import plotly.graph_objects as go


def build_plot(
data: pd.DataFrame,
config: Any,
px_function: Callable,
theming_function: Callable,
theming_params: List[str],
preprocess: Optional[Callable] = None,
) -> go.Figure:
"""
Base function to build Plotly figures with common patterns.

The function follows these steps:
1. Get all parameters from the config model
2. Create the dictionary of arguments for the plot function
3. Apply preprocessing
4. Create the base figure
5. Apply theme and additional styling

Parameters
----------
data : pd.DataFrame
The DataFrame containing the plot data.
config : Any
The Pydantic model with all plot configurations.
px_function : Callable
The Plotly Express function to use (e.g., px.bar, px.scatter, etc).
theming_function : Callable
The theming function to apply to the figure.
theming_params : List[str]
List of parameter names handled by the theming function.
preprocess : Callable, Optional
Optional preprocessing function for special features.

Returns
-------
go.Figure
A styled Plotly figure object.
"""
# Get all parameters from the config model
all_config_params = config.model_dump()

# Create the dictionary of arguments for the plot function
plot_args = {
k: v
for k, v in all_config_params.items()
if k not in theming_params and v is not None
}

# Apply preprocessing if provided
if preprocess and callable(preprocess):
data, plot_args = preprocess(data, plot_args, config)

# Create the base figure
fig = px_function(data, **plot_args)

# Apply theme and additional styling
fig = theming_function(fig, config)

return fig
Loading