-
Couldn't load subscription status.
- Fork 0
Refactor vuecore library with an initial example for scatter plot #11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 6 commits
Commits
Show all changes
20 commits
Select commit
Hold shift + click to select a range
fc43949
♻️ Add initial version of project refactoring, using scatter plot as …
sayalaruano 9b54fc8
♻️ Refactor code to support various engines and handle this logic wit…
sayalaruano 7d27bc8
🎨 Add enums for plot and engine types
sayalaruano dd49d7b
✅ Add tests for scatter plot functions
sayalaruano 4b5b43d
📝 Add docstrings and enums in the plotly/__init__.py file
sayalaruano 1ec04f2
🐛 Fix ruff errors during CI
sayalaruano d2adca7
Merge branch 'main' into refactor-scatter
sayalaruano 58e96db
📝 Add notebook to show scatter plot examples, and remove validation t…
sayalaruano 155c76e
🐛 Fix circular import bug, add try-except block to install chrmore to…
sayalaruano fffa849
➖ Remove unused dependency
sayalaruano 4486119
✏️ Add all expected report formats on the value-error message
sayalaruano 95bb54e
💚 Add readthedocs dependencies to download chrome, which is required …
sayalaruano f68a35a
✏️ Correct identation on apt dependencies for readthedocs.yaml
sayalaruano 03eab2d
📝 Add api_example/scatter into docs, update notebook, and create pyth…
sayalaruano c96d9a9
🐛 Fix indentation fro apt packages in readthedocs.yaml and imporitng …
sayalaruano 390551a
🐛 Fix import bug in scatter python script
sayalaruano 16d6827
🐛 Fix bug on scatter python script
sayalaruano 23e7252
📝 Update scatter notebook header
sayalaruano bd7e1ad
📝 Modify header of scatter notebook and add title to basic plot
sayalaruano 275db81
📝 Show df on the scatter notebook
sayalaruano File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,3 +3,6 @@ reference | |
| # builds | ||
| _build | ||
| jupyter_execute | ||
|
|
||
| # VsCode | ||
| *.DS_Store | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -37,6 +37,7 @@ dependencies = [ | |
| "webweb", | ||
| "acore", | ||
| "dash-cytoscape", | ||
| "pydantic", | ||
| ] | ||
|
|
||
| [project.optional-dependencies] | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| from enum import auto | ||
|
|
||
| try: | ||
| from enum import StrEnum | ||
| except ImportError: | ||
| from strenum import StrEnum | ||
|
|
||
|
|
||
| class PlotType(StrEnum): | ||
| SCATTER = auto() | ||
| LINE = auto() | ||
| # Add other plot types as needed | ||
|
|
||
|
|
||
| class EngineType(StrEnum): | ||
| PLOTLY = auto() | ||
| # Add other engines as needed |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,113 @@ | ||
| from typing import Callable | ||
| from vuecore import PlotType, EngineType | ||
|
|
||
| # Import the engine modules to trigger their registration | ||
| from . import plotly # noqa: F401, E402 | ||
|
|
||
| # from . import matplotlib # This is where you'd add a new engine | ||
|
|
||
| # Registries to hold the functions from each backend | ||
| PLOT_BUILDERS = {} | ||
| PLOT_SAVERS = {} | ||
|
|
||
|
|
||
| def register_builder(plot_type: PlotType, engine: EngineType, func: Callable): | ||
| """ | ||
| Registers a plot builder function for a given plot type and engine. | ||
|
|
||
| This allows dynamic dispatch of plotting functions depending on the desired | ||
| plot type (e.g., scatter, histogram) and backend engine (e.g., Plotly, Matplotlib). | ||
|
|
||
| Parameters | ||
| ---------- | ||
| plot_type : PlotType | ||
| The type of plot (e.g., SCATTER). | ||
| engine : EngineType | ||
| The rendering engine (e.g., PLOTLY). | ||
| func : Callable | ||
| The plotting function to register for this type and engine. | ||
|
|
||
| Returns | ||
| ------- | ||
| None | ||
| """ | ||
| if engine not in PLOT_BUILDERS: | ||
| PLOT_BUILDERS[engine] = {} | ||
| PLOT_BUILDERS[engine][plot_type] = func | ||
|
|
||
|
|
||
| def register_saver(engine: EngineType, func: Callable): | ||
| """ | ||
| Registers a save function for a given engine. | ||
|
|
||
| This allows saving plots using engine-specific logic (e.g., Plotly's `write_image`, | ||
| Matplotlib's `savefig`, etc.). | ||
|
|
||
| Parameters | ||
| ---------- | ||
| engine : EngineType | ||
| The rendering engine for which to register the saver function. | ||
| func : Callable | ||
| The saving function to use for this engine. | ||
|
|
||
| Returns | ||
| ------- | ||
| None | ||
| """ | ||
| PLOT_SAVERS[engine] = func | ||
|
|
||
|
|
||
| def get_builder(plot_type: PlotType, engine: EngineType) -> Callable: | ||
| """ | ||
| Retrieves a plot builder function from the registry. | ||
|
|
||
| Looks up the plotting function based on the specified plot type and engine. | ||
|
|
||
| Parameters | ||
| ---------- | ||
| plot_type : PlotType | ||
| The type of plot to retrieve. | ||
| engine : EngineType | ||
| The engine used to render the plot. | ||
|
|
||
| Returns | ||
| ------- | ||
| Callable | ||
| The registered plotting function. | ||
|
|
||
| Raises | ||
| ------ | ||
| ValueError | ||
| If no function is found for the given plot type and engine. | ||
| """ | ||
| try: | ||
| return PLOT_BUILDERS[engine][plot_type] | ||
| except KeyError: | ||
| raise ValueError(f"No '{plot_type}' builder found for engine '{engine}'") | ||
|
|
||
|
|
||
| def get_saver(engine: EngineType) -> Callable: | ||
| """ | ||
| Retrieves a save function from the registry. | ||
|
|
||
| Returns the function used to save plots for the specified engine. | ||
|
|
||
| Parameters | ||
| ---------- | ||
| engine : EngineType | ||
| The engine for which the saving function should be retrieved. | ||
|
|
||
| Returns | ||
| ------- | ||
| Callable | ||
| The registered saving function. | ||
|
|
||
| Raises | ||
| ------ | ||
| ValueError | ||
| If no saver function is registered for the given engine. | ||
| """ | ||
| try: | ||
| return PLOT_SAVERS[engine] | ||
| except KeyError: | ||
| raise ValueError(f"No saver found for engine '{engine}'") |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| from vuecore.engines import register_builder, register_saver | ||
| from vuecore import PlotType, EngineType | ||
|
|
||
| from .scatter import build as build_scatter | ||
| from .saver import save | ||
|
|
||
| # Register the functions with the central dispatcher | ||
| register_builder( | ||
| plot_type=PlotType.SCATTER, engine=EngineType.PLOTLY, func=build_scatter | ||
| ) | ||
| register_saver(engine=EngineType.PLOTLY, func=save) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| import plotly.graph_objects as go | ||
| from pathlib import Path | ||
|
|
||
|
|
||
| def save(fig: go.Figure, filepath: str) -> None: | ||
| """ | ||
| Saves a Plotly figure to a file, inferring the format from the extension. | ||
|
|
||
| This utility provides a single interface for exporting a figure to various | ||
| static and interactive formats. | ||
|
|
||
| Parameters | ||
| ---------- | ||
| fig : go.Figure | ||
| The Plotly figure object to save. | ||
| filepath : str | ||
| The destination path for the file (e.g., 'my_plot.png', 'figure.html'). | ||
| The format is determined by the file extension. | ||
|
|
||
| Returns | ||
| ------- | ||
| None | ||
|
|
||
| Raises | ||
| ------ | ||
| ValueError | ||
| If the file extension is not one of the supported formats. | ||
| ImportError | ||
| If required libraries for image export (e.g., kaleido) are not installed. | ||
|
|
||
| Examples | ||
| -------- | ||
| >>> import plotly.express as px | ||
| >>> fig = px.scatter(x=[1, 2, 3], y=[1, 2, 3]) | ||
| >>> # Save as an interactive HTML file | ||
| >>> save(fig, 'scatter.html') | ||
| Plot saved to scatter.html | ||
| >>> # Save as a static PNG image | ||
| >>> save(fig, 'scatter.png') | ||
| Plot saved to scatter.png | ||
| """ | ||
| path = Path(filepath) | ||
| suffix = path.suffix.lower() | ||
|
|
||
| if suffix in [".png", ".jpg", ".jpeg", ".webp", ".svg", ".pdf"]: | ||
| fig.write_image(filepath) | ||
| elif suffix == ".html": | ||
| fig.write_html(filepath, include_plotlyjs="cdn") | ||
| elif suffix == ".json": | ||
| fig.write_json(filepath) | ||
| else: | ||
| raise ValueError( | ||
| f"Unsupported file format: '{suffix}'. Supported formats: .png, .svg, .pdf, .html, .json" | ||
| ) | ||
|
|
||
| print(f"Plot saved to {filepath}") | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| import pandas as pd | ||
| import plotly.express as px | ||
| import plotly.graph_objects as go | ||
| from vuecore.schemas.distribution.scatter import ScatterConfig | ||
| from vuecore.utils.statistics import get_density | ||
| from .theming import apply_scatter_theme | ||
|
|
||
|
|
||
| def build(data: pd.DataFrame, config: ScatterConfig) -> go.Figure: | ||
| """ | ||
| Creates a Plotly scatter plot figure from a DataFrame and configuration. | ||
|
|
||
| This function acts as a bridge between the abstract plot definition and the | ||
| Plotly Express implementation. It translates the validated configuration | ||
| into the arguments for `plotly.express.scatter`. | ||
|
|
||
| Parameters | ||
| ---------- | ||
| data : pd.DataFrame | ||
| The DataFrame containing the plot data. | ||
| config : ScatterConfig | ||
| The validated Pydantic model object containing all plot configurations. | ||
|
|
||
| Returns | ||
| ------- | ||
| go.Figure | ||
| A `plotly.graph_objects.Figure` object representing the scatter plot. | ||
| """ | ||
| plot_args = { | ||
| "x": config.x, | ||
| "y": config.y, | ||
| "size": config.size, | ||
| "symbol": config.symbol, | ||
| "text": config.text, | ||
| "hover_data": config.hover_cols, | ||
| "trendline": config.trendline, | ||
| } | ||
|
|
||
| if config.color_by_density: | ||
| # Calculate density and pass it to the 'color' argument | ||
| density_values = get_density(data[config.x].values, data[config.y].values) | ||
| plot_args["color"] = density_values | ||
| else: | ||
| # Use standard group-based coloring | ||
| plot_args["color"] = config.group | ||
| plot_args["color_discrete_map"] = config.colors | ||
|
|
||
| fig = px.scatter(data, **plot_args) | ||
|
|
||
| # Apply theme | ||
| fig = apply_scatter_theme(fig, config) | ||
|
|
||
| return fig |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| import plotly.graph_objects as go | ||
| from vuecore.schemas.distribution.scatter import ScatterConfig | ||
|
|
||
|
|
||
| def apply_scatter_theme(fig: go.Figure, config: ScatterConfig) -> go.Figure: | ||
| """ | ||
| Applies a consistent layout and theme to a Plotly figure. | ||
|
|
||
| This function separates styling from plot creation, allowing for a consistent | ||
| look and feel across different plot types. It updates traces and layout | ||
| properties based on the provided configuration. | ||
|
|
||
| Parameters | ||
| ---------- | ||
| fig : go.Figure | ||
| The Plotly figure object to be styled. | ||
| config : ScatterConfig | ||
| The configuration object containing styling info like titles and dimensions. | ||
|
|
||
| Returns | ||
| ------- | ||
| go.Figure | ||
| The styled Plotly figure object. | ||
| """ | ||
| fig.update_traces( | ||
| marker=dict( | ||
| opacity=config.marker_opacity, | ||
| line=dict(width=config.marker_line_width, color=config.marker_line_color), | ||
| ), | ||
| selector=dict(mode="markers"), | ||
| ) | ||
|
|
||
| fig.update_layout( | ||
| title_text=config.title, | ||
| xaxis_title=config.x_title or config.x.title(), | ||
| yaxis_title=config.y_title or config.y.title(), | ||
| height=config.height, | ||
| width=config.width, | ||
| template="plotly_white", | ||
| legend=dict(orientation="h", yanchor="bottom", y=1.02, xanchor="right", x=1), | ||
| hovermode="closest", | ||
| ) | ||
| return fig |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.