Skip to content

Commit

Permalink
fix: redesigned shiny_renderer using htmltools and expanded on sample…
Browse files Browse the repository at this point in the history
… py-shiny/maidr plot
  • Loading branch information
krishnanand5 committed Aug 14, 2024
1 parent fcc3bae commit a47f6b1
Show file tree
Hide file tree
Showing 6 changed files with 503 additions and 10 deletions.
57 changes: 57 additions & 0 deletions example/py-shiny/example_pyshiny_reactive_scatter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
from maidr.custom_renderers.shiny_renderer import render_maidr
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns
from shiny import App, reactive, render, ui

# Load the dataset
iris = sns.load_dataset("iris")

# Define the UI components for the Shiny application
app_ui = ui.page_fluid(
ui.row(
ui.column(
3,
ui.input_select(
"x_var",
"Select X variable:",
choices=iris.select_dtypes(include=["float64"]).columns.tolist(),
selected="sepal_length",
),
ui.input_select(
"y_var",
"Select Y variable:",
choices=iris.select_dtypes(include=["float64"]).columns.tolist(),
selected="sepal_width",
),
),
ui.column(9, ui.output_ui("reactivebarplot")),
)
)


# Define the server
def server(input, output, session):
@reactive.Calc
def create_reactivebarplot():
fig, ax = plt.subplots(figsize=(10, 6))
s_plot = sns.scatterplot(
data=iris, x=input.x_var(), y=input.y_var(), hue="species", ax=ax
)
ax.set_title(f"Iris {input.y_var()} vs {input.x_var()}")
ax.set_xlabel(input.x_var().replace("_", " ").title())
ax.set_ylabel(input.y_var().replace("_", " ").title())
return s_plot

@output
@render.ui
def reactivebarplot():
return render_maidr(create_reactivebarplot)(width="100%", height="700px")


# Create the app
app = App(app_ui, server)

# Run the app
if __name__ == "__main__":
app.run()
3 changes: 2 additions & 1 deletion maidr/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,11 @@
lineplot,
scatterplot,
)
from .maidr import close, save_html, show, stacked
from .maidr import close, render, save_html, show, stacked

__all__ = [
"close",
"render",
"save_html",
"show",
"stacked",
Expand Down
58 changes: 58 additions & 0 deletions maidr/custom_renderers/shiny_renderer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
from matplotlib.axes import Axes
from matplotlib.figure import Figure
import maidr
from shiny import ui
from htmltools import tags
from typing import Any, Optional


def render_maidr(func):
"""
Render the MAIDR plot for a given plot object obtained from Shiny.
Parameters
----------
func: Callable Object
The Shiny function which returns an object that can be rendered for displaying the maidr plot.
"""

def wrapper(
*args, width: Optional[str] = None, height: Optional[str] = None, **kwargs
):
"""
Create an iframe HTML object containing the rendered MAIDR that can be injected into the Shiny widget component.
Parameters
----------
*args: Any
This allows the wrapper to accept any number of positional arguments.
width: Optional[str], default="None"
An optional string parameter for specifying the width of the iframe. It defaults to None if not provided.
height: Optional[str], default="None"
An optional string parameter for specifying the height of the iframe. It defaults to None if not provided.
**kwargs: Any
This allows the wrapper to accept any number of keyword arguments.
"""
try:
plot_obj = func(*args, **kwargs)
rendered_dict = maidr.render(plot_obj)

html_content = rendered_dict.get("html", "")

# Create a style string to append to the iframe
style_parts = []
if width:
style_parts.append(f"width: {width}")
if height:
style_parts.append(f"height: {height}")
style_string = "; ".join(style_parts)

# Create an iframe with the HTML payload in srcdoc attribute and styles as received
iframe = ui.tags.iframe(srcdoc=html_content, style=style_string)

return iframe

except Exception as e:
return ui.p(f"Error rendering plot: {str(e)}")

return wrapper
9 changes: 9 additions & 0 deletions maidr/maidr.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from typing import Literal, Any

from htmltools import RenderedHTML
from matplotlib.axes import Axes
from matplotlib.container import BarContainer

Expand All @@ -10,6 +11,14 @@
from maidr.core.figure_manager import FigureManager


def render(
plot: Any, *, lib_prefix: str | None = "lib", include_version: bool = True
) -> RenderedHTML:
ax = FigureManager.get_axes(plot)
maidr = FigureManager.get_maidr(ax.get_figure())
return maidr.render(lib_prefix=lib_prefix, include_version=include_version)


def show(plot: Any, renderer: Literal["auto", "ipython", "browser"] = "auto") -> object:
ax = FigureManager.get_axes(plot)
maidr = FigureManager.get_maidr(ax.get_figure())
Expand Down
Loading

0 comments on commit a47f6b1

Please sign in to comment.