From b1bbdf1ff014134dd98e170ff7881020d837e057 Mon Sep 17 00:00:00 2001 From: Ian Hunt-Isaak Date: Fri, 14 Apr 2023 11:15:45 -0400 Subject: [PATCH] Docstrings (#272) * Use kwarg forwarding to remove unncessary args * style: cleanup hyperslicer * style: document all remaining parameters * style: style fixes * fix: correct imshow args in hyperslicer --- docs/conf.py | 2 +- mpl_interactions/generic.py | 68 +++++++++++--------------------- mpl_interactions/mpl_kwargs.py | 6 ++- mpl_interactions/pyplot.py | 72 ++++++++++++---------------------- 4 files changed, 54 insertions(+), 94 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index ed0f0b7..27890cb 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -254,4 +254,4 @@ def linkcode_resolve(domain, info): fn = os.path.relpath(fn, start=os.path.dirname(mpl_inter.__file__)) - return f"https://github.com/mpl-extensions/mpl-interactions/blob/main/mpl_interactions/{fn}{linespec}" + return f"https://github.com/mpl-extensions/mpl-interactions/blob/main/mpl_interactions/{fn}{linespec}" # noqa: E501 diff --git a/mpl_interactions/generic.py b/mpl_interactions/generic.py index 6b8bace..14a84df 100644 --- a/mpl_interactions/generic.py +++ b/mpl_interactions/generic.py @@ -18,6 +18,7 @@ gogogo_figure, notebook_backend, ) +from .mpl_kwargs import imshow_kwargs_list, kwarg_popper from .utils import figure, nearest_idx from .xarray_helpers import get_hs_axes, get_hs_extent, get_hs_fmts @@ -567,21 +568,11 @@ def _ipython_display_(self): def hyperslicer( arr, - cmap=None, - norm=None, - aspect=None, - interpolation=None, alpha=None, vmin=None, vmax=None, vmin_vmax=None, - origin=None, - extent=None, autoscale_cmap=True, - filternorm=True, - filterrad=4.0, - resample=None, - url=None, ax=None, slider_formats=None, title=None, @@ -602,24 +593,22 @@ def hyperslicer( arr : arraylike or xarray Hyperstack of images. The last 2 or 3 dimensions will be treated as individiual images. If an xarray.DataArray then the dimensions will be automatically inferred. - cmap : str or `~matplotlib.colors.Colormap` - The Colormap instance or registered colormap name used to map - scalar data to colors. This parameter is ignored for RGB(A) data. - forwarded to matplotlib - norm : `~matplotlib.colors.Normalize`, optional - The `~matplotlib.colors.Normalize` instance used to scale scalar data to the [0, 1] - range before mapping to colors using *cmap*. By default, a linear - scaling mapping the lowest value to 0 and the highest to 1 is used. - This parameter is ignored for RGB(A) data. - forwarded to matplotlib + alpha : float, Callable or widget shorthand, indexed controls, optional + The alpha of the image. If a callable then it will receive parameters be autoupdated. + Can also be given a widget shorthand to automatically generate a slider + (e.g. `alpha = (0, 1, 10)`). + vmin, vmax : float, callable, shorthand for slider or indexed controls, optional + The vmin, vmax values for the colormap. Can accept a float for a fixed value, + or any slider shorthand to control with a slider, or an indexed controls + object to use an existing slider, or an arbitrary function of the other + parameters. + vmin_vmax : tuple of float + Used to generate a range slider for vmin and vmax. Should be given in range slider + notation: `("r", 0, 1)`. autoscale_cmap : bool If True rescale the colormap for every function update. Will not update if vmin and vmax are provided or if the returned image is RGB(A) like. forwarded to matplotlib - aspect : {'equal', 'auto'} or float - forwarded to matplotlib - interpolation : str - forwarded to matplotlib ax : matplotlib axis, optional if None a new figure and axis will be created slider_formats : None, string, or dict @@ -636,13 +625,11 @@ def hyperslicer( Whether to attach an ipywidgets.Play widget to any sliders that get created. If a boolean it will apply to all kwargs, if a dictionary you choose which sliders you want to attach play buttons too. - - None: no sliders - True: sliders on the lft - False: no sliders - 'left': sliders on the left - 'right': sliders on the right - is_color_image : boolean If True, will treat the last 3 dimensions as comprising a color images and will only set up sliders for the first arr.ndim - 3 dimensions. @@ -651,6 +638,10 @@ def hyperslicer( controls display_controls : boolean Whether the controls should display on creation. Ignored if controls is specified. + **kwargs : + `names` can be used to set the axes names, `axes` can be used to set the displayed values + of multiple sliders, and `axis0`, `axis1` etc can be used with widget shorthand to set the + displayed values of the sliders. All valid imshow kwargs are passed through to `imshow`. Returns ------- @@ -675,9 +666,10 @@ def hyperslicer( else: im_dims = 2 - ipympl = notebook_backend() + ipympl = notebook_backend() or force_ipywidgets fig, ax = gogogo_figure(ipympl, ax) slider_format_strings = create_slider_format_dict(slider_formats) + kwargs, imshow_kwargs = kwarg_popper(kwargs, imshow_kwargs_list) name_to_dim = {} slices = [0 for i in range(arr.ndim - im_dims)] @@ -696,13 +688,7 @@ def hyperslicer( # Just pass in an array - no kwargs for i in range(arr.ndim - im_dims): - start, stop = None, None name = f"axis{i}" - if name in kwargs: - if len(kwargs[name]) == 2: - start, stop = kwargs.pop(name) - else: - kwargs.pop(name) if axes is not None and axes[i] is not None: # now we assume the axes[i] has one of the following forms @@ -748,13 +734,12 @@ def hyperslicer( slider_format_strings[name] = "{:.0f}" kwargs[name] = np.arange(arr.shape[i]) + extent = kwargs.get("extent", None) + origin = kwargs.get("origin", "upper") if arr_type == "xarray": slider_format_strings = get_hs_fmts(arr, is_color_image=is_color_image) if extent is None: extent = get_hs_extent(arr, is_color_image=is_color_image, origin=origin) - else: - if "extent" not in kwargs: - extent = None extra_ctrls = [] funcs, extra_ctrls, param_excluder = prep_scalars(kwargs, vmin=vmin, vmax=vmax, alpha=alpha) @@ -816,19 +801,10 @@ def update(params, indices, cache): new_data = arr[tuple(0 for i in range(arr.ndim - im_dims))] im = ax.imshow( new_data, - cmap=cmap, - norm=norm, - aspect=aspect, - interpolation=interpolation, alpha=alpha, vmin=callable_else_value_no_cast(vmin, params), vmax=callable_else_value_no_cast(vmax, params), - origin=origin, - extent=extent, - filternorm=filternorm, - filterrad=filterrad, - resample=resample, - url=url, + **imshow_kwargs, ) # this is necessary to make calls to plt.colorbar behave as expected # i know it's bad news to use private methods :( diff --git a/mpl_interactions/mpl_kwargs.py b/mpl_interactions/mpl_kwargs.py index e2a9fd9..33690a2 100644 --- a/mpl_interactions/mpl_kwargs.py +++ b/mpl_interactions/mpl_kwargs.py @@ -61,7 +61,11 @@ "zorder", ] -imshow_kwargs_list = ArtistInspector(AxesImage).get_setters() +imshow_kwargs_list = [ + *ArtistInspector(AxesImage).get_setters(), + "aspect", # these are arguments to imshow not captured by `get_setter` + "origin", +] collection_kwargs_list = ArtistInspector(Collection).get_setters() Text_kwargs_list = [ diff --git a/mpl_interactions/pyplot.py b/mpl_interactions/pyplot.py index 8a5661a..9fde3bf 100644 --- a/mpl_interactions/pyplot.py +++ b/mpl_interactions/pyplot.py @@ -417,7 +417,6 @@ def interactive_scatter( y=None, s=None, c=None, - cmap=None, vmin=None, vmax=None, alpha=None, @@ -448,14 +447,19 @@ def interactive_scatter( Valid input to plt.scatter or a function s : float, array-like, function, or index controls object valid input to plt.scatter, or a function - alpha : float, None, or function(s), broadcastable + vmin, vmax : float, callable, shorthand for slider or indexed controls + The vmin, vmax values for the colormap. Can accept a float for a fixed value, + or any slider shorthand to control with a slider, or an indexed controls + object to use an existing slider, or an arbitrary function of the other + parameters. + alpha : float or Callable, optional Affects all scatter points. This will compound with any alpha introduced by the ``c`` argument marker : MarkerStyle, or Callable, optional The marker style or a function returning marker styles. - edgecolor[s] : callable or valid argument to scatter + edgecolors : callable or valid argument to scatter passed through to scatter. - facecolor[s] : callable or valid argument to scatter + facecolors : callable or valid argument to scatter Valid input to plt.scatter, or a function label : string Passed through to Matplotlib @@ -486,12 +490,13 @@ def interactive_scatter( - False: no sliders - 'left': sliders on the left - 'right': sliders on the right - controls : mpl_interactions.controller.Controls An existing controls object if you want to tie multiple plot elements to the same set of controls display_controls : boolean Whether the controls should display on creation. Ignored if controls is specified. + **kwargs: + Interpreted as widgets and remainder are passed through to `ax.scatter`. Returns ------- @@ -616,7 +621,6 @@ def check_callable_alpha(alpha_, params, cache): s=s_, vmin=vmin, vmax=vmax, - cmap=cmap, marker=marker_, alpha=a_, edgecolors=ec_, @@ -635,21 +639,11 @@ def check_callable_alpha(alpha_, params, cache): # of `matplotlib.pyplot.imshow` def interactive_imshow( X, - cmap=None, - norm=None, - aspect=None, - interpolation=None, alpha=None, vmin=None, vmax=None, vmin_vmax=None, - origin=None, - extent=None, autoscale_cmap=True, - filternorm=True, - filterrad=4.0, - resample=None, - url=None, ax=None, slider_formats=None, force_ipywidgets=False, @@ -666,29 +660,23 @@ def interactive_imshow( X : function or image like If a function it must return an image-like object. See matplotlib.pyplot.imshow for the full set of valid options. - cmap : str or `~matplotlib.colors.Colormap` - The Colormap instance or registered colormap name used to map - scalar data to colors. This parameter is ignored for RGB(A) data. - forwarded to matplotlib - norm : `~matplotlib.colors.Normalize`, optional - The `~matplotlib.colors.Normalize` instance used to scale scalar data to the [0, 1] - range before mapping to colors using *cmap*. By default, a linear - scaling mapping the lowest value to 0 and the highest to 1 is used. - This parameter is ignored for RGB(A) data. - forwarded to matplotlib - autoscale_cmap : bool - If True rescale the colormap for every function update. Will not update - if vmin and vmax are provided or if the returned image is RGB(A) like. - forwarded to matplotlib - aspect : {'equal', 'auto'} or float - forwarded to matplotlib - interpolation : str - forwarded to matplotlib alpha : float, callable, shorthand for slider or indexed controls The alpha value of the image. Can accept a float for a fixed value, or any slider shorthand to control with a slider, or an indexed controls object to use an existing slider, or an arbitrary function of the other parameters. + vmin, vmax : float, callable, shorthand for slider or indexed controls + The vmin, vmax values for the colormap. Can accept a float for a fixed value, + or any slider shorthand to control with a slider, or an indexed controls + object to use an existing slider, or an arbitrary function of the other + parameters. + vmin_vmax : tuple of float + Used to generate a range slider for vmin and vmax. Should be given in range slider + notation: `("r", 0, 1)`. + autoscale_cmap : bool + If True rescale the colormap for every function update. Will not update + if vmin and vmax are provided or if the returned image is RGB(A) like. + forwarded to matplotlib ax : matplotlib axis, optional The axis on which to plot. If none the current axis will be used. slider_formats : None, string, or dict @@ -707,12 +695,13 @@ def interactive_imshow( - False: no sliders - 'left': sliders on the left - 'right': sliders on the right - controls : mpl_interactions.controller.Controls An existing controls object if you want to tie multiple plot elements to the same set of controls display_controls : boolean Whether the controls should display on creation. Ignored if controls is specified. + **kwargs: + Interpreted as widgets and remainder are passed through to `ax.imshow`. Returns ------- @@ -777,19 +766,9 @@ def update(params, indices, cache): sca(ax) im = ax.imshow( new_data, - cmap=cmap, - norm=norm, - aspect=aspect, - interpolation=interpolation, alpha=callable_else_value_no_cast(alpha, param_excluder(params, "alpha")), vmin=callable_else_value_no_cast(vmin, param_excluder(params, "vmin")), vmax=callable_else_value_no_cast(vmax, param_excluder(params, "vmax")), - origin=origin, - extent=extent, - filternorm=filternorm, - filterrad=filterrad, - resample=resample, - url=url, **imshow_kwargs, ) @@ -1287,7 +1266,8 @@ def interactive_text( .. note:: - fontdict properties are currently static - see https://github.com/mpl-extensions/mpl-interactions/issues/247 + fontdict properties are currently static + see https://github.com/mpl-extensions/mpl-interactions/issues/247 Parameters