From 94565901a3e01437a94b04ce906458d9f25fd99e Mon Sep 17 00:00:00 2001 From: Advait Gaur Date: Thu, 23 Jan 2025 01:12:26 +0530 Subject: [PATCH 1/3] Add consistent legend support across backends --- src/arviz_plots/backend/bokeh/legend.py | 10 +++++ src/arviz_plots/backend/plotly/legend.py | 47 +++++++++++++++++++++++- src/arviz_plots/plots/psensedistplot.py | 6 +++ 3 files changed, 61 insertions(+), 2 deletions(-) diff --git a/src/arviz_plots/backend/bokeh/legend.py b/src/arviz_plots/backend/bokeh/legend.py index 4248c6a3..68126b8b 100644 --- a/src/arviz_plots/backend/bokeh/legend.py +++ b/src/arviz_plots/backend/bokeh/legend.py @@ -61,6 +61,16 @@ def legend( for kws in kwarg_list: glyph = artist_fun(**{**artist_kwargs, **kws}) glyph_list.append(glyph) + + # Add automatic legend placement logic + if side == "auto": + # Place legend outside if there's enough space, inside otherwise + plot_width = target_plot.width + if plot_width >= 600: # arbitrary threshold + side = "right" + else: + side = "center" + leg = Legend( items=[(str(label), [glyph]) for label, glyph in zip(label_list, glyph_list)], title=title, diff --git a/src/arviz_plots/backend/plotly/legend.py b/src/arviz_plots/backend/plotly/legend.py index 52a57fe5..a33a1a88 100644 --- a/src/arviz_plots/backend/plotly/legend.py +++ b/src/arviz_plots/backend/plotly/legend.py @@ -1,8 +1,51 @@ """Plotly legend generation.""" +def dealiase_line_kwargs(kwargs): + """Convert arviz common interface properties to plotly ones.""" + prop_map = {"width": "width", "linestyle": "dash"} + return {prop_map.get(key, key): value for key, value in kwargs.items()} def legend( target, kwarg_list, label_list, title=None, artist_type="line", artist_kwargs=None, **kwargs ): - """Generate a legend with plotly.""" - raise NotImplementedError("Still in progress") + """Generate a legend with plotly. + + Parameters + ---------- + target : plotly.graph_objects.Figure + The figure to add the legend to + label_list : list + List of labels for each legend entry + artist_kwargs : dict, optional + Additional kwargs passed to all artists + **kwargs : dict + Additional kwargs passed to legend configuration + """ + if artist_kwargs is None: + artist_kwargs = {} + + if artist_type == "line": + artist_fun = target.add_scatter + kwarg_list = [dealiase_line_kwargs(kws) for kws in kwarg_list] + mode = "lines" + else: + raise NotImplementedError("Only line type legends supported for now") + + # Add invisible traces that will only show in legend + for kws, label in zip(kwarg_list, label_list): + artist_fun( + x=[None], + y=[None], + name=str(label), + mode=mode, + line=kws, + showlegend=True, + **artist_kwargs + ) + + # Configure legend + target.update_layout( + showlegend=True, + legend_title_text=title, + **kwargs + ) diff --git a/src/arviz_plots/plots/psensedistplot.py b/src/arviz_plots/plots/psensedistplot.py index b3680bdf..fa8872da 100644 --- a/src/arviz_plots/plots/psensedistplot.py +++ b/src/arviz_plots/plots/psensedistplot.py @@ -249,4 +249,10 @@ def plot_psense_dist( stats_kwargs=stats_kwargs, ) + # Add legend for alpha parameter automatically + plot_collection.add_legend( + "alpha", + title="Power Scale Factor", + ) + return plot_collection From a220891856ebf8f7a37a898d5d77c883e067fa7d Mon Sep 17 00:00:00 2001 From: Advait Gaur Date: Thu, 23 Jan 2025 03:18:57 +0530 Subject: [PATCH 2/3] Update Read the Docs configuration to specify Sphinx configuration file --- .readthedocs.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 9b3d4141..8a43023d 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -8,7 +8,7 @@ build: python: "3.12" sphinx: - fail_on_warning: true + configuration: docs/source/conf.py python: install: From 7c173a4684dcd7b96636b6ae2bc40988e1565507 Mon Sep 17 00:00:00 2001 From: Advait Gaur Date: Fri, 24 Jan 2025 17:31:05 +0530 Subject: [PATCH 3/3] Legend placement logic and update doc string for Plotly backends --- src/arviz_plots/backend/bokeh/legend.py | 7 +++---- src/arviz_plots/backend/plotly/legend.py | 15 ++++++++++++--- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/arviz_plots/backend/bokeh/legend.py b/src/arviz_plots/backend/bokeh/legend.py index 68126b8b..0a0de9e3 100644 --- a/src/arviz_plots/backend/bokeh/legend.py +++ b/src/arviz_plots/backend/bokeh/legend.py @@ -19,7 +19,8 @@ def legend( artist_type="line", artist_kwargs=None, legend_target=None, - side="right", + side="auto", + legend_placement_threshold=600, #Magic number **kwargs, ): """Generate a legend on a figure given lists of labels and property kwargs. @@ -62,11 +63,9 @@ def legend( glyph = artist_fun(**{**artist_kwargs, **kws}) glyph_list.append(glyph) - # Add automatic legend placement logic if side == "auto": - # Place legend outside if there's enough space, inside otherwise plot_width = target_plot.width - if plot_width >= 600: # arbitrary threshold + if plot_width >= legend_placement_threshold: side = "right" else: side = "center" diff --git a/src/arviz_plots/backend/plotly/legend.py b/src/arviz_plots/backend/plotly/legend.py index a33a1a88..8b6ef098 100644 --- a/src/arviz_plots/backend/plotly/legend.py +++ b/src/arviz_plots/backend/plotly/legend.py @@ -2,7 +2,7 @@ def dealiase_line_kwargs(kwargs): """Convert arviz common interface properties to plotly ones.""" - prop_map = {"width": "width", "linestyle": "dash"} + prop_map = {"linewidth": "width", "linestyle": "dash"} return {prop_map.get(key, key): value for key, value in kwargs.items()} def legend( @@ -14,12 +14,23 @@ def legend( ---------- target : plotly.graph_objects.Figure The figure to add the legend to + kwarg_list : list + List of style dictionaries for each legend entry label_list : list List of labels for each legend entry + title : str, optional + Title of the legend + artist_type : str, optional + Type of artist to use for legend entries. Currently only "line" is supported. artist_kwargs : dict, optional Additional kwargs passed to all artists **kwargs : dict Additional kwargs passed to legend configuration + + Returns + ------- + None + The legend is added to the target figure inplace """ if artist_kwargs is None: artist_kwargs = {} @@ -31,7 +42,6 @@ def legend( else: raise NotImplementedError("Only line type legends supported for now") - # Add invisible traces that will only show in legend for kws, label in zip(kwarg_list, label_list): artist_fun( x=[None], @@ -43,7 +53,6 @@ def legend( **artist_kwargs ) - # Configure legend target.update_layout( showlegend=True, legend_title_text=title,