arviz-devs / arviz-plots

ArviZ modular plotting
https://arviz-plots.readthedocs.io
Apache License 2.0
2 stars 1 forks source link

Tooltip and grouping information? #68

Open OriolAbril opened 1 month ago

OriolAbril commented 1 month ago

We might want to provide tooltip and grouping information somehow as part of the common plotting interface. Even if some backends can't include that into the plot, it would be a great win for those that can.

OriolAbril commented 1 month ago

Here is an example of getting an interactive legend working with plot_dist. As we can pass arbitrary elements as aesthetics and as plot_kwargs everything is feasible already, but we might want to set that behaviour as the default (maybe only when there are multiple models for example, with docs on doing that also for plot_dist with chains as different colors...).

Note: to make that a default the legendgroup argument should become part of the common interface (with this or another name) and be ignored for backends where it makes no sense.

Interactive legend in plot_dist

Code to reproduce At the time of writing, this requires the plotly_poc branch ```python import numpy as np import arviz_plots as azp from arviz_base import load_arviz_data import plotly.io as pio pio.renderers.default = "browser" c = load_arviz_data("centered_eight") n = load_arviz_data("non_centered_eight") pc = azp.plot_dist( {"centered": c, "non_centered": n}, backend="plotly", pc_kwargs={"aes": {"legendgroup": ["model"]}, "legendgroup": ["centered", "non_centered"]}, aes_map={ "credible_interval": {"color", "y", "legendgroup"}, "point_estimate": {"color", "y", "legendgroup"}, }, plot_kwargs={ "kde": {"showlegend": False}, "credible_interval": {"showlegend": False}, "point_estimate": {"showlegend": False}, "point_estimate_text": {"showlegend": False}, } ) # generate interactive legend colors = pc.aes["mu"]["color"].values plot = pc.viz["chart"].item() obj_centered = pc.viz["mu"]["kde"].sel(model="centered").item() obj_non_centered = pc.viz["mu"]["kde"].sel(model="non_centered").item() plot.update_traces( selector=lambda trace: (trace.y.shape == obj_centered.y.shape) and np.allclose(trace.y, obj_centered.y), name="centered", legendgroup="centered", showlegend=True, ) plot.update_traces( selector=lambda trace: (trace.y.shape == obj_non_centered.y.shape) and np.allclose(trace.y, obj_non_centered.y), name="non centered", legendgroup="non_centered", showlegend=True, ) # ------ pc.show() ```

or with plot_forest:

Screencast de 9-7-24 22:30:39.webm

Code to reproduce At the time of writing, this requires the plotly_poc branch ```python import numpy as np import arviz_plots as azp from arviz_base import load_arviz_data import plotly.io as pio pio.renderers.default = "browser" c = load_arviz_data("centered_eight") n = load_arviz_data("non_centered_eight") pc = azp.plot_forest( {"centered": c, "non_centered": n}, backend="plotly", pc_kwargs={"aes": {"legendgroup": ["model"]}, "legendgroup": ["centered", "non_centered"]}, plot_kwargs={ "trunk": {"showlegend": False}, "twig": {"showlegend": False}, "point_estimate": {"showlegend": False}, "labels": {"showlegend": False}, } ) # generate interactive legend colors = pc.aes["mu"]["color"].values plot = pc.viz["plot"].sel(column="forest").item() obj_centered = pc.viz["mu"]["point_estimate"].sel(chain=0, model="centered").item() obj_non_centered = pc.viz["mu"]["point_estimate"].sel(chain=0, model="non_centered").item() plot.update_traces( selector=lambda trace: np.allclose(trace.y, obj_centered.y) & np.allclose(trace.x, obj_centered.x), name="centered", mode="lines+markers", legendgroup="centered", showlegend=True, line={"color": colors[0]} ) plot.update_traces( selector=lambda trace: np.allclose(trace.y, obj_non_centered.y) & np.allclose(trace.x, obj_non_centered.x), name="non centered", mode="lines+markers", legendgroup="non_centered", showlegend=True, line={"color": colors[1]} ) # ------ pc.show() ```
aloctavodia commented 1 month ago

At least some of this functionality is supported by matplotlib. See here https://matplotlib.org/stable/gallery/event_handling/legend_picking.html

Do we want to support interactivity for matplotlib too?