From ba44468b8d1535df0edd321b91e31c93b4b2fad2 Mon Sep 17 00:00:00 2001 From: Silke Schomann Date: Mon, 11 Nov 2024 09:25:00 +0000 Subject: [PATCH 01/23] Generated new version of pyplot --- src/mslice/plotting/pyplot.py | 2280 +++++++++++++++++++++++++-------- tools/boilerplate.py | 179 ++- 2 files changed, 1892 insertions(+), 567 deletions(-) diff --git a/src/mslice/plotting/pyplot.py b/src/mslice/plotting/pyplot.py index 8d049ac8..48947455 100644 --- a/src/mslice/plotting/pyplot.py +++ b/src/mslice/plotting/pyplot.py @@ -29,6 +29,7 @@ from matplotlib import rcsetup, style from matplotlib import _pylab_helpers, interactive from matplotlib import cbook + try: from matplotlib import _docstring as docstring except ImportError: @@ -46,6 +47,7 @@ from matplotlib import cm from matplotlib.cm import _colormaps as colormaps, register_cmap + try: from matplotlib.cm import _get_cmap as get_cmap except ImportError: @@ -61,15 +63,33 @@ from matplotlib.widgets import Button, Slider, Widget from matplotlib.ticker import ( - TickHelper, Formatter, FixedFormatter, NullFormatter, FuncFormatter, - FormatStrFormatter, ScalarFormatter, LogFormatter, LogFormatterExponent, - LogFormatterMathtext, Locator, IndexLocator, FixedLocator, NullLocator, - LinearLocator, LogLocator, AutoLocator, MultipleLocator, MaxNLocator) + TickHelper, + Formatter, + FixedFormatter, + NullFormatter, + FuncFormatter, + FormatStrFormatter, + ScalarFormatter, + LogFormatter, + LogFormatterExponent, + LogFormatterMathtext, + Locator, + IndexLocator, + FixedLocator, + NullLocator, + LinearLocator, + LogLocator, + AutoLocator, + MultipleLocator, + MaxNLocator, +) from mslice.plotting.globalfiguremanager import set_category -from mslice.plotting.globalfiguremanager import (CATEGORY_CUT, - CATEGORY_SLICE, - GlobalFigureManager) +from mslice.plotting.globalfiguremanager import ( + CATEGORY_CUT, + CATEGORY_SLICE, + GlobalFigureManager, +) _log = logging.getLogger(__name__) @@ -142,6 +162,7 @@ def install_repl_displayhook(): _REPL_DISPLAYHOOK = _ReplDisplayHook.IPYTHON from IPython.core.pylabtools import backend2gui + # trigger IPython's eventloop integration, if available ipython_gui_name = backend2gui.get(get_backend()) if ipython_gui_name: @@ -153,6 +174,7 @@ def uninstall_repl_displayhook(): global _REPL_DISPLAYHOOK if _REPL_DISPLAYHOOK is _ReplDisplayHook.IPYTHON: from IPython import get_ipython + ip = get_ipython() ip.events.unregister("post_execute", _draw_all_if_interactive) _REPL_DISPLAYHOOK = _ReplDisplayHook.NONE @@ -171,15 +193,19 @@ def findobj(o=None, match=None, include_self=True): def _get_required_interactive_framework(backend_mod): - if not hasattr(getattr(backend_mod, "FigureCanvas", None), - "required_interactive_framework"): + if not hasattr( + getattr(backend_mod, "FigureCanvas", None), "required_interactive_framework" + ): _api.warn_deprecated( - "3.6", name="Support for FigureCanvases without a " - "required_interactive_framework attribute") + "3.6", + name="Support for FigureCanvases without a " + "required_interactive_framework attribute", + ) return None # Inline this once the deprecation elapses. return backend_mod.FigureCanvas.required_interactive_framework + _backend_mod = None @@ -213,25 +239,27 @@ def switch_backend(newbackend): global _backend_mod # make sure the init is pulled up so we can assign to it later import matplotlib.backends + close("all") if newbackend is rcsetup._auto_backend_sentinel: current_framework = cbook._get_running_interactive_framework() - mapping = {'qt': 'qtagg', - 'gtk3': 'gtk3agg', - 'gtk4': 'gtk4agg', - 'wx': 'wxagg', - 'tk': 'tkagg', - 'macosx': 'macosx', - 'headless': 'agg'} + mapping = { + "qt": "qtagg", + "gtk3": "gtk3agg", + "gtk4": "gtk4agg", + "wx": "wxagg", + "tk": "tkagg", + "macosx": "macosx", + "headless": "agg", + } best_guess = mapping.get(current_framework, None) if best_guess is not None: candidates = [best_guess] else: candidates = [] - candidates += [ - "macosx", "qtagg", "gtk4agg", "gtk3agg", "tkagg", "wxagg"] + candidates += ["macosx", "qtagg", "gtk4agg", "gtk3agg", "tkagg", "wxagg"] # Don't try to fallback on the cairo-based backends as they each have # an additional dependency (pycairo) over the agg-based backend, and @@ -242,7 +270,7 @@ def switch_backend(newbackend): except ImportError: continue else: - rcParamsOrig['backend'] = candidate + rcParamsOrig["backend"] = candidate return else: # Switching to Agg should always succeed; if it doesn't, let the @@ -251,24 +279,29 @@ def switch_backend(newbackend): rcParamsOrig["backend"] = "agg" return - backend_mod = importlib.import_module( - cbook._backend_module_name(newbackend)) + backend_mod = importlib.import_module(cbook._backend_module_name(newbackend)) required_framework = _get_required_interactive_framework(backend_mod) if required_framework is not None: current_framework = cbook._get_running_interactive_framework() - if (current_framework and required_framework - and current_framework != required_framework): + if ( + current_framework + and required_framework + and current_framework != required_framework + ): raise ImportError( "Cannot load backend {!r} which requires the {!r} interactive " "framework, as {!r} is currently running".format( - newbackend, required_framework, current_framework)) + newbackend, required_framework, current_framework + ) + ) # Load the new_figure_manager() and show() functions from the backend. # Classically, backends can directly export these functions. This should # keep working for backcompat. new_figure_manager = getattr(backend_mod, "new_figure_manager", None) + # show = getattr(backend_mod, "show", None) # In that classical approach, backends are implemented as modules, but # "inherit" default method implementations from backend_bases._Backend. @@ -284,6 +317,7 @@ class backend_mod(matplotlib.backend_bases._Backend): if new_figure_manager is None: # only try to get the canvas class if have opted into the new scheme canvas_class = backend_mod.FigureCanvas + def new_figure_manager_given_figure(num, figure): return canvas_class.new_manager(figure, num) @@ -297,19 +331,18 @@ def draw_if_interactive(): if manager: manager.canvas.draw_idle() - backend_mod.new_figure_manager_given_figure = \ - new_figure_manager_given_figure + backend_mod.new_figure_manager_given_figure = new_figure_manager_given_figure backend_mod.new_figure_manager = new_figure_manager backend_mod.draw_if_interactive = draw_if_interactive - _log.debug("Loaded backend %s version %s.", - newbackend, backend_mod.backend_version) + _log.debug("Loaded backend %s version %s.", newbackend, backend_mod.backend_version) - rcParams['backend'] = rcParamsDefault['backend'] = newbackend + rcParams["backend"] = rcParamsDefault["backend"] = newbackend _backend_mod = backend_mod for func_name in ["new_figure_manager", "draw_if_interactive", "show"]: globals()[func_name].__signature__ = inspect.signature( - getattr(backend_mod, func_name)) + getattr(backend_mod, func_name) + ) # Need to keep a global reference to the backend for compatibility reasons. # See https://github.com/matplotlib/matplotlib/issues/6092 @@ -323,7 +356,7 @@ def draw_if_interactive(): def _warn_if_gui_out_of_main_thread(): warn = False if _get_required_interactive_framework(_get_backend_mod()): - if hasattr(threading, 'get_native_id'): + if hasattr(threading, "get_native_id"): # This compares native thread ids because even if Python-level # Thread objects match, the underlying OS thread (which is what # really matters) may be different on Python implementations with @@ -337,8 +370,8 @@ def _warn_if_gui_out_of_main_thread(): warn = True if warn: _api.warn_external( - "Starting a Matplotlib GUI outside of the main thread will likely " - "fail.") + "Starting a Matplotlib GUI outside of the main thread will likely " "fail." + ) # This function's signature is rewritten upon backend-load by switch_backend. @@ -621,50 +654,58 @@ def xkcd(scale=1, length=100, randomness=2): # This cannot be implemented in terms of contextmanager() or rc_context() # because this needs to work as a non-contextmanager too. - if rcParams['text.usetex']: - raise RuntimeError( - "xkcd mode is not compatible with text.usetex = True") + if rcParams["text.usetex"]: + raise RuntimeError("xkcd mode is not compatible with text.usetex = True") stack = ExitStack() stack.callback(dict.update, rcParams, rcParams.copy()) from matplotlib import patheffects - rcParams.update({ - 'font.family': ['xkcd', 'xkcd Script', 'Humor Sans', 'Comic Neue', - 'Comic Sans MS'], - 'font.size': 14.0, - 'path.sketch': (scale, length, randomness), - 'path.effects': [ - patheffects.withStroke(linewidth=4, foreground="w")], - 'axes.linewidth': 1.5, - 'lines.linewidth': 2.0, - 'figure.facecolor': 'white', - 'grid.linewidth': 0.0, - 'axes.grid': False, - 'axes.unicode_minus': False, - 'axes.edgecolor': 'black', - 'xtick.major.size': 8, - 'xtick.major.width': 3, - 'ytick.major.size': 8, - 'ytick.major.width': 3, - }) + + rcParams.update( + { + "font.family": [ + "xkcd", + "xkcd Script", + "Humor Sans", + "Comic Neue", + "Comic Sans MS", + ], + "font.size": 14.0, + "path.sketch": (scale, length, randomness), + "path.effects": [patheffects.withStroke(linewidth=4, foreground="w")], + "axes.linewidth": 1.5, + "lines.linewidth": 2.0, + "figure.facecolor": "white", + "grid.linewidth": 0.0, + "axes.grid": False, + "axes.unicode_minus": False, + "axes.edgecolor": "black", + "xtick.major.size": 8, + "xtick.major.width": 3, + "ytick.major.size": 8, + "ytick.major.width": 3, + } + ) return stack ## Figures ## + @_api.make_keyword_only("3.6", "facecolor") -def figure(num=None, # autoincrement if None, else integer from 1-N - figsize=None, # defaults to rc figure.figsize - dpi=None, # defaults to rc figure.dpi - facecolor=None, # defaults to rc figure.facecolor - edgecolor=None, # defaults to rc figure.edgecolor - frameon=True, - FigureClass=Figure, - clear=False, - **kwargs - ): +def figure( + num=None, # autoincrement if None, else integer from 1-N + figsize=None, # defaults to rc figure.figsize + dpi=None, # defaults to rc figure.dpi + facecolor=None, # defaults to rc figure.facecolor + edgecolor=None, # defaults to rc figure.edgecolor + frameon=True, + FigureClass=Figure, + clear=False, + **kwargs, +): return GlobalFigureManager.get_figure_number(num).figure @@ -679,9 +720,12 @@ def _auto_draw_if_interactive(fig, val): fig : Figure A figure object which is assumed to be associated with a canvas """ - if (val and matplotlib.is_interactive() - and not fig.canvas.is_saving() - and not fig.canvas._is_idle_drawing): + if ( + val + and matplotlib.is_interactive() + and not fig.canvas.is_saving() + and not fig.canvas._is_idle_drawing + ): # Some artists can mark themselves as stale in the middle of drawing # (e.g. axes position & tick labels being computed at draw time), but # this shouldn't trigger a redraw because the current redraw will @@ -755,11 +799,11 @@ def close(fig=None): return else: GlobalFigureManager.destroy(figManager.num) - elif fig == 'all': + elif fig == "all": GlobalFigureManager.destroy_all() elif isinstance(fig, int): GlobalFigureManager.destroy(fig) - elif hasattr(fig, 'int'): + elif hasattr(fig, "int"): # if we are dealing with a type UUID, we # can use its integer representation GlobalFigureManager.destroy(fig.int) @@ -771,8 +815,10 @@ def close(fig=None): elif isinstance(fig, Figure): GlobalFigureManager.destroy_fig(fig) else: - raise TypeError("close() argument must be a Figure, an int, a string, " - "or None, not %s" % type(fig)) + raise TypeError( + "close() argument must be a Figure, an int, a string, " + "or None, not %s" % type(fig) + ) def clf(): @@ -808,12 +854,15 @@ def savefig(*args, **kwargs): def figlegend(*args, **kwargs): return gcf().legend(*args, **kwargs) + + if Figure.legend.__doc__: figlegend.__doc__ = Figure.legend.__doc__.replace("legend(", "figlegend(") ## Axes ## + @docstring.dedent_interpd def axes(arg=None, **kwargs): """ @@ -902,7 +951,7 @@ def axes(arg=None, **kwargs): plt.axes((left, bottom, width, height), facecolor='grey') """ fig = gcf() - pos = kwargs.pop('position', None) + pos = kwargs.pop("position", None) if arg is None: if pos is None: return fig.add_subplot(**kwargs) @@ -937,6 +986,7 @@ def cla(): ## More ways of creating axes ## + @docstring.dedent_interpd def subplot(*args, **kwargs): """ @@ -1076,16 +1126,16 @@ def subplot(*args, **kwargs): # Here we will only normalize `polar=True` vs `projection='polar'` and let # downstream code deal with the rest. unset = object() - projection = kwargs.get('projection', unset) - polar = kwargs.pop('polar', unset) + projection = kwargs.get("projection", unset) + polar = kwargs.pop("polar", unset) if polar is not unset and polar: # if we got mixed messages from the user, raise - if projection is not unset and projection != 'polar': + if projection is not unset and projection != "polar": raise ValueError( f"polar={polar}, yet projection={projection!r}. " "Only one of these arguments should be supplied." ) - kwargs['projection'] = projection = 'polar' + kwargs["projection"] = projection = "polar" # if subplot called without arguments, create subplot(1, 1, 1) if len(args) == 0: @@ -1097,13 +1147,17 @@ def subplot(*args, **kwargs): # because what was intended to be the sharex argument is instead treated as # a subplot index for subplot() if len(args) >= 3 and isinstance(args[2], bool): - _api.warn_external("The subplot index argument to subplot() appears " - "to be a boolean. Did you intend to use " - "subplots()?") + _api.warn_external( + "The subplot index argument to subplot() appears " + "to be a boolean. Did you intend to use " + "subplots()?" + ) # Check for nrows and ncols, which are not valid subplot args: - if 'nrows' in kwargs or 'ncols' in kwargs: - raise TypeError("subplot() got an unexpected keyword argument 'ncols' " - "and/or 'nrows'. Did you intend to call subplots()?") + if "nrows" in kwargs or "ncols" in kwargs: + raise TypeError( + "subplot() got an unexpected keyword argument 'ncols' " + "and/or 'nrows'. Did you intend to call subplots()?" + ) fig = gcf() @@ -1112,7 +1166,7 @@ def subplot(*args, **kwargs): for ax in fig.axes: # if we found an Axes at the position sort out if we can re-use it - if hasattr(ax, 'get_subplotspec') and ax.get_subplotspec() == key: + if hasattr(ax, "get_subplotspec") and ax.get_subplotspec() == key: # if the user passed no kwargs, re-use if kwargs == {}: break @@ -1127,22 +1181,37 @@ def subplot(*args, **kwargs): fig.sca(ax) - axes_to_delete = [other for other in fig.axes - if other != ax and ax.bbox.fully_overlaps(other.bbox)] + axes_to_delete = [ + other + for other in fig.axes + if other != ax and ax.bbox.fully_overlaps(other.bbox) + ] if axes_to_delete: _api.warn_deprecated( - "3.6", message="Auto-removal of overlapping axes is deprecated " + "3.6", + message="Auto-removal of overlapping axes is deprecated " "since %(since)s and will be removed %(removal)s; explicitly call " - "ax.remove() as needed.") + "ax.remove() as needed.", + ) for ax_to_del in axes_to_delete: delaxes(ax_to_del) return ax -def subplots(nrows=1, ncols=1, *, sharex=False, sharey=False, squeeze=True, - width_ratios=None, height_ratios=None, - subplot_kw=None, gridspec_kw=None, **fig_kw): +def subplots( + nrows=1, + ncols=1, + *, + sharex=False, + sharey=False, + squeeze=True, + width_ratios=None, + height_ratios=None, + subplot_kw=None, + gridspec_kw=None, + **fig_kw, +): """ Create a figure and a set of subplots. @@ -1287,16 +1356,32 @@ def subplots(nrows=1, ncols=1, *, sharex=False, sharey=False, squeeze=True, """ fig = figure(**fig_kw) - axs = fig.subplots(nrows=nrows, ncols=ncols, sharex=sharex, sharey=sharey, - squeeze=squeeze, subplot_kw=subplot_kw, - gridspec_kw=gridspec_kw, height_ratios=height_ratios, - width_ratios=width_ratios) + axs = fig.subplots( + nrows=nrows, + ncols=ncols, + sharex=sharex, + sharey=sharey, + squeeze=squeeze, + subplot_kw=subplot_kw, + gridspec_kw=gridspec_kw, + height_ratios=height_ratios, + width_ratios=width_ratios, + ) return fig, axs -def subplot_mosaic(mosaic, *, sharex=False, sharey=False, - width_ratios=None, height_ratios=None, empty_sentinel='.', - subplot_kw=None, gridspec_kw=None, **fig_kw): +def subplot_mosaic( + mosaic, + *, + sharex=False, + sharey=False, + width_ratios=None, + height_ratios=None, + empty_sentinel=".", + subplot_kw=None, + gridspec_kw=None, + **fig_kw, +): """ Build a layout of Axes based on ASCII art or nested lists. @@ -1390,10 +1475,14 @@ def subplot_mosaic(mosaic, *, sharex=False, sharey=False, """ fig = figure(**fig_kw) ax_dict = fig.subplot_mosaic( - mosaic, sharex=sharex, sharey=sharey, - height_ratios=height_ratios, width_ratios=width_ratios, - subplot_kw=subplot_kw, gridspec_kw=gridspec_kw, - empty_sentinel=empty_sentinel + mosaic, + sharex=sharex, + sharey=sharey, + height_ratios=height_ratios, + width_ratios=width_ratios, + subplot_kw=subplot_kw, + gridspec_kw=gridspec_kw, + empty_sentinel=empty_sentinel, ) return fig, ax_dict @@ -1448,13 +1537,18 @@ def subplot2grid(shape, loc, rowspan=1, colspan=1, fig=None, **kwargs): subplotspec = gs.new_subplotspec(loc, rowspan=rowspan, colspan=colspan) ax = fig.add_subplot(subplotspec, **kwargs) - axes_to_delete = [other for other in fig.axes - if other != ax and ax.bbox.fully_overlaps(other.bbox)] + axes_to_delete = [ + other + for other in fig.axes + if other != ax and ax.bbox.fully_overlaps(other.bbox) + ] if axes_to_delete: _api.warn_deprecated( - "3.6", message="Auto-removal of overlapping axes is deprecated " + "3.6", + message="Auto-removal of overlapping axes is deprecated " "since %(since)s and will be removed %(removal)s; explicitly call " - "ax.remove() as needed.") + "ax.remove() as needed.", + ) for ax_to_del in axes_to_delete: delaxes(ax_to_del) @@ -1501,8 +1595,8 @@ def subplot_tool(targetfig=None): ------- `matplotlib.widgets.SubplotTool` """ - tbar = rcParams['toolbar'] # turn off the navigation toolbar for toolfig - rcParams['toolbar'] = 'None' + tbar = rcParams["toolbar"] # turn off the navigation toolbar for toolfig + rcParams["toolbar"] = "None" if targetfig is None: manager = get_current_fig_manager() targetfig = manager.canvas.figure @@ -1512,12 +1606,12 @@ def subplot_tool(targetfig=None): if manager.canvas.figure == targetfig: break else: - raise RuntimeError('Could not find manager for targetfig') + raise RuntimeError("Could not find manager for targetfig") toolfig = figure(figsize=(6, 3)) toolfig.subplots_adjust(top=0.9) ret = SubplotTool(targetfig, toolfig) - rcParams['toolbar'] = tbar + rcParams["toolbar"] = tbar GlobalFigureManager.set_active(manager) # restore the current figure return ret @@ -1542,6 +1636,7 @@ def box(on=None): on = not ax.get_frame_on() ax.set_frame_on(on) + ## Axis ## @@ -1667,8 +1762,9 @@ def xticks(ticks=None, labels=None, *, minor=False, **kwargs): if ticks is None: locs = ax.get_xticks(minor=minor) if labels is not None: - raise TypeError("xticks(): Parameter 'labels' can't be set " - "without setting 'ticks'") + raise TypeError( + "xticks(): Parameter 'labels' can't be set " "without setting 'ticks'" + ) else: locs = ax.set_xticks(ticks, minor=minor) @@ -1730,8 +1826,9 @@ def yticks(ticks=None, labels=None, *, minor=False, **kwargs): if ticks is None: locs = ax.get_yticks(minor=minor) if labels is not None: - raise TypeError("yticks(): Parameter 'labels' can't be set " - "without setting 'ticks'") + raise TypeError( + "yticks(): Parameter 'labels' can't be set " "without setting 'ticks'" + ) else: locs = ax.set_yticks(ticks, minor=minor) @@ -1806,13 +1903,14 @@ def rgrids(radii=None, labels=None, angle=None, fmt=None, **kwargs): """ ax = gca() if not isinstance(ax, PolarAxes): - raise RuntimeError('rgrids only defined for polar axes') + raise RuntimeError("rgrids only defined for polar axes") if all(p is None for p in [radii, labels, angle, fmt]) and not kwargs: lines = ax.yaxis.get_gridlines() labels = ax.yaxis.get_ticklabels() else: lines, labels = ax.set_rgrids( - radii, labels=labels, angle=angle, fmt=fmt, **kwargs) + radii, labels=labels, angle=angle, fmt=fmt, **kwargs + ) return lines, labels @@ -1874,19 +1972,23 @@ def thetagrids(angles=None, labels=None, fmt=None, **kwargs): """ ax = gca() if not isinstance(ax, PolarAxes): - raise RuntimeError('thetagrids only defined for polar axes') + raise RuntimeError("thetagrids only defined for polar axes") if all(param is None for param in [angles, labels, fmt]) and not kwargs: lines = ax.xaxis.get_ticklines() labels = ax.xaxis.get_ticklabels() else: - lines, labels = ax.set_thetagrids(angles, - labels=labels, fmt=fmt, **kwargs) + lines, labels = ax.set_thetagrids(angles, labels=labels, fmt=fmt, **kwargs) return lines, labels _NON_PLOT_COMMANDS = { - 'connect', 'disconnect', 'get_current_fig_manager', 'ginput', - 'new_figure_manager', 'waitforbuttonpress'} + "connect", + "disconnect", + "get_current_fig_manager", + "ginput", + "new_figure_manager", + "waitforbuttonpress", +} def get_plot_commands(): @@ -1896,14 +1998,22 @@ def get_plot_commands(): # This works by searching for all functions in this module and removing # a few hard-coded exclusions, as well as all of the colormap-setting # functions, and anything marked as private with a preceding underscore. - exclude = {'colormaps', 'colors', 'get_plot_commands', - *_NON_PLOT_COMMANDS, *colormaps} + exclude = { + "colormaps", + "colors", + "get_plot_commands", + *_NON_PLOT_COMMANDS, + *colormaps, + } this_module = inspect.getmodule(get_plot_commands) return sorted( - name for name, obj in globals().items() - if not name.startswith('_') and name not in exclude - and inspect.isfunction(obj) - and inspect.getmodule(obj) is this_module) + name + for name, obj in globals().items() + if not name.startswith("_") + and name not in exclude + and inspect.isfunction(obj) + and inspect.getmodule(obj) is this_module + ) ## Plotting part 1: manually generated functions and wrappers ## @@ -1914,10 +2024,12 @@ def colorbar(mappable=None, cax=None, ax=None, **kwargs): if mappable is None: mappable = gci() if mappable is None: - raise RuntimeError('No mappable was found to use for colorbar ' - 'creation. First define a mappable such as ' - 'an image (with imshow) or a contour set (' - 'with contourf).') + raise RuntimeError( + "No mappable was found to use for colorbar " + "creation. First define a mappable such as " + "an image (with imshow) or a contour set (" + "with contourf)." + ) ret = gcf().colorbar(mappable, cax=cax, ax=ax, **kwargs) return ret @@ -1938,7 +2050,7 @@ def clim(vmin=None, vmax=None): """ im = gci() if im is None: - raise RuntimeError('You must first define an image, e.g., with imshow') + raise RuntimeError("You must first define an image, e.g., with imshow") im.set_clim(vmin, vmax) @@ -1960,7 +2072,7 @@ def set_cmap(cmap): """ cmap = get_cmap(cmap) - rc('image', cmap=cmap.name) + rc("image", cmap=cmap.name) im = gci() if im is not None: @@ -2044,8 +2156,10 @@ def polar(*args, **kwargs): if gcf().get_axes(): ax = gca() if not isinstance(ax, PolarAxes): - _api.warn_external('Trying to create polar plot on an Axes ' - 'that does not have a polar projection.') + _api.warn_external( + "Trying to create polar plot on an Axes " + "that does not have a polar projection." + ) else: ax = axes(projection="polar") return ax.plot(*args, **kwargs) @@ -2057,129 +2171,258 @@ def polar(*args, **kwargs): # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Figure.figimage) def figimage( - X, xo=0, yo=0, alpha=None, norm=None, cmap=None, vmin=None, - vmax=None, origin=None, resize=False, **kwargs): + X: ArrayLike, + xo: int = 0, + yo: int = 0, + alpha: float | None = None, + norm: str | Normalize | None = None, + cmap: str | Colormap | None = None, + vmin: float | None = None, + vmax: float | None = None, + origin: Literal["upper", "lower"] | None = None, + resize: bool = False, + **kwargs, +) -> FigureImage: return gcf().figimage( - X, xo=xo, yo=yo, alpha=alpha, norm=norm, cmap=cmap, vmin=vmin, - vmax=vmax, origin=origin, resize=resize, **kwargs) + X, + xo=xo, + yo=yo, + alpha=alpha, + norm=norm, + cmap=cmap, + vmin=vmin, + vmax=vmax, + origin=origin, + resize=resize, + **kwargs, + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Figure.text) -def figtext(x, y, s, fontdict=None, **kwargs): +def figtext( + x: float, y: float, s: str, fontdict: dict[str, Any] | None = None, **kwargs +) -> Text: return gcf().text(x, y, s, fontdict=fontdict, **kwargs) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Figure.gca) -def gca(): +def gca() -> Axes: return gcf().gca() # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Figure._gci) -def gci(): +def gci() -> ScalarMappable | None: return gcf()._gci() # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Figure.ginput) def ginput( - n=1, timeout=30, show_clicks=True, - mouse_add=MouseButton.LEFT, mouse_pop=MouseButton.RIGHT, - mouse_stop=MouseButton.MIDDLE): + n: int = 1, + timeout: float = 30, + show_clicks: bool = True, + mouse_add: MouseButton = MouseButton.LEFT, + mouse_pop: MouseButton = MouseButton.RIGHT, + mouse_stop: MouseButton = MouseButton.MIDDLE, +) -> list[tuple[int, int]]: return gcf().ginput( - n=n, timeout=timeout, show_clicks=show_clicks, - mouse_add=mouse_add, mouse_pop=mouse_pop, - mouse_stop=mouse_stop) + n=n, + timeout=timeout, + show_clicks=show_clicks, + mouse_add=mouse_add, + mouse_pop=mouse_pop, + mouse_stop=mouse_stop, + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Figure.subplots_adjust) def subplots_adjust( - left=None, bottom=None, right=None, top=None, wspace=None, - hspace=None): - return gcf().subplots_adjust( - left=left, bottom=bottom, right=right, top=top, wspace=wspace, - hspace=hspace) + left: float | None = None, + bottom: float | None = None, + right: float | None = None, + top: float | None = None, + wspace: float | None = None, + hspace: float | None = None, +) -> None: + gcf().subplots_adjust( + left=left, bottom=bottom, right=right, top=top, wspace=wspace, hspace=hspace + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Figure.suptitle) -def suptitle(t, **kwargs): +def suptitle(t: str, **kwargs) -> Text: return gcf().suptitle(t, **kwargs) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Figure.tight_layout) -def tight_layout(*, pad=1.08, h_pad=None, w_pad=None, rect=None): - return gcf().tight_layout(pad=pad, h_pad=h_pad, w_pad=w_pad, rect=rect) +def tight_layout( + *, + pad: float = 1.08, + h_pad: float | None = None, + w_pad: float | None = None, + rect: tuple[float, float, float, float] | None = None, +) -> None: + gcf().tight_layout(pad=pad, h_pad=h_pad, w_pad=w_pad, rect=rect) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Figure.waitforbuttonpress) -def waitforbuttonpress(timeout=-1): +def waitforbuttonpress(timeout: float = -1) -> None | bool: return gcf().waitforbuttonpress(timeout=timeout) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.acorr) @set_category(CATEGORY_CUT) -def acorr(x, *, data=None, **kwargs): - return gca().acorr( - x, **({"data": data} if data is not None else {}), **kwargs) +def acorr( + x: ArrayLike, *, data=None, **kwargs +) -> tuple[np.ndarray, np.ndarray, LineCollection | Line2D, Line2D | None]: + return gca().acorr(x, **({"data": data} if data is not None else {}), **kwargs) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.angle_spectrum) @set_category(CATEGORY_CUT) def angle_spectrum( - x, Fs=None, Fc=None, window=None, pad_to=None, sides=None, *, - data=None, **kwargs): + x: ArrayLike, + Fs: float | None = None, + Fc: int | None = None, + window: Callable[[ArrayLike], ArrayLike] | ArrayLike | None = None, + pad_to: int | None = None, + sides: Literal["default", "onesided", "twosided"] | None = None, + *, + data=None, + **kwargs, +) -> tuple[np.ndarray, np.ndarray, Line2D]: return gca().angle_spectrum( - x, Fs=Fs, Fc=Fc, window=window, pad_to=pad_to, sides=sides, - **({"data": data} if data is not None else {}), **kwargs) + x, + Fs=Fs, + Fc=Fc, + window=window, + pad_to=pad_to, + sides=sides, + **({"data": data} if data is not None else {}), + **kwargs, + ) + + +# Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@_copy_docstring_and_deprecators(Axes.annotate) +@set_category(CATEGORY_CUT) +def annotate( + text: str, + xy: tuple[float, float], + xytext: tuple[float, float] | None = None, + xycoords: ( + str + | Artist + | Transform + | Callable[[RendererBase], Bbox | Transform] + | tuple[float, float] + ) = "data", + textcoords: ( + str + | Artist + | Transform + | Callable[[RendererBase], Bbox | Transform] + | tuple[float, float] + | None + ) = None, + arrowprops: dict[str, Any] | None = None, + annotation_clip: bool | None = None, + **kwargs, +) -> Annotation: + return gca().annotate( + text, + xy, + xytext=xytext, + xycoords=xycoords, + textcoords=textcoords, + arrowprops=arrowprops, + annotation_clip=annotation_clip, + **kwargs, + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.arrow) @set_category(CATEGORY_CUT) -def arrow(x, y, dx, dy, **kwargs): +def arrow(x: float, y: float, dx: float, dy: float, **kwargs) -> FancyArrow: return gca().arrow(x, y, dx, dy, **kwargs) +# Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@_copy_docstring_and_deprecators(Axes.autoscale) +@set_category(CATEGORY_CUT) +def autoscale( + enable: bool = True, + axis: Literal["both", "x", "y"] = "both", + tight: bool | None = None, +) -> None: + gca().autoscale(enable=enable, axis=axis, tight=tight) + + # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.axhline) @set_category(CATEGORY_CUT) -def axhline(y=0, xmin=0, xmax=1, **kwargs): +def axhline(y: float = 0, xmin: float = 0, xmax: float = 1, **kwargs) -> Line2D: return gca().axhline(y=y, xmin=xmin, xmax=xmax, **kwargs) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.axhspan) @set_category(CATEGORY_CUT) -def axhspan(ymin, ymax, xmin=0, xmax=1, **kwargs): +def axhspan( + ymin: float, ymax: float, xmin: float = 0, xmax: float = 1, **kwargs +) -> Polygon: return gca().axhspan(ymin, ymax, xmin=xmin, xmax=xmax, **kwargs) +# Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@_copy_docstring_and_deprecators(Axes.axis) +@set_category(CATEGORY_CUT) +def axis( + arg: tuple[float, float, float, float] | bool | str | None = None, + /, + *, + emit: bool = True, + **kwargs, +) -> tuple[float, float, float, float]: + return gca().axis(arg, emit=emit, **kwargs) + + # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.axline) @set_category(CATEGORY_CUT) -def axline(xy1, xy2=None, *, slope=None, **kwargs): +def axline( + xy1: tuple[float, float], + xy2: tuple[float, float] | None = None, + *, + slope: float | None = None, + **kwargs, +) -> AxLine: return gca().axline(xy1, xy2=xy2, slope=slope, **kwargs) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.axvline) @set_category(CATEGORY_CUT) -def axvline(x=0, ymin=0, ymax=1, **kwargs): +def axvline(x: float = 0, ymin: float = 0, ymax: float = 1, **kwargs) -> Line2D: return gca().axvline(x=x, ymin=ymin, ymax=ymax, **kwargs) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.axvspan) @set_category(CATEGORY_CUT) -def axvspan(xmin, xmax, ymin=0, ymax=1, **kwargs): +def axvspan( + xmin: float, xmax: float, ymin: float = 0, ymax: float = 1, **kwargs +) -> Polygon: return gca().axvspan(xmin, xmax, ymin=ymin, ymax=ymax, **kwargs) @@ -2187,83 +2430,164 @@ def axvspan(xmin, xmax, ymin=0, ymax=1, **kwargs): @_copy_docstring_and_deprecators(Axes.bar) @set_category(CATEGORY_CUT) def bar( - x, height, width=0.8, bottom=None, *, align='center', - data=None, **kwargs): + x: float | ArrayLike, + height: float | ArrayLike, + width: float | ArrayLike = 0.8, + bottom: float | ArrayLike | None = None, + *, + align: Literal["center", "edge"] = "center", + data=None, + **kwargs, +) -> BarContainer: return gca().bar( - x, height, width=width, bottom=bottom, align=align, - **({"data": data} if data is not None else {}), **kwargs) + x, + height, + width=width, + bottom=bottom, + align=align, + **({"data": data} if data is not None else {}), + **kwargs, + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.barbs) @set_category(CATEGORY_CUT) -def barbs(*args, data=None, **kwargs): - return gca().barbs( - *args, **({"data": data} if data is not None else {}), - **kwargs) +def barbs(*args, data=None, **kwargs) -> Barbs: + return gca().barbs(*args, **({"data": data} if data is not None else {}), **kwargs) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.barh) @set_category(CATEGORY_CUT) def barh( - y, width, height=0.8, left=None, *, align='center', - data=None, **kwargs): + y: float | ArrayLike, + width: float | ArrayLike, + height: float | ArrayLike = 0.8, + left: float | ArrayLike | None = None, + *, + align: Literal["center", "edge"] = "center", + data=None, + **kwargs, +) -> BarContainer: return gca().barh( - y, width, height=height, left=left, align=align, - **({"data": data} if data is not None else {}), **kwargs) + y, + width, + height=height, + left=left, + align=align, + **({"data": data} if data is not None else {}), + **kwargs, + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.bar_label) @set_category(CATEGORY_CUT) def bar_label( - container, labels=None, *, fmt='%g', label_type='edge', - padding=0, **kwargs): + container: BarContainer, + labels: ArrayLike | None = None, + *, + fmt: str | Callable[[float], str] = "%g", + label_type: Literal["center", "edge"] = "edge", + padding: float = 0, + **kwargs, +) -> list[Annotation]: return gca().bar_label( - container, labels=labels, fmt=fmt, label_type=label_type, - padding=padding, **kwargs) + container, + labels=labels, + fmt=fmt, + label_type=label_type, + padding=padding, + **kwargs, + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.boxplot) @set_category(CATEGORY_CUT) def boxplot( - x, notch=None, sym=None, vert=None, whis=None, - positions=None, widths=None, patch_artist=None, - bootstrap=None, usermedians=None, conf_intervals=None, - meanline=None, showmeans=None, showcaps=None, showbox=None, - showfliers=None, boxprops=None, labels=None, flierprops=None, - medianprops=None, meanprops=None, capprops=None, - whiskerprops=None, manage_ticks=True, autorange=False, - zorder=None, capwidths=None, *, data=None): + x: ArrayLike | Sequence[ArrayLike], + notch: bool | None = None, + sym: str | None = None, + vert: bool | None = None, + whis: float | tuple[float, float] | None = None, + positions: ArrayLike | None = None, + widths: float | ArrayLike | None = None, + patch_artist: bool | None = None, + bootstrap: int | None = None, + usermedians: ArrayLike | None = None, + conf_intervals: ArrayLike | None = None, + meanline: bool | None = None, + showmeans: bool | None = None, + showcaps: bool | None = None, + showbox: bool | None = None, + showfliers: bool | None = None, + boxprops: dict[str, Any] | None = None, + labels: Sequence[str] | None = None, + flierprops: dict[str, Any] | None = None, + medianprops: dict[str, Any] | None = None, + meanprops: dict[str, Any] | None = None, + capprops: dict[str, Any] | None = None, + whiskerprops: dict[str, Any] | None = None, + manage_ticks: bool = True, + autorange: bool = False, + zorder: float | None = None, + capwidths: float | ArrayLike | None = None, + *, + data=None, +) -> dict[str, Any]: return gca().boxplot( - x, notch=notch, sym=sym, vert=vert, whis=whis, - positions=positions, widths=widths, patch_artist=patch_artist, - bootstrap=bootstrap, usermedians=usermedians, - conf_intervals=conf_intervals, meanline=meanline, - showmeans=showmeans, showcaps=showcaps, showbox=showbox, - showfliers=showfliers, boxprops=boxprops, labels=labels, - flierprops=flierprops, medianprops=medianprops, - meanprops=meanprops, capprops=capprops, - whiskerprops=whiskerprops, manage_ticks=manage_ticks, - autorange=autorange, zorder=zorder, capwidths=capwidths, - **({"data": data} if data is not None else {})) + x, + notch=notch, + sym=sym, + vert=vert, + whis=whis, + positions=positions, + widths=widths, + patch_artist=patch_artist, + bootstrap=bootstrap, + usermedians=usermedians, + conf_intervals=conf_intervals, + meanline=meanline, + showmeans=showmeans, + showcaps=showcaps, + showbox=showbox, + showfliers=showfliers, + boxprops=boxprops, + labels=labels, + flierprops=flierprops, + medianprops=medianprops, + meanprops=meanprops, + capprops=capprops, + whiskerprops=whiskerprops, + manage_ticks=manage_ticks, + autorange=autorange, + zorder=zorder, + capwidths=capwidths, + **({"data": data} if data is not None else {}), + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.broken_barh) @set_category(CATEGORY_CUT) -def broken_barh(xranges, yrange, *, data=None, **kwargs): +def broken_barh( + xranges: Sequence[tuple[float, float]], + yrange: tuple[float, float], + *, + data=None, + **kwargs, +) -> BrokenBarHCollection: return gca().broken_barh( - xranges, yrange, - **({"data": data} if data is not None else {}), **kwargs) + xranges, yrange, **({"data": data} if data is not None else {}), **kwargs + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.clabel) @set_category(CATEGORY_CUT) -def clabel(CS, levels=None, **kwargs): +def clabel(CS: ContourSet, levels: ArrayLike | None = None, **kwargs) -> list[Text]: return gca().clabel(CS, levels=levels, **kwargs) @@ -2271,35 +2595,61 @@ def clabel(CS, levels=None, **kwargs): @_copy_docstring_and_deprecators(Axes.cohere) @set_category(CATEGORY_CUT) def cohere( - x, y, NFFT=256, Fs=2, Fc=0, detrend=mlab.detrend_none, - window=mlab.window_hanning, noverlap=0, pad_to=None, - sides='default', scale_by_freq=None, *, data=None, **kwargs): + x: ArrayLike, + y: ArrayLike, + NFFT: int = 256, + Fs: float = 2, + Fc: int = 0, + detrend: ( + Literal["none", "mean", "linear"] | Callable[[ArrayLike], ArrayLike] + ) = mlab.detrend_none, + window: Callable[[ArrayLike], ArrayLike] | ArrayLike = mlab.window_hanning, + noverlap: int = 0, + pad_to: int | None = None, + sides: Literal["default", "onesided", "twosided"] = "default", + scale_by_freq: bool | None = None, + *, + data=None, + **kwargs, +) -> tuple[np.ndarray, np.ndarray]: return gca().cohere( - x, y, NFFT=NFFT, Fs=Fs, Fc=Fc, detrend=detrend, window=window, - noverlap=noverlap, pad_to=pad_to, sides=sides, + x, + y, + NFFT=NFFT, + Fs=Fs, + Fc=Fc, + detrend=detrend, + window=window, + noverlap=noverlap, + pad_to=pad_to, + sides=sides, scale_by_freq=scale_by_freq, - **({"data": data} if data is not None else {}), **kwargs) + **({"data": data} if data is not None else {}), + **kwargs, + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.contour) @set_category(CATEGORY_SLICE) -def contour(*args, data=None, **kwargs): +def contour(*args, data=None, **kwargs) -> QuadContourSet: __ret = gca().contour( - *args, **({"data": data} if data is not None else {}), - **kwargs) - if __ret._A is not None: sci(__ret) # noqa + *args, **({"data": data} if data is not None else {}), **kwargs + ) + if __ret._A is not None: # type: ignore[attr-defined] + sci(__ret) return __ret # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.contourf) @set_category(CATEGORY_SLICE) -def contourf(*args, data=None, **kwargs): +def contourf(*args, data=None, **kwargs) -> QuadContourSet: __ret = gca().contourf( - *args, **({"data": data} if data is not None else {}), - **kwargs) - if __ret._A is not None: sci(__ret) # noqa + *args, **({"data": data} if data is not None else {}), **kwargs + ) + if __ret._A is not None: # type: ignore[attr-defined] + sci(__ret) return __ret @@ -2307,93 +2657,259 @@ def contourf(*args, data=None, **kwargs): @_copy_docstring_and_deprecators(Axes.csd) @set_category(CATEGORY_CUT) def csd( - x, y, NFFT=None, Fs=None, Fc=None, detrend=None, window=None, - noverlap=None, pad_to=None, sides=None, scale_by_freq=None, - return_line=None, *, data=None, **kwargs): + x: ArrayLike, + y: ArrayLike, + NFFT: int | None = None, + Fs: float | None = None, + Fc: int | None = None, + detrend: ( + Literal["none", "mean", "linear"] | Callable[[ArrayLike], ArrayLike] | None + ) = None, + window: Callable[[ArrayLike], ArrayLike] | ArrayLike | None = None, + noverlap: int | None = None, + pad_to: int | None = None, + sides: Literal["default", "onesided", "twosided"] | None = None, + scale_by_freq: bool | None = None, + return_line: bool | None = None, + *, + data=None, + **kwargs, +) -> tuple[np.ndarray, np.ndarray] | tuple[np.ndarray, np.ndarray, Line2D]: return gca().csd( - x, y, NFFT=NFFT, Fs=Fs, Fc=Fc, detrend=detrend, window=window, - noverlap=noverlap, pad_to=pad_to, sides=sides, - scale_by_freq=scale_by_freq, return_line=return_line, - **({"data": data} if data is not None else {}), **kwargs) + x, + y, + NFFT=NFFT, + Fs=Fs, + Fc=Fc, + detrend=detrend, + window=window, + noverlap=noverlap, + pad_to=pad_to, + sides=sides, + scale_by_freq=scale_by_freq, + return_line=return_line, + **({"data": data} if data is not None else {}), + **kwargs, + ) + + +# Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@_copy_docstring_and_deprecators(Axes.ecdf) +@set_category(CATEGORY_CUT) +def ecdf( + x: ArrayLike, + weights: ArrayLike | None = None, + *, + complementary: bool = False, + orientation: Literal["vertical", "horizonatal"] = "vertical", + compress: bool = False, + data=None, + **kwargs, +) -> Line2D: + return gca().ecdf( + x, + weights=weights, + complementary=complementary, + orientation=orientation, + compress=compress, + **({"data": data} if data is not None else {}), + **kwargs, + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.errorbar) @set_category(CATEGORY_CUT) def errorbar( - x, y, yerr=None, xerr=None, fmt='', ecolor=None, - elinewidth=None, capsize=None, barsabove=False, lolims=False, - uplims=False, xlolims=False, xuplims=False, errorevery=1, - capthick=None, *, data=None, **kwargs): + x: float | ArrayLike, + y: float | ArrayLike, + yerr: float | ArrayLike | None = None, + xerr: float | ArrayLike | None = None, + fmt: str = "", + ecolor: ColorType | None = None, + elinewidth: float | None = None, + capsize: float | None = None, + barsabove: bool = False, + lolims: bool | ArrayLike = False, + uplims: bool | ArrayLike = False, + xlolims: bool | ArrayLike = False, + xuplims: bool | ArrayLike = False, + errorevery: int | tuple[int, int] = 1, + capthick: float | None = None, + *, + data=None, + **kwargs, +) -> ErrorbarContainer: return gca().errorbar( - x, y, yerr=yerr, xerr=xerr, fmt=fmt, ecolor=ecolor, - elinewidth=elinewidth, capsize=capsize, barsabove=barsabove, - lolims=lolims, uplims=uplims, xlolims=xlolims, - xuplims=xuplims, errorevery=errorevery, capthick=capthick, - **({"data": data} if data is not None else {}), **kwargs) + x, + y, + yerr=yerr, + xerr=xerr, + fmt=fmt, + ecolor=ecolor, + elinewidth=elinewidth, + capsize=capsize, + barsabove=barsabove, + lolims=lolims, + uplims=uplims, + xlolims=xlolims, + xuplims=xuplims, + errorevery=errorevery, + capthick=capthick, + **({"data": data} if data is not None else {}), + **kwargs, + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.eventplot) @set_category(CATEGORY_CUT) def eventplot( - positions, orientation='horizontal', lineoffsets=1, - linelengths=1, linewidths=None, colors=None, alpha=None, - linestyles='solid', *, data=None, **kwargs): + positions: ArrayLike | Sequence[ArrayLike], + orientation: Literal["horizontal", "vertical"] = "horizontal", + lineoffsets: float | Sequence[float] = 1, + linelengths: float | Sequence[float] = 1, + linewidths: float | Sequence[float] | None = None, + colors: ColorType | Sequence[ColorType] | None = None, + alpha: float | Sequence[float] | None = None, + linestyles: LineStyleType | Sequence[LineStyleType] = "solid", + *, + data=None, + **kwargs, +) -> EventCollection: return gca().eventplot( - positions, orientation=orientation, lineoffsets=lineoffsets, - linelengths=linelengths, linewidths=linewidths, colors=colors, - alpha=alpha, linestyles=linestyles, - **({"data": data} if data is not None else {}), **kwargs) + positions, + orientation=orientation, + lineoffsets=lineoffsets, + linelengths=linelengths, + linewidths=linewidths, + colors=colors, + alpha=alpha, + linestyles=linestyles, + **({"data": data} if data is not None else {}), + **kwargs, + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.fill) @set_category(CATEGORY_CUT) -def fill(*args, data=None, **kwargs): - return gca().fill( - *args, **({"data": data} if data is not None else {}), - **kwargs) +def fill(*args, data=None, **kwargs) -> list[Polygon]: + return gca().fill(*args, **({"data": data} if data is not None else {}), **kwargs) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.fill_between) @set_category(CATEGORY_CUT) def fill_between( - x, y1, y2=0, where=None, interpolate=False, step=None, *, - data=None, **kwargs): + x: ArrayLike, + y1: ArrayLike | float, + y2: ArrayLike | float = 0, + where: Sequence[bool] | None = None, + interpolate: bool = False, + step: Literal["pre", "post", "mid"] | None = None, + *, + data=None, + **kwargs, +) -> PolyCollection: return gca().fill_between( - x, y1, y2=y2, where=where, interpolate=interpolate, step=step, - **({"data": data} if data is not None else {}), **kwargs) + x, + y1, + y2=y2, + where=where, + interpolate=interpolate, + step=step, + **({"data": data} if data is not None else {}), + **kwargs, + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.fill_betweenx) @set_category(CATEGORY_CUT) def fill_betweenx( - y, x1, x2=0, where=None, step=None, interpolate=False, *, - data=None, **kwargs): + y: ArrayLike, + x1: ArrayLike | float, + x2: ArrayLike | float = 0, + where: Sequence[bool] | None = None, + step: Literal["pre", "post", "mid"] | None = None, + interpolate: bool = False, + *, + data=None, + **kwargs, +) -> PolyCollection: return gca().fill_betweenx( - y, x1, x2=x2, where=where, step=step, interpolate=interpolate, - **({"data": data} if data is not None else {}), **kwargs) + y, + x1, + x2=x2, + where=where, + step=step, + interpolate=interpolate, + **({"data": data} if data is not None else {}), + **kwargs, + ) + + +# Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@_copy_docstring_and_deprecators(Axes.grid) +@set_category(CATEGORY_CUT) +def grid( + visible: bool | None = None, + which: Literal["major", "minor", "both"] = "major", + axis: Literal["both", "x", "y"] = "both", + **kwargs, +) -> None: + gca().grid(visible=visible, which=which, axis=axis, **kwargs) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.hexbin) @set_category(CATEGORY_SLICE) def hexbin( - x, y, C=None, gridsize=100, bins=None, xscale='linear', - yscale='linear', extent=None, cmap=None, norm=None, vmin=None, - vmax=None, alpha=None, linewidths=None, edgecolors='face', - reduce_C_function=np.mean, mincnt=None, marginals=False, *, - data=None, **kwargs): + x: ArrayLike, + y: ArrayLike, + C: ArrayLike | None = None, + gridsize: int | tuple[int, int] = 100, + bins: Literal["log"] | int | Sequence[float] | None = None, + xscale: Literal["linear", "log"] = "linear", + yscale: Literal["linear", "log"] = "linear", + extent: tuple[float, float, float, float] | None = None, + cmap: str | Colormap | None = None, + norm: str | Normalize | None = None, + vmin: float | None = None, + vmax: float | None = None, + alpha: float | None = None, + linewidths: float | None = None, + edgecolors: Literal["face", "none"] | ColorType = "face", + reduce_C_function: Callable[[np.ndarray | list[float]], float] = np.mean, + mincnt: int | None = None, + marginals: bool = False, + *, + data=None, + **kwargs, +) -> PolyCollection: __ret = gca().hexbin( - x, y, C=C, gridsize=gridsize, bins=bins, xscale=xscale, - yscale=yscale, extent=extent, cmap=cmap, norm=norm, vmin=vmin, - vmax=vmax, alpha=alpha, linewidths=linewidths, - edgecolors=edgecolors, reduce_C_function=reduce_C_function, - mincnt=mincnt, marginals=marginals, - **({"data": data} if data is not None else {}), **kwargs) + x, + y, + C=C, + gridsize=gridsize, + bins=bins, + xscale=xscale, + yscale=yscale, + extent=extent, + cmap=cmap, + norm=norm, + vmin=vmin, + vmax=vmax, + alpha=alpha, + linewidths=linewidths, + edgecolors=edgecolors, + reduce_C_function=reduce_C_function, + mincnt=mincnt, + marginals=marginals, + **({"data": data} if data is not None else {}), + **kwargs, + ) sci(__ret) return __ret @@ -2402,40 +2918,102 @@ def hexbin( @_copy_docstring_and_deprecators(Axes.hist) @set_category(CATEGORY_CUT) def hist( - x, bins=None, range=None, density=False, weights=None, - cumulative=False, bottom=None, histtype='bar', align='mid', - orientation='vertical', rwidth=None, log=False, color=None, - label=None, stacked=False, *, data=None, **kwargs): + x: ArrayLike | Sequence[ArrayLike], + bins: int | Sequence[float] | str | None = None, + range: tuple[float, float] | None = None, + density: bool = False, + weights: ArrayLike | None = None, + cumulative: bool | float = False, + bottom: ArrayLike | float | None = None, + histtype: Literal["bar", "barstacked", "step", "stepfilled"] = "bar", + align: Literal["left", "mid", "right"] = "mid", + orientation: Literal["vertical", "horizontal"] = "vertical", + rwidth: float | None = None, + log: bool = False, + color: ColorType | Sequence[ColorType] | None = None, + label: str | Sequence[str] | None = None, + stacked: bool = False, + *, + data=None, + **kwargs, +) -> tuple[ + np.ndarray | list[np.ndarray], + np.ndarray, + BarContainer | Polygon | list[BarContainer | Polygon], +]: return gca().hist( - x, bins=bins, range=range, density=density, weights=weights, - cumulative=cumulative, bottom=bottom, histtype=histtype, - align=align, orientation=orientation, rwidth=rwidth, log=log, - color=color, label=label, stacked=stacked, - **({"data": data} if data is not None else {}), **kwargs) + x, + bins=bins, + range=range, + density=density, + weights=weights, + cumulative=cumulative, + bottom=bottom, + histtype=histtype, + align=align, + orientation=orientation, + rwidth=rwidth, + log=log, + color=color, + label=label, + stacked=stacked, + **({"data": data} if data is not None else {}), + **kwargs, + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.stairs) @set_category(CATEGORY_CUT) def stairs( - values, edges=None, *, orientation='vertical', baseline=0, - fill=False, data=None, **kwargs): + values: ArrayLike, + edges: ArrayLike | None = None, + *, + orientation: Literal["vertical", "horizontal"] = "vertical", + baseline: float | ArrayLike | None = 0, + fill: bool = False, + data=None, + **kwargs, +) -> StepPatch: return gca().stairs( - values, edges=edges, orientation=orientation, - baseline=baseline, fill=fill, - **({"data": data} if data is not None else {}), **kwargs) + values, + edges=edges, + orientation=orientation, + baseline=baseline, + fill=fill, + **({"data": data} if data is not None else {}), + **kwargs, + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.hist2d) @set_category(CATEGORY_SLICE) def hist2d( - x, y, bins=10, range=None, density=False, weights=None, - cmin=None, cmax=None, *, data=None, **kwargs): + x: ArrayLike, + y: ArrayLike, + bins: None | int | tuple[int, int] | ArrayLike | tuple[ArrayLike, ArrayLike] = 10, + range: ArrayLike | None = None, + density: bool = False, + weights: ArrayLike | None = None, + cmin: float | None = None, + cmax: float | None = None, + *, + data=None, + **kwargs, +) -> tuple[np.ndarray, np.ndarray, np.ndarray, QuadMesh]: __ret = gca().hist2d( - x, y, bins=bins, range=range, density=density, - weights=weights, cmin=cmin, cmax=cmax, - **({"data": data} if data is not None else {}), **kwargs) + x, + y, + bins=bins, + range=range, + density=density, + weights=weights, + cmin=cmin, + cmax=cmax, + **({"data": data} if data is not None else {}), + **kwargs, + ) sci(__ret[-1]) return __ret @@ -2444,38 +3022,94 @@ def hist2d( @_copy_docstring_and_deprecators(Axes.hlines) @set_category(CATEGORY_CUT) def hlines( - y, xmin, xmax, colors=None, linestyles='solid', label='', *, - data=None, **kwargs): + y: float | ArrayLike, + xmin: float | ArrayLike, + xmax: float | ArrayLike, + colors: ColorType | Sequence[ColorType] | None = None, + linestyles: LineStyleType = "solid", + label: str = "", + *, + data=None, + **kwargs, +) -> LineCollection: return gca().hlines( - y, xmin, xmax, colors=colors, linestyles=linestyles, - label=label, **({"data": data} if data is not None else {}), - **kwargs) + y, + xmin, + xmax, + colors=colors, + linestyles=linestyles, + label=label, + **({"data": data} if data is not None else {}), + **kwargs, + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.imshow) @set_category(CATEGORY_SLICE) def imshow( - X, cmap=None, norm=None, *, aspect=None, interpolation=None, - alpha=None, vmin=None, vmax=None, origin=None, extent=None, - interpolation_stage=None, filternorm=True, filterrad=4.0, - resample=None, url=None, data=None, **kwargs): + X: ArrayLike | PIL.Image.Image, + cmap: str | Colormap | None = None, + norm: str | Normalize | None = None, + *, + aspect: Literal["equal", "auto"] | float | None = None, + interpolation: str | None = None, + alpha: float | ArrayLike | None = None, + vmin: float | None = None, + vmax: float | None = None, + origin: Literal["upper", "lower"] | None = None, + extent: tuple[float, float, float, float] | None = None, + interpolation_stage: Literal["data", "rgba"] | None = None, + filternorm: bool = True, + filterrad: float = 4.0, + resample: bool | None = None, + url: str | None = None, + data=None, + **kwargs, +) -> AxesImage: __ret = gca().imshow( - X, cmap=cmap, norm=norm, aspect=aspect, - interpolation=interpolation, alpha=alpha, vmin=vmin, - vmax=vmax, origin=origin, extent=extent, + X, + cmap=cmap, + norm=norm, + aspect=aspect, + interpolation=interpolation, + alpha=alpha, + vmin=vmin, + vmax=vmax, + origin=origin, + extent=extent, interpolation_stage=interpolation_stage, - filternorm=filternorm, filterrad=filterrad, resample=resample, - url=url, **({"data": data} if data is not None else {}), - **kwargs) + filternorm=filternorm, + filterrad=filterrad, + resample=resample, + url=url, + **({"data": data} if data is not None else {}), + **kwargs, + ) sci(__ret) return __ret +# Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@_copy_docstring_and_deprecators(Axes.legend) +@set_category(CATEGORY_CUT) +def legend(*args, **kwargs) -> Legend: + return gca().legend(*args, **kwargs) + + +# Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@_copy_docstring_and_deprecators(Axes.locator_params) +@set_category(CATEGORY_CUT) +def locator_params( + axis: Literal["both", "x", "y"] = "both", tight: bool | None = None, **kwargs +) -> None: + gca().locator_params(axis=axis, tight=tight, **kwargs) + + # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.loglog) @set_category(CATEGORY_CUT) -def loglog(*args, **kwargs): +def loglog(*args, **kwargs) -> list[Line2D]: return gca().loglog(*args, **kwargs) @@ -2483,24 +3117,81 @@ def loglog(*args, **kwargs): @_copy_docstring_and_deprecators(Axes.magnitude_spectrum) @set_category(CATEGORY_CUT) def magnitude_spectrum( - x, Fs=None, Fc=None, window=None, pad_to=None, sides=None, - scale=None, *, data=None, **kwargs): + x: ArrayLike, + Fs: float | None = None, + Fc: int | None = None, + window: Callable[[ArrayLike], ArrayLike] | ArrayLike | None = None, + pad_to: int | None = None, + sides: Literal["default", "onesided", "twosided"] | None = None, + scale: Literal["default", "linear", "dB"] | None = None, + *, + data=None, + **kwargs, +) -> tuple[np.ndarray, np.ndarray, Line2D]: return gca().magnitude_spectrum( - x, Fs=Fs, Fc=Fc, window=window, pad_to=pad_to, sides=sides, - scale=scale, **({"data": data} if data is not None else {}), - **kwargs) + x, + Fs=Fs, + Fc=Fc, + window=window, + pad_to=pad_to, + sides=sides, + scale=scale, + **({"data": data} if data is not None else {}), + **kwargs, + ) + + +# Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@_copy_docstring_and_deprecators(Axes.margins) +@set_category(CATEGORY_CUT) +def margins( + *margins: float, + x: float | None = None, + y: float | None = None, + tight: bool | None = True, +) -> tuple[float, float] | None: + return gca().margins(*margins, x=x, y=y, tight=tight) + + +# Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@_copy_docstring_and_deprecators(Axes.minorticks_off) +@set_category(CATEGORY_CUT) +def minorticks_off() -> None: + gca().minorticks_off() + + +# Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@_copy_docstring_and_deprecators(Axes.minorticks_on) +@set_category(CATEGORY_CUT) +def minorticks_on() -> None: + gca().minorticks_on() # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.pcolor) @set_category(CATEGORY_SLICE) def pcolor( - *args, shading=None, alpha=None, norm=None, cmap=None, - vmin=None, vmax=None, data=None, **kwargs): + *args: ArrayLike, + shading: Literal["flat", "nearest", "auto"] | None = None, + alpha: float | None = None, + norm: str | Normalize | None = None, + cmap: str | Colormap | None = None, + vmin: float | None = None, + vmax: float | None = None, + data=None, + **kwargs, +) -> Collection: __ret = gca().pcolor( - *args, shading=shading, alpha=alpha, norm=norm, cmap=cmap, - vmin=vmin, vmax=vmax, - **({"data": data} if data is not None else {}), **kwargs) + *args, + shading=shading, + alpha=alpha, + norm=norm, + cmap=cmap, + vmin=vmin, + vmax=vmax, + **({"data": data} if data is not None else {}), + **kwargs, + ) sci(__ret) return __ret @@ -2509,13 +3200,29 @@ def pcolor( @_copy_docstring_and_deprecators(Axes.pcolormesh) @set_category(CATEGORY_SLICE) def pcolormesh( - *args, alpha=None, norm=None, cmap=None, vmin=None, - vmax=None, shading=None, antialiased=False, data=None, - **kwargs): + *args: ArrayLike, + alpha: float | None = None, + norm: str | Normalize | None = None, + cmap: str | Colormap | None = None, + vmin: float | None = None, + vmax: float | None = None, + shading: Literal["flat", "nearest", "gouraud", "auto"] | None = None, + antialiased: bool = False, + data=None, + **kwargs, +) -> QuadMesh: __ret = gca().pcolormesh( - *args, alpha=alpha, norm=norm, cmap=cmap, vmin=vmin, - vmax=vmax, shading=shading, antialiased=antialiased, - **({"data": data} if data is not None else {}), **kwargs) + *args, + alpha=alpha, + norm=norm, + cmap=cmap, + vmin=vmin, + vmax=vmax, + shading=shading, + antialiased=antialiased, + **({"data": data} if data is not None else {}), + **kwargs, + ) sci(__ret) return __ret @@ -2524,73 +3231,166 @@ def pcolormesh( @_copy_docstring_and_deprecators(Axes.phase_spectrum) @set_category(CATEGORY_CUT) def phase_spectrum( - x, Fs=None, Fc=None, window=None, pad_to=None, sides=None, *, - data=None, **kwargs): + x: ArrayLike, + Fs: float | None = None, + Fc: int | None = None, + window: Callable[[ArrayLike], ArrayLike] | ArrayLike | None = None, + pad_to: int | None = None, + sides: Literal["default", "onesided", "twosided"] | None = None, + *, + data=None, + **kwargs, +) -> tuple[np.ndarray, np.ndarray, Line2D]: return gca().phase_spectrum( - x, Fs=Fs, Fc=Fc, window=window, pad_to=pad_to, sides=sides, - **({"data": data} if data is not None else {}), **kwargs) + x, + Fs=Fs, + Fc=Fc, + window=window, + pad_to=pad_to, + sides=sides, + **({"data": data} if data is not None else {}), + **kwargs, + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.pie) @set_category(CATEGORY_CUT) def pie( - x, explode=None, labels=None, colors=None, autopct=None, - pctdistance=0.6, shadow=False, labeldistance=1.1, - startangle=0, radius=1, counterclock=True, wedgeprops=None, - textprops=None, center=(0, 0), frame=False, - rotatelabels=False, *, normalize=True, hatch=None, data=None): + x: ArrayLike, + explode: ArrayLike | None = None, + labels: Sequence[str] | None = None, + colors: ColorType | Sequence[ColorType] | None = None, + autopct: str | Callable[[float], str] | None = None, + pctdistance: float = 0.6, + shadow: bool = False, + labeldistance: float | None = 1.1, + startangle: float = 0, + radius: float = 1, + counterclock: bool = True, + wedgeprops: dict[str, Any] | None = None, + textprops: dict[str, Any] | None = None, + center: tuple[float, float] = (0, 0), + frame: bool = False, + rotatelabels: bool = False, + *, + normalize: bool = True, + hatch: str | Sequence[str] | None = None, + data=None, +) -> tuple[list[Wedge], list[Text]] | tuple[list[Wedge], list[Text], list[Text]]: return gca().pie( - x, explode=explode, labels=labels, colors=colors, - autopct=autopct, pctdistance=pctdistance, shadow=shadow, - labeldistance=labeldistance, startangle=startangle, - radius=radius, counterclock=counterclock, - wedgeprops=wedgeprops, textprops=textprops, center=center, - frame=frame, rotatelabels=rotatelabels, normalize=normalize, - hatch=hatch, **({"data": data} if data is not None else {})) + x, + explode=explode, + labels=labels, + colors=colors, + autopct=autopct, + pctdistance=pctdistance, + shadow=shadow, + labeldistance=labeldistance, + startangle=startangle, + radius=radius, + counterclock=counterclock, + wedgeprops=wedgeprops, + textprops=textprops, + center=center, + frame=frame, + rotatelabels=rotatelabels, + normalize=normalize, + hatch=hatch, + **({"data": data} if data is not None else {}), + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.plot) @set_category(CATEGORY_CUT) -def plot(*args, scalex=True, scaley=True, data=None, **kwargs): +def plot( + *args: float | ArrayLike | str, + scalex: bool = True, + scaley: bool = True, + data=None, + **kwargs, +) -> list[Line2D]: return gca().plot( - *args, scalex=scalex, scaley=scaley, - **({"data": data} if data is not None else {}), **kwargs) + *args, + scalex=scalex, + scaley=scaley, + **({"data": data} if data is not None else {}), + **kwargs, + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.plot_date) @set_category(CATEGORY_CUT) def plot_date( - x, y, fmt='o', tz=None, xdate=True, ydate=False, *, - data=None, **kwargs): + x: ArrayLike, + y: ArrayLike, + fmt: str = "o", + tz: str | datetime.tzinfo | None = None, + xdate: bool = True, + ydate: bool = False, + *, + data=None, + **kwargs, +) -> list[Line2D]: return gca().plot_date( - x, y, fmt=fmt, tz=tz, xdate=xdate, ydate=ydate, - **({"data": data} if data is not None else {}), **kwargs) + x, + y, + fmt=fmt, + tz=tz, + xdate=xdate, + ydate=ydate, + **({"data": data} if data is not None else {}), + **kwargs, + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.psd) @set_category(CATEGORY_CUT) def psd( - x, NFFT=None, Fs=None, Fc=None, detrend=None, window=None, - noverlap=None, pad_to=None, sides=None, scale_by_freq=None, - return_line=None, *, data=None, **kwargs): + x: ArrayLike, + NFFT: int | None = None, + Fs: float | None = None, + Fc: int | None = None, + detrend: ( + Literal["none", "mean", "linear"] | Callable[[ArrayLike], ArrayLike] | None + ) = None, + window: Callable[[ArrayLike], ArrayLike] | ArrayLike | None = None, + noverlap: int | None = None, + pad_to: int | None = None, + sides: Literal["default", "onesided", "twosided"] | None = None, + scale_by_freq: bool | None = None, + return_line: bool | None = None, + *, + data=None, + **kwargs, +) -> tuple[np.ndarray, np.ndarray] | tuple[np.ndarray, np.ndarray, Line2D]: return gca().psd( - x, NFFT=NFFT, Fs=Fs, Fc=Fc, detrend=detrend, window=window, - noverlap=noverlap, pad_to=pad_to, sides=sides, - scale_by_freq=scale_by_freq, return_line=return_line, - **({"data": data} if data is not None else {}), **kwargs) + x, + NFFT=NFFT, + Fs=Fs, + Fc=Fc, + detrend=detrend, + window=window, + noverlap=noverlap, + pad_to=pad_to, + sides=sides, + scale_by_freq=scale_by_freq, + return_line=return_line, + **({"data": data} if data is not None else {}), + **kwargs, + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.quiver) @set_category(CATEGORY_SLICE) -def quiver(*args, data=None, **kwargs): +def quiver(*args, data=None, **kwargs) -> Quiver: __ret = gca().quiver( - *args, **({"data": data} if data is not None else {}), - **kwargs) + *args, **({"data": data} if data is not None else {}), **kwargs + ) sci(__ret) return __ret @@ -2598,7 +3398,9 @@ def quiver(*args, data=None, **kwargs): # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.quiverkey) @set_category(CATEGORY_CUT) -def quiverkey(Q, X, Y, U, label, **kwargs): +def quiverkey( + Q: Quiver, X: float, Y: float, U: float, label: str, **kwargs +) -> QuiverKey: return gca().quiverkey(Q, X, Y, U, label, **kwargs) @@ -2606,14 +3408,40 @@ def quiverkey(Q, X, Y, U, label, **kwargs): @_copy_docstring_and_deprecators(Axes.scatter) @set_category(CATEGORY_SLICE) def scatter( - x, y, s=None, c=None, marker=None, cmap=None, norm=None, - vmin=None, vmax=None, alpha=None, linewidths=None, *, - edgecolors=None, plotnonfinite=False, data=None, **kwargs): + x: float | ArrayLike, + y: float | ArrayLike, + s: float | ArrayLike | None = None, + c: ArrayLike | Sequence[ColorType] | ColorType | None = None, + marker: MarkerType | None = None, + cmap: str | Colormap | None = None, + norm: str | Normalize | None = None, + vmin: float | None = None, + vmax: float | None = None, + alpha: float | None = None, + linewidths: float | Sequence[float] | None = None, + *, + edgecolors: Literal["face", "none"] | ColorType | Sequence[ColorType] | None = None, + plotnonfinite: bool = False, + data=None, + **kwargs, +) -> PathCollection: __ret = gca().scatter( - x, y, s=s, c=c, marker=marker, cmap=cmap, norm=norm, - vmin=vmin, vmax=vmax, alpha=alpha, linewidths=linewidths, - edgecolors=edgecolors, plotnonfinite=plotnonfinite, - **({"data": data} if data is not None else {}), **kwargs) + x, + y, + s=s, + c=c, + marker=marker, + cmap=cmap, + norm=norm, + vmin=vmin, + vmax=vmax, + alpha=alpha, + linewidths=linewidths, + edgecolors=edgecolors, + plotnonfinite=plotnonfinite, + **({"data": data} if data is not None else {}), + **kwargs, + ) sci(__ret) return __ret @@ -2621,14 +3449,14 @@ def scatter( # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.semilogx) @set_category(CATEGORY_CUT) -def semilogx(*args, **kwargs): +def semilogx(*args, **kwargs) -> list[Line2D]: return gca().semilogx(*args, **kwargs) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.semilogy) @set_category(CATEGORY_CUT) -def semilogy(*args, **kwargs): +def semilogy(*args, **kwargs) -> list[Line2D]: return gca().semilogy(*args, **kwargs) @@ -2636,16 +3464,48 @@ def semilogy(*args, **kwargs): @_copy_docstring_and_deprecators(Axes.specgram) @set_category(CATEGORY_SLICE) def specgram( - x, NFFT=None, Fs=None, Fc=None, detrend=None, window=None, - noverlap=None, cmap=None, xextent=None, pad_to=None, - sides=None, scale_by_freq=None, mode=None, scale=None, - vmin=None, vmax=None, *, data=None, **kwargs): + x: ArrayLike, + NFFT: int | None = None, + Fs: float | None = None, + Fc: int | None = None, + detrend: ( + Literal["none", "mean", "linear"] | Callable[[ArrayLike], ArrayLike] | None + ) = None, + window: Callable[[ArrayLike], ArrayLike] | ArrayLike | None = None, + noverlap: int | None = None, + cmap: str | Colormap | None = None, + xextent: tuple[float, float] | None = None, + pad_to: int | None = None, + sides: Literal["default", "onesided", "twosided"] | None = None, + scale_by_freq: bool | None = None, + mode: Literal["default", "psd", "magnitude", "angle", "phase"] | None = None, + scale: Literal["default", "linear", "dB"] | None = None, + vmin: float | None = None, + vmax: float | None = None, + *, + data=None, + **kwargs, +) -> tuple[np.ndarray, np.ndarray, np.ndarray, AxesImage]: __ret = gca().specgram( - x, NFFT=NFFT, Fs=Fs, Fc=Fc, detrend=detrend, window=window, - noverlap=noverlap, cmap=cmap, xextent=xextent, pad_to=pad_to, - sides=sides, scale_by_freq=scale_by_freq, mode=mode, - scale=scale, vmin=vmin, vmax=vmax, - **({"data": data} if data is not None else {}), **kwargs) + x, + NFFT=NFFT, + Fs=Fs, + Fc=Fc, + detrend=detrend, + window=window, + noverlap=noverlap, + cmap=cmap, + xextent=xextent, + pad_to=pad_to, + sides=sides, + scale_by_freq=scale_by_freq, + mode=mode, + scale=scale, + vmin=vmin, + vmax=vmax, + **({"data": data} if data is not None else {}), + **kwargs, + ) sci(__ret[-1]) return __ret @@ -2653,67 +3513,196 @@ def specgram( # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.stackplot) @set_category(CATEGORY_CUT) -def stackplot( - x, *args, labels=(), colors=None, baseline='zero', data=None, - **kwargs): +def stackplot(x, *args, labels=(), colors=None, baseline="zero", data=None, **kwargs): return gca().stackplot( - x, *args, labels=labels, colors=colors, baseline=baseline, - **({"data": data} if data is not None else {}), **kwargs) + x, + *args, + labels=labels, + colors=colors, + baseline=baseline, + **({"data": data} if data is not None else {}), + **kwargs, + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.stem) @set_category(CATEGORY_CUT) def stem( - *args, linefmt=None, markerfmt=None, basefmt=None, bottom=0, - label=None, - use_line_collection=_api.deprecation._deprecated_parameter, - orientation='vertical', data=None): + *args: ArrayLike | str, + linefmt: str | None = None, + markerfmt: str | None = None, + basefmt: str | None = None, + bottom: float = 0, + label: str | None = None, + orientation: Literal["vertical", "horizontal"] = "vertical", + data=None, +) -> StemContainer: return gca().stem( - *args, linefmt=linefmt, markerfmt=markerfmt, basefmt=basefmt, - bottom=bottom, label=label, - use_line_collection=use_line_collection, + *args, + linefmt=linefmt, + markerfmt=markerfmt, + basefmt=basefmt, + bottom=bottom, + label=label, orientation=orientation, - **({"data": data} if data is not None else {})) + **({"data": data} if data is not None else {}), + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.step) @set_category(CATEGORY_CUT) -def step(x, y, *args, where='pre', data=None, **kwargs): +def step( + x: ArrayLike, + y: ArrayLike, + *args, + where: Literal["pre", "post", "mid"] = "pre", + data=None, + **kwargs, +) -> list[Line2D]: return gca().step( - x, y, *args, where=where, - **({"data": data} if data is not None else {}), **kwargs) + x, + y, + *args, + where=where, + **({"data": data} if data is not None else {}), + **kwargs, + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.streamplot) @set_category(CATEGORY_SLICE) def streamplot( - x, y, u, v, density=1, linewidth=None, color=None, cmap=None, - norm=None, arrowsize=1, arrowstyle='-|>', minlength=0.1, - transform=None, zorder=None, start_points=None, maxlength=4.0, - integration_direction='both', broken_streamlines=True, *, - data=None): + x, + y, + u, + v, + density=1, + linewidth=None, + color=None, + cmap=None, + norm=None, + arrowsize=1, + arrowstyle="-|>", + minlength=0.1, + transform=None, + zorder=None, + start_points=None, + maxlength=4.0, + integration_direction="both", + broken_streamlines=True, + *, + data=None, +): __ret = gca().streamplot( - x, y, u, v, density=density, linewidth=linewidth, color=color, - cmap=cmap, norm=norm, arrowsize=arrowsize, - arrowstyle=arrowstyle, minlength=minlength, - transform=transform, zorder=zorder, start_points=start_points, + x, + y, + u, + v, + density=density, + linewidth=linewidth, + color=color, + cmap=cmap, + norm=norm, + arrowsize=arrowsize, + arrowstyle=arrowstyle, + minlength=minlength, + transform=transform, + zorder=zorder, + start_points=start_points, maxlength=maxlength, integration_direction=integration_direction, broken_streamlines=broken_streamlines, - **({"data": data} if data is not None else {})) + **({"data": data} if data is not None else {}), + ) sci(__ret.lines) return __ret +# Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@_copy_docstring_and_deprecators(Axes.table) +@set_category(CATEGORY_CUT) +def table( + cellText=None, + cellColours=None, + cellLoc="right", + colWidths=None, + rowLabels=None, + rowColours=None, + rowLoc="left", + colLabels=None, + colColours=None, + colLoc="center", + loc="bottom", + bbox=None, + edges="closed", + **kwargs, +): + return gca().table( + cellText=cellText, + cellColours=cellColours, + cellLoc=cellLoc, + colWidths=colWidths, + rowLabels=rowLabels, + rowColours=rowColours, + rowLoc=rowLoc, + colLabels=colLabels, + colColours=colColours, + colLoc=colLoc, + loc=loc, + bbox=bbox, + edges=edges, + **kwargs, + ) + + +# Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@_copy_docstring_and_deprecators(Axes.text) +@set_category(CATEGORY_CUT) +def text( + x: float, y: float, s: str, fontdict: dict[str, Any] | None = None, **kwargs +) -> Text: + return gca().text(x, y, s, fontdict=fontdict, **kwargs) + + +# Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@_copy_docstring_and_deprecators(Axes.tick_params) +@set_category(CATEGORY_CUT) +def tick_params(axis: Literal["both", "x", "y"] = "both", **kwargs) -> None: + gca().tick_params(axis=axis, **kwargs) + + +# Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@_copy_docstring_and_deprecators(Axes.ticklabel_format) +@set_category(CATEGORY_CUT) +def ticklabel_format( + *, + axis: Literal["both", "x", "y"] = "both", + style: Literal["", "sci", "scientific", "plain"] = "", + scilimits: tuple[int, int] | None = None, + useOffset: bool | float | None = None, + useLocale: bool | None = None, + useMathText: bool | None = None, +) -> None: + gca().ticklabel_format( + axis=axis, + style=style, + scilimits=scilimits, + useOffset=useOffset, + useLocale=useLocale, + useMathText=useMathText, + ) + + # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.tricontour) @set_category(CATEGORY_SLICE) def tricontour(*args, **kwargs): __ret = gca().tricontour(*args, **kwargs) - if __ret._A is not None: sci(__ret) # noqa + if __ret._A is not None: # type: ignore[attr-defined] + sci(__ret) return __ret @@ -2722,7 +3711,8 @@ def tricontour(*args, **kwargs): @set_category(CATEGORY_SLICE) def tricontourf(*args, **kwargs): __ret = gca().tricontourf(*args, **kwargs) - if __ret._A is not None: sci(__ret) # noqa + if __ret._A is not None: # type: ignore[attr-defined] + sci(__ret) return __ret @@ -2730,11 +3720,27 @@ def tricontourf(*args, **kwargs): @_copy_docstring_and_deprecators(Axes.tripcolor) @set_category(CATEGORY_SLICE) def tripcolor( - *args, alpha=1.0, norm=None, cmap=None, vmin=None, vmax=None, - shading='flat', facecolors=None, **kwargs): + *args, + alpha=1.0, + norm=None, + cmap=None, + vmin=None, + vmax=None, + shading="flat", + facecolors=None, + **kwargs, +): __ret = gca().tripcolor( - *args, alpha=alpha, norm=norm, cmap=cmap, vmin=vmin, - vmax=vmax, shading=shading, facecolors=facecolors, **kwargs) + *args, + alpha=alpha, + norm=norm, + cmap=cmap, + vmin=vmin, + vmax=vmax, + shading=shading, + facecolors=facecolors, + **kwargs, + ) sci(__ret) return __ret @@ -2750,390 +3756,600 @@ def triplot(*args, **kwargs): @_copy_docstring_and_deprecators(Axes.violinplot) @set_category(CATEGORY_CUT) def violinplot( - dataset, positions=None, vert=True, widths=0.5, - showmeans=False, showextrema=True, showmedians=False, - quantiles=None, points=100, bw_method=None, *, data=None): + dataset: ArrayLike | Sequence[ArrayLike], + positions: ArrayLike | None = None, + vert: bool = True, + widths: float | ArrayLike = 0.5, + showmeans: bool = False, + showextrema: bool = True, + showmedians: bool = False, + quantiles: Sequence[float | Sequence[float]] | None = None, + points: int = 100, + bw_method: ( + Literal["scott", "silverman"] | float | Callable[[GaussianKDE], float] | None + ) = None, + *, + data=None, +) -> dict[str, Collection]: return gca().violinplot( - dataset, positions=positions, vert=vert, widths=widths, - showmeans=showmeans, showextrema=showextrema, - showmedians=showmedians, quantiles=quantiles, points=points, + dataset, + positions=positions, + vert=vert, + widths=widths, + showmeans=showmeans, + showextrema=showextrema, + showmedians=showmedians, + quantiles=quantiles, + points=points, bw_method=bw_method, - **({"data": data} if data is not None else {})) + **({"data": data} if data is not None else {}), + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.vlines) @set_category(CATEGORY_CUT) def vlines( - x, ymin, ymax, colors=None, linestyles='solid', label='', *, - data=None, **kwargs): + x: float | ArrayLike, + ymin: float | ArrayLike, + ymax: float | ArrayLike, + colors: ColorType | Sequence[ColorType] | None = None, + linestyles: LineStyleType = "solid", + label: str = "", + *, + data=None, + **kwargs, +) -> LineCollection: return gca().vlines( - x, ymin, ymax, colors=colors, linestyles=linestyles, - label=label, **({"data": data} if data is not None else {}), - **kwargs) + x, + ymin, + ymax, + colors=colors, + linestyles=linestyles, + label=label, + **({"data": data} if data is not None else {}), + **kwargs, + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.xcorr) @set_category(CATEGORY_CUT) def xcorr( - x, y, normed=True, detrend=mlab.detrend_none, usevlines=True, - maxlags=10, *, data=None, **kwargs): + x: ArrayLike, + y: ArrayLike, + normed: bool = True, + detrend: Callable[[ArrayLike], ArrayLike] = mlab.detrend_none, + usevlines: bool = True, + maxlags: int = 10, + *, + data=None, + **kwargs, +) -> tuple[np.ndarray, np.ndarray, LineCollection | Line2D, Line2D | None]: return gca().xcorr( - x, y, normed=normed, detrend=detrend, usevlines=usevlines, + x, + y, + normed=normed, + detrend=detrend, + usevlines=usevlines, maxlags=maxlags, - **({"data": data} if data is not None else {}), **kwargs) + **({"data": data} if data is not None else {}), + **kwargs, + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. -@_copy_docstring_and_deprecators(Axes.cla) -def cla(): - return gca().cla() +@_copy_docstring_and_deprecators(Axes._sci) +@set_category(CATEGORY_CUT) +def sci(im: ScalarMappable) -> None: + gca()._sci(im) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. -@_copy_docstring_and_deprecators(Axes.grid) -def grid(visible=None, which='major', axis='both', **kwargs): - return gca().grid(visible=visible, which=which, axis=axis, **kwargs) +@_copy_docstring_and_deprecators(Axes.set_title) +@set_category(CATEGORY_CUT) +def title( + label: str, + fontdict: dict[str, Any] | None = None, + loc: Literal["left", "center", "right"] | None = None, + pad: float | None = None, + *, + y: float | None = None, + **kwargs, +) -> Text: + return gca().set_title(label, fontdict=fontdict, loc=loc, pad=pad, y=y, **kwargs) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. -@_copy_docstring_and_deprecators(Axes.legend) -def legend(*args, **kwargs): - return gca().legend(*args, **kwargs) +@_copy_docstring_and_deprecators(Axes.set_xlabel) +@set_category(CATEGORY_CUT) +def xlabel( + xlabel: str, + fontdict: dict[str, Any] | None = None, + labelpad: float | None = None, + *, + loc: Literal["left", "center", "right"] | None = None, + **kwargs, +) -> Text: + return gca().set_xlabel( + xlabel, fontdict=fontdict, labelpad=labelpad, loc=loc, **kwargs + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. -@_copy_docstring_and_deprecators(Axes.table) -def table( - cellText=None, cellColours=None, cellLoc='right', - colWidths=None, rowLabels=None, rowColours=None, - rowLoc='left', colLabels=None, colColours=None, - colLoc='center', loc='bottom', bbox=None, edges='closed', - **kwargs): - return gca().table( - cellText=cellText, cellColours=cellColours, cellLoc=cellLoc, - colWidths=colWidths, rowLabels=rowLabels, - rowColours=rowColours, rowLoc=rowLoc, colLabels=colLabels, - colColours=colColours, colLoc=colLoc, loc=loc, bbox=bbox, - edges=edges, **kwargs) +@_copy_docstring_and_deprecators(Axes.set_ylabel) +@set_category(CATEGORY_CUT) +def ylabel( + ylabel: str, + fontdict: dict[str, Any] | None = None, + labelpad: float | None = None, + *, + loc: Literal["bottom", "center", "top"] | None = None, + **kwargs, +) -> Text: + return gca().set_ylabel( + ylabel, fontdict=fontdict, labelpad=labelpad, loc=loc, **kwargs + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. -@_copy_docstring_and_deprecators(Axes.text) -def text(x, y, s, fontdict=None, **kwargs): - return gca().text(x, y, s, fontdict=fontdict, **kwargs) +@_copy_docstring_and_deprecators(Axes.set_xscale) +@set_category(CATEGORY_CUT) +def xscale(value: str | ScaleBase, **kwargs) -> None: + gca().set_xscale(value, **kwargs) + + +# Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@_copy_docstring_and_deprecators(Axes.set_yscale) +@set_category(CATEGORY_CUT) +def yscale(value: str | ScaleBase, **kwargs) -> None: + gca().set_yscale(value, **kwargs) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.annotate) def annotate( - text, xy, xytext=None, xycoords='data', textcoords=None, - arrowprops=None, annotation_clip=None, **kwargs): + text: str, + xy: tuple[float, float], + xytext: tuple[float, float] | None = None, + xycoords: ( + str + | Artist + | Transform + | Callable[[RendererBase], Bbox | Transform] + | tuple[float, float] + ) = "data", + textcoords: ( + str + | Artist + | Transform + | Callable[[RendererBase], Bbox | Transform] + | tuple[float, float] + | None + ) = None, + arrowprops: dict[str, Any] | None = None, + annotation_clip: bool | None = None, + **kwargs, +) -> Annotation: return gca().annotate( - text, xy, xytext=xytext, xycoords=xycoords, - textcoords=textcoords, arrowprops=arrowprops, - annotation_clip=annotation_clip, **kwargs) + text, + xy, + xytext=xytext, + xycoords=xycoords, + textcoords=textcoords, + arrowprops=arrowprops, + annotation_clip=annotation_clip, + **kwargs, + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. -@_copy_docstring_and_deprecators(Axes.ticklabel_format) -def ticklabel_format( - *, axis='both', style='', scilimits=None, useOffset=None, - useLocale=None, useMathText=None): - return gca().ticklabel_format( - axis=axis, style=style, scilimits=scilimits, - useOffset=useOffset, useLocale=useLocale, - useMathText=useMathText) +@_copy_docstring_and_deprecators(Axes.autoscale) +def autoscale( + enable: bool = True, + axis: Literal["both", "x", "y"] = "both", + tight: bool | None = None, +) -> None: + gca().autoscale(enable=enable, axis=axis, tight=tight) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. -@_copy_docstring_and_deprecators(Axes.locator_params) -def locator_params(axis='both', tight=None, **kwargs): - return gca().locator_params(axis=axis, tight=tight, **kwargs) +@_copy_docstring_and_deprecators(Axes.axis) +def axis( + arg: tuple[float, float, float, float] | bool | str | None = None, + /, + *, + emit: bool = True, + **kwargs, +) -> tuple[float, float, float, float]: + return gca().axis(arg, emit=emit, **kwargs) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. -@_copy_docstring_and_deprecators(Axes.tick_params) -def tick_params(axis='both', **kwargs): - return gca().tick_params(axis=axis, **kwargs) +@_copy_docstring_and_deprecators(Axes.grid) +def grid( + visible: bool | None = None, + which: Literal["major", "minor", "both"] = "major", + axis: Literal["both", "x", "y"] = "both", + **kwargs, +) -> None: + gca().grid(visible=visible, which=which, axis=axis, **kwargs) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. -@_copy_docstring_and_deprecators(Axes.margins) -def margins(*margins, x=None, y=None, tight=True): - return gca().margins(*margins, x=x, y=y, tight=tight) +@_copy_docstring_and_deprecators(Axes.legend) +def legend(*args, **kwargs) -> Legend: + return gca().legend(*args, **kwargs) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. -@_copy_docstring_and_deprecators(Axes.autoscale) -def autoscale(enable=True, axis='both', tight=None): - return gca().autoscale(enable=enable, axis=axis, tight=tight) +@_copy_docstring_and_deprecators(Axes.locator_params) +def locator_params( + axis: Literal["both", "x", "y"] = "both", tight: bool | None = None, **kwargs +) -> None: + gca().locator_params(axis=axis, tight=tight, **kwargs) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. -@_copy_docstring_and_deprecators(Axes.axis) -def axis(arg=None, /, *, emit=True, **kwargs): - return gca().axis(arg, emit=emit, **kwargs) +@_copy_docstring_and_deprecators(Axes.margins) +def margins( + *margins: float, + x: float | None = None, + y: float | None = None, + tight: bool | None = True, +) -> tuple[float, float] | None: + return gca().margins(*margins, x=x, y=y, tight=tight) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.minorticks_off) -def minorticks_off(): - return gca().minorticks_off() +def minorticks_off() -> None: + gca().minorticks_off() # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.minorticks_on) -def minorticks_on(): - return gca().minorticks_on() +def minorticks_on() -> None: + gca().minorticks_on() + + +# Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@_copy_docstring_and_deprecators(Axes.table) +def table( + cellText=None, + cellColours=None, + cellLoc="right", + colWidths=None, + rowLabels=None, + rowColours=None, + rowLoc="left", + colLabels=None, + colColours=None, + colLoc="center", + loc="bottom", + bbox=None, + edges="closed", + **kwargs, +): + return gca().table( + cellText=cellText, + cellColours=cellColours, + cellLoc=cellLoc, + colWidths=colWidths, + rowLabels=rowLabels, + rowColours=rowColours, + rowLoc=rowLoc, + colLabels=colLabels, + colColours=colColours, + colLoc=colLoc, + loc=loc, + bbox=bbox, + edges=edges, + **kwargs, + ) + + +# Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@_copy_docstring_and_deprecators(Axes.text) +def text( + x: float, y: float, s: str, fontdict: dict[str, Any] | None = None, **kwargs +) -> Text: + return gca().text(x, y, s, fontdict=fontdict, **kwargs) + + +# Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@_copy_docstring_and_deprecators(Axes.ticklabel_format) +def ticklabel_format( + *, + axis: Literal["both", "x", "y"] = "both", + style: Literal["", "sci", "scientific", "plain"] = "", + scilimits: tuple[int, int] | None = None, + useOffset: bool | float | None = None, + useLocale: bool | None = None, + useMathText: bool | None = None, +) -> None: + gca().ticklabel_format( + axis=axis, + style=style, + scilimits=scilimits, + useOffset=useOffset, + useLocale=useLocale, + useMathText=useMathText, + ) + + +# Autogenerated by boilerplate.py. Do not edit as changes will be lost. +@_copy_docstring_and_deprecators(Axes.tick_params) +def tick_params(axis: Literal["both", "x", "y"] = "both", **kwargs) -> None: + gca().tick_params(axis=axis, **kwargs) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes._sci) -def sci(im): - return gca()._sci(im) +def sci(im: ScalarMappable) -> None: + gca()._sci(im) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.set_title) -def title(label, fontdict=None, loc=None, pad=None, *, y=None, **kwargs): - return gca().set_title( - label, fontdict=fontdict, loc=loc, pad=pad, y=y, **kwargs) +def title( + label: str, + fontdict: dict[str, Any] | None = None, + loc: Literal["left", "center", "right"] | None = None, + pad: float | None = None, + *, + y: float | None = None, + **kwargs, +) -> Text: + return gca().set_title(label, fontdict=fontdict, loc=loc, pad=pad, y=y, **kwargs) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.set_xlabel) -def xlabel(xlabel, fontdict=None, labelpad=None, *, loc=None, **kwargs): +def xlabel( + xlabel: str, + fontdict: dict[str, Any] | None = None, + labelpad: float | None = None, + *, + loc: Literal["left", "center", "right"] | None = None, + **kwargs, +) -> Text: return gca().set_xlabel( - xlabel, fontdict=fontdict, labelpad=labelpad, loc=loc, - **kwargs) + xlabel, fontdict=fontdict, labelpad=labelpad, loc=loc, **kwargs + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.set_ylabel) -def ylabel(ylabel, fontdict=None, labelpad=None, *, loc=None, **kwargs): +def ylabel( + ylabel: str, + fontdict: dict[str, Any] | None = None, + labelpad: float | None = None, + *, + loc: Literal["bottom", "center", "top"] | None = None, + **kwargs, +) -> Text: return gca().set_ylabel( - ylabel, fontdict=fontdict, labelpad=labelpad, loc=loc, - **kwargs) + ylabel, fontdict=fontdict, labelpad=labelpad, loc=loc, **kwargs + ) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.set_xscale) -def xscale(value, **kwargs): - return gca().set_xscale(value, **kwargs) +def xscale(value: str | ScaleBase, **kwargs) -> None: + gca().set_xscale(value, **kwargs) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes.set_yscale) -def yscale(value, **kwargs): - return gca().set_yscale(value, **kwargs) +def yscale(value: str | ScaleBase, **kwargs) -> None: + gca().set_yscale(value, **kwargs) # Autogenerated by boilerplate.py. Do not edit as changes will be lost. -def autumn(): +def autumn() -> None: """ Set the colormap to 'autumn'. This changes the default colormap as well as the colormap of the current image if there is one. See ``help(colormaps)`` for more information. """ - set_cmap('autumn') + set_cmap("autumn") # Autogenerated by boilerplate.py. Do not edit as changes will be lost. -def bone(): +def bone() -> None: """ Set the colormap to 'bone'. This changes the default colormap as well as the colormap of the current image if there is one. See ``help(colormaps)`` for more information. """ - set_cmap('bone') + set_cmap("bone") # Autogenerated by boilerplate.py. Do not edit as changes will be lost. -def cool(): +def cool() -> None: """ Set the colormap to 'cool'. This changes the default colormap as well as the colormap of the current image if there is one. See ``help(colormaps)`` for more information. """ - set_cmap('cool') + set_cmap("cool") # Autogenerated by boilerplate.py. Do not edit as changes will be lost. -def copper(): +def copper() -> None: """ Set the colormap to 'copper'. This changes the default colormap as well as the colormap of the current image if there is one. See ``help(colormaps)`` for more information. """ - set_cmap('copper') + set_cmap("copper") # Autogenerated by boilerplate.py. Do not edit as changes will be lost. -def flag(): +def flag() -> None: """ Set the colormap to 'flag'. This changes the default colormap as well as the colormap of the current image if there is one. See ``help(colormaps)`` for more information. """ - set_cmap('flag') + set_cmap("flag") # Autogenerated by boilerplate.py. Do not edit as changes will be lost. -def gray(): +def gray() -> None: """ Set the colormap to 'gray'. This changes the default colormap as well as the colormap of the current image if there is one. See ``help(colormaps)`` for more information. """ - set_cmap('gray') + set_cmap("gray") # Autogenerated by boilerplate.py. Do not edit as changes will be lost. -def hot(): +def hot() -> None: """ Set the colormap to 'hot'. This changes the default colormap as well as the colormap of the current image if there is one. See ``help(colormaps)`` for more information. """ - set_cmap('hot') + set_cmap("hot") # Autogenerated by boilerplate.py. Do not edit as changes will be lost. -def hsv(): +def hsv() -> None: """ Set the colormap to 'hsv'. This changes the default colormap as well as the colormap of the current image if there is one. See ``help(colormaps)`` for more information. """ - set_cmap('hsv') + set_cmap("hsv") # Autogenerated by boilerplate.py. Do not edit as changes will be lost. -def jet(): +def jet() -> None: """ Set the colormap to 'jet'. This changes the default colormap as well as the colormap of the current image if there is one. See ``help(colormaps)`` for more information. """ - set_cmap('jet') + set_cmap("jet") # Autogenerated by boilerplate.py. Do not edit as changes will be lost. -def pink(): +def pink() -> None: """ Set the colormap to 'pink'. This changes the default colormap as well as the colormap of the current image if there is one. See ``help(colormaps)`` for more information. """ - set_cmap('pink') + set_cmap("pink") # Autogenerated by boilerplate.py. Do not edit as changes will be lost. -def prism(): +def prism() -> None: """ Set the colormap to 'prism'. This changes the default colormap as well as the colormap of the current image if there is one. See ``help(colormaps)`` for more information. """ - set_cmap('prism') + set_cmap("prism") # Autogenerated by boilerplate.py. Do not edit as changes will be lost. -def spring(): +def spring() -> None: """ Set the colormap to 'spring'. This changes the default colormap as well as the colormap of the current image if there is one. See ``help(colormaps)`` for more information. """ - set_cmap('spring') + set_cmap("spring") # Autogenerated by boilerplate.py. Do not edit as changes will be lost. -def summer(): +def summer() -> None: """ Set the colormap to 'summer'. This changes the default colormap as well as the colormap of the current image if there is one. See ``help(colormaps)`` for more information. """ - set_cmap('summer') + set_cmap("summer") # Autogenerated by boilerplate.py. Do not edit as changes will be lost. -def winter(): +def winter() -> None: """ Set the colormap to 'winter'. This changes the default colormap as well as the colormap of the current image if there is one. See ``help(colormaps)`` for more information. """ - set_cmap('winter') + set_cmap("winter") # Autogenerated by boilerplate.py. Do not edit as changes will be lost. -def magma(): +def magma() -> None: """ Set the colormap to 'magma'. This changes the default colormap as well as the colormap of the current image if there is one. See ``help(colormaps)`` for more information. """ - set_cmap('magma') + set_cmap("magma") # Autogenerated by boilerplate.py. Do not edit as changes will be lost. -def inferno(): +def inferno() -> None: """ Set the colormap to 'inferno'. This changes the default colormap as well as the colormap of the current image if there is one. See ``help(colormaps)`` for more information. """ - set_cmap('inferno') + set_cmap("inferno") # Autogenerated by boilerplate.py. Do not edit as changes will be lost. -def plasma(): +def plasma() -> None: """ Set the colormap to 'plasma'. This changes the default colormap as well as the colormap of the current image if there is one. See ``help(colormaps)`` for more information. """ - set_cmap('plasma') + set_cmap("plasma") # Autogenerated by boilerplate.py. Do not edit as changes will be lost. -def viridis(): +def viridis() -> None: """ Set the colormap to 'viridis'. This changes the default colormap as well as the colormap of the current image if there is one. See ``help(colormaps)`` for more information. """ - set_cmap('viridis') + set_cmap("viridis") # Autogenerated by boilerplate.py. Do not edit as changes will be lost. -def nipy_spectral(): +def nipy_spectral() -> None: """ Set the colormap to 'nipy_spectral'. This changes the default colormap as well as the colormap of the current image if there is one. See ``help(colormaps)`` for more information. """ - set_cmap('nipy_spectral') + set_cmap("nipy_spectral") diff --git a/tools/boilerplate.py b/tools/boilerplate.py index 8903c868..1de03376 100644 --- a/tools/boilerplate.py +++ b/tools/boilerplate.py @@ -1,8 +1,6 @@ """ Script to autogenerate pyplot wrappers. -This script copies the approach take by matplotlib.pyplot to generate the pyplot api. - When this script is run, the current contents of pyplot are split into generatable and non-generatable content (via the magic header :attr:`PYPLOT_MAGIC_HEADER`) and the generatable content is overwritten. @@ -15,12 +13,15 @@ # runtime with the proper signatures, a static pyplot.py is simpler for static # analysis tools to parse. +import ast from enum import Enum +import functools import inspect from inspect import Parameter from pathlib import Path import sys -import textwrap +import subprocess + # This line imports the installed copy of matplotlib, and not the local copy. import numpy as np @@ -74,23 +75,23 @@ def {name}{signature}: @_copy_docstring_and_deprecators(Axes.{called_name}) @set_category(CATEGORY_CUT) def {name}{signature}: - return gca().{called_name}{call} + {return_statement}gca().{called_name}{call} """ MISC_METHOD_TEMPLATE = AUTOGEN_MSG + """ @_copy_docstring_and_deprecators(Axes.{called_name}) def {name}{signature}: - return gca().{called_name}{call} + {return_statement}gca().{called_name}{call} """ FIGURE_METHOD_TEMPLATE = AUTOGEN_MSG + """ @_copy_docstring_and_deprecators(Figure.{called_name}) def {name}{signature}: - return gcf().{called_name}{call} + {return_statement}gcf().{called_name}{call} """ CMAP_TEMPLATE = ''' -def {name}(): +def {name}() -> None: """ Set the colormap to {name!r}. @@ -127,6 +128,17 @@ def __repr__(self): return self._repr +class direct_repr: + """ + A placeholder class to destringify annotations from ast + """ + def __init__(self, value): + self._repr = value + + def __repr__(self): + return self._repr + + def generate_function(name, called_fullname, template, **kwargs): """ Create a wrapper function *pyplot_name* calling *call_name*. @@ -149,10 +161,6 @@ def generate_function(name, called_fullname, template, **kwargs): **kwargs Additional parameters are passed to ``template.format()``. """ - text_wrapper = textwrap.TextWrapper( - break_long_words=False, width=70, - initial_indent=' ' * 8, subsequent_indent=' ' * 8) - # Get signature of wrapped function. class_name, called_name = called_fullname.split('.') class_ = {'Axes': Axes, 'Figure': Figure}[class_name] @@ -163,16 +171,17 @@ def generate_function(name, called_fullname, template, **kwargs): # redecorated with make_keyword_only by _copy_docstring_and_deprecators. if decorator and decorator.func is _api.make_keyword_only: meth = meth.__wrapped__ - signature = inspect.signature(meth) + + annotated_trees = get_ast_mro_trees(class_) + signature = get_matching_signature(meth, annotated_trees) + # Replace self argument. params = list(signature.parameters.values())[1:] + has_return_value = str(signature.return_annotation) != 'None' signature = str(signature.replace(parameters=[ param.replace(default=value_formatter(param.default)) if param.default is not param.empty else param for param in params])) - if len('def ' + name + signature) >= 80: - # Move opening parenthesis before newline. - signature = '(\n' + text_wrapper.fill(signature).replace('(', '', 1) # How to call the wrapped function. call = '(' + ', '.join(( # Pass "intended-as-positional" parameters positionally to avoid @@ -184,9 +193,6 @@ def generate_function(name, called_fullname, template, **kwargs): # Only pass the data kwarg if it is actually set, to avoid forcing # third-party subclasses to support it. '**({{"data": data}} if data is not None else {{}})' - # Avoid linebreaks in the middle of the expression, by using \0 as a - # placeholder that will be substituted after wrapping. - .replace(' ', '\0') if param.name == "data" else '{0}={0}' if param.kind in [ @@ -200,9 +206,7 @@ def generate_function(name, called_fullname, template, **kwargs): if param.kind is Parameter.VAR_KEYWORD else None).format(param.name) for param in params) + ')' - MAX_CALL_PREFIX = 18 # len(' __ret = gca().') - if MAX_CALL_PREFIX + max(len(name), len(called_name)) + len(call) >= 80: - call = '(\n' + text_wrapper.fill(call[1:]).replace('\0', ' ') + return_statement = 'return ' if has_return_value else '' # Bail out in case of name collision. for reserved in ('gca', 'gci', 'gcf', '__ret'): if reserved in params: @@ -214,6 +218,7 @@ def generate_function(name, called_fullname, template, **kwargs): called_name=called_name, signature=signature, call=call, + return_statement=return_statement, **kwargs) @@ -231,22 +236,20 @@ def boilerplate_gen(): 'tight_layout', 'waitforbuttonpress', ) - _misc_commands = ( - 'cla', + 'annotate', + 'autoscale', + 'axis', 'grid', 'legend', - 'table', - 'text', - 'annotate', - 'ticklabel_format', 'locator_params', - 'tick_params', 'margins', - 'autoscale', - 'axis', 'minorticks_off', 'minorticks_on', + 'table', + 'text', + 'ticklabel_format', + 'tick_params', # pyplot name : real name 'sci:_sci', 'title:set_title', @@ -255,14 +258,16 @@ def boilerplate_gen(): 'xscale:set_xscale', 'yscale:set_yscale', ) - # These methods are all simple wrappers of Axes methods by the same name. _axes_commands = ( 'acorr', 'angle_spectrum', + 'annotate', 'arrow', + 'autoscale', 'axhline', 'axhspan', + 'axis', 'axline', 'axvline', 'axvspan', @@ -277,19 +282,26 @@ def boilerplate_gen(): 'contour', 'contourf', 'csd', + 'ecdf', 'errorbar', 'eventplot', 'fill', 'fill_between', 'fill_betweenx', + 'grid', 'hexbin', 'hist', 'stairs', 'hist2d', 'hlines', 'imshow', + 'legend', + 'locator_params', 'loglog', 'magnitude_spectrum', + 'margins', + 'minorticks_off', + 'minorticks_on', 'pcolor', 'pcolormesh', 'phase_spectrum', @@ -308,6 +320,10 @@ def boilerplate_gen(): 'stem', 'step', 'streamplot', + 'table', + 'text', + 'tick_params', + 'ticklabel_format', 'tricontour', 'tricontourf', 'tripcolor', @@ -315,11 +331,24 @@ def boilerplate_gen(): 'violinplot', 'vlines', 'xcorr', + # pyplot name : real name + 'sci:_sci', + 'title:set_title', + 'xlabel:set_xlabel', + 'ylabel:set_ylabel', + 'xscale:set_xscale', + 'yscale:set_yscale', ) cmappable = { - 'contour': 'if __ret._A is not None: sci(__ret) # noqa', - 'contourf': 'if __ret._A is not None: sci(__ret) # noqa', + 'contour': ( + 'if __ret._A is not None: # type: ignore[attr-defined]\n' + ' sci(__ret)' + ), + 'contourf': ( + 'if __ret._A is not None: # type: ignore[attr-defined]\n' + ' sci(__ret)' + ), 'hexbin': 'sci(__ret)', 'scatter': 'sci(__ret)', 'pcolor': 'sci(__ret)', @@ -330,8 +359,14 @@ def boilerplate_gen(): 'quiver': 'sci(__ret)', 'specgram': 'sci(__ret[-1])', 'streamplot': 'sci(__ret.lines)', - 'tricontour': 'if __ret._A is not None: sci(__ret) # noqa', - 'tricontourf': 'if __ret._A is not None: sci(__ret) # noqa', + 'tricontour': ( + 'if __ret._A is not None: # type: ignore[attr-defined]\n' + ' sci(__ret)' + ), + 'tricontourf': ( + 'if __ret._A is not None: # type: ignore[attr-defined]\n' + ' sci(__ret)' + ), 'tripcolor': 'sci(__ret)', } @@ -401,6 +436,80 @@ def build_pyplot(pyplot_path): pyplot.writelines(pyplot_orig) pyplot.writelines(boilerplate_gen()) + # Run black to autoformat pyplot + subprocess.run( + [sys.executable, "-m", "black", "--line-length=88", pyplot_path], + check=True + ) + + +### Methods for retrieving signatures from pyi stub files + +def get_ast_tree(cls): + path = Path(inspect.getfile(cls)) + stubpath = path.with_suffix(".pyi") + path = stubpath if stubpath.exists() else path + tree = ast.parse(path.read_text()) + for item in tree.body: + if isinstance(item, ast.ClassDef) and item.name == cls.__name__: + return item + raise ValueError(f"Cannot find {cls.__name__} in ast") + + +@functools.lru_cache +def get_ast_mro_trees(cls): + return [get_ast_tree(c) for c in cls.__mro__ if c.__module__ != "builtins"] + + +def get_matching_signature(method, trees): + sig = inspect.signature(method) + for tree in trees: + for item in tree.body: + if not isinstance(item, ast.FunctionDef): + continue + if item.name == method.__name__: + return update_sig_from_node(item, sig) + # The following methods are implemented outside of the mro of Axes + # and thus do not get their annotated versions found with current code + # stackplot + # streamplot + # table + # tricontour + # tricontourf + # tripcolor + # triplot + + # import warnings + # warnings.warn(f"'{method.__name__}' not found") + return sig + + +def update_sig_from_node(node, sig): + params = dict(sig.parameters) + args = node.args + allargs = ( + *args.posonlyargs, + *args.args, + args.vararg, + *args.kwonlyargs, + args.kwarg, + ) + for param in allargs: + if param is None: + continue + if param.annotation is None: + continue + annotation = direct_repr(ast.unparse(param.annotation)) + params[param.arg] = params[param.arg].replace(annotation=annotation) + + if node.returns is not None: + return inspect.Signature( + params.values(), + return_annotation=direct_repr(ast.unparse(node.returns)) + ) + else: + return inspect.Signature(params.values()) + if __name__ == '__main__': # Write the matplotlib.pyplot file. From ac62be178f94348e8589543f9d65b6f95b756348 Mon Sep 17 00:00:00 2001 From: Silke Schomann Date: Mon, 11 Nov 2024 09:36:43 +0000 Subject: [PATCH 02/23] Updated matplotlib version in pyproject.toml --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 7e6bb2bf..a3e65972 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -22,7 +22,7 @@ classifiers = [ dependencies = [ "ipython", "numpy", - "matplotlib>=1.5", + "matplotlib>=3.8.4", "six", "qtawesome", "pre-commit", From 6094eab68896104e902ec3f4d03ec5ff5722e34e Mon Sep 17 00:00:00 2001 From: Silke Schomann Date: Mon, 11 Nov 2024 10:45:09 +0000 Subject: [PATCH 03/23] Import ArrayLike --- src/mslice/plotting/pyplot.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mslice/plotting/pyplot.py b/src/mslice/plotting/pyplot.py index 48947455..2e6d5959 100644 --- a/src/mslice/plotting/pyplot.py +++ b/src/mslice/plotting/pyplot.py @@ -54,6 +54,7 @@ from matplotlib.cm import get_cmap import numpy as np +from numpy.typing import ArrayLike # We may not need the following imports here: from matplotlib.colors import Normalize From 8a5d0eb124f72f70ba57a5d23507497b4e70db5f Mon Sep 17 00:00:00 2001 From: Silke Schomann Date: Mon, 11 Nov 2024 10:58:50 +0000 Subject: [PATCH 04/23] Import Colormap --- src/mslice/plotting/pyplot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mslice/plotting/pyplot.py b/src/mslice/plotting/pyplot.py index 2e6d5959..e171ca96 100644 --- a/src/mslice/plotting/pyplot.py +++ b/src/mslice/plotting/pyplot.py @@ -57,7 +57,7 @@ from numpy.typing import ArrayLike # We may not need the following imports here: -from matplotlib.colors import Normalize +from matplotlib.colors import Normalize, Colormap from matplotlib.lines import Line2D from matplotlib.text import Text, Annotation from matplotlib.patches import Polygon, Rectangle, Circle, Arrow From c7613ef64878582e76174cbe0ca1384c248daf34 Mon Sep 17 00:00:00 2001 From: Silke Schomann Date: Mon, 11 Nov 2024 11:05:34 +0000 Subject: [PATCH 05/23] Import Literal --- src/mslice/plotting/pyplot.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mslice/plotting/pyplot.py b/src/mslice/plotting/pyplot.py index e171ca96..a0492abb 100644 --- a/src/mslice/plotting/pyplot.py +++ b/src/mslice/plotting/pyplot.py @@ -20,6 +20,7 @@ import sys import threading import time +from typing import Literal from cycler import cycler import matplotlib From 96d477f576404f70050ccaff5c7786a0b1ce9cb1 Mon Sep 17 00:00:00 2001 From: Silke Schomann Date: Mon, 11 Nov 2024 11:12:33 +0000 Subject: [PATCH 06/23] Import FigureImage --- src/mslice/plotting/pyplot.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mslice/plotting/pyplot.py b/src/mslice/plotting/pyplot.py index a0492abb..2a4d4927 100644 --- a/src/mslice/plotting/pyplot.py +++ b/src/mslice/plotting/pyplot.py @@ -26,6 +26,7 @@ import matplotlib import matplotlib.colorbar import matplotlib.image +from matplotlib.image import FigureImage from matplotlib import _api from matplotlib import rcsetup, style from matplotlib import _pylab_helpers, interactive From ec9ef7c86c721bd86bee312ff669d87217450bfe Mon Sep 17 00:00:00 2001 From: Silke Schomann Date: Mon, 11 Nov 2024 11:14:12 +0000 Subject: [PATCH 07/23] Use matplotlib.image.FigureImage --- src/mslice/plotting/pyplot.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/mslice/plotting/pyplot.py b/src/mslice/plotting/pyplot.py index 2a4d4927..3fefd8b9 100644 --- a/src/mslice/plotting/pyplot.py +++ b/src/mslice/plotting/pyplot.py @@ -26,7 +26,6 @@ import matplotlib import matplotlib.colorbar import matplotlib.image -from matplotlib.image import FigureImage from matplotlib import _api from matplotlib import rcsetup, style from matplotlib import _pylab_helpers, interactive @@ -2185,7 +2184,7 @@ def figimage( origin: Literal["upper", "lower"] | None = None, resize: bool = False, **kwargs, -) -> FigureImage: +) -> matplotlib.image.FigureImage: return gcf().figimage( X, xo=xo, From dea980e3b95daf95b2921263675bf8a733e89dd8 Mon Sep 17 00:00:00 2001 From: Silke Schomann Date: Mon, 11 Nov 2024 11:46:57 +0000 Subject: [PATCH 08/23] Import Any --- src/mslice/plotting/pyplot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mslice/plotting/pyplot.py b/src/mslice/plotting/pyplot.py index 3fefd8b9..31eec7dc 100644 --- a/src/mslice/plotting/pyplot.py +++ b/src/mslice/plotting/pyplot.py @@ -20,7 +20,7 @@ import sys import threading import time -from typing import Literal +from typing import Any, Literal from cycler import cycler import matplotlib From 24fffd8d04be6049e6c08dbb8824f8d5305956eb Mon Sep 17 00:00:00 2001 From: Silke Schomann Date: Mon, 11 Nov 2024 11:51:53 +0000 Subject: [PATCH 09/23] Use matplotlib.cm.ScalarMappable --- src/mslice/plotting/pyplot.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mslice/plotting/pyplot.py b/src/mslice/plotting/pyplot.py index 31eec7dc..b97a4918 100644 --- a/src/mslice/plotting/pyplot.py +++ b/src/mslice/plotting/pyplot.py @@ -2216,7 +2216,7 @@ def gca() -> Axes: # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Figure._gci) -def gci() -> ScalarMappable | None: +def gci() -> matplotlib.cm.ScalarMappable | None: return gcf()._gci() @@ -3843,7 +3843,7 @@ def xcorr( # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes._sci) @set_category(CATEGORY_CUT) -def sci(im: ScalarMappable) -> None: +def sci(im: matplotlib.cm.ScalarMappable) -> None: gca()._sci(im) @@ -4088,7 +4088,7 @@ def tick_params(axis: Literal["both", "x", "y"] = "both", **kwargs) -> None: # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes._sci) -def sci(im: ScalarMappable) -> None: +def sci(im: matplotlib.cm.ScalarMappable) -> None: gca()._sci(im) From eaa4ac6cb4c5575bf7436cd02a35bbe953744862 Mon Sep 17 00:00:00 2001 From: Silke Schomann Date: Mon, 11 Nov 2024 12:03:13 +0000 Subject: [PATCH 10/23] Added imports for matplotlib.collections --- src/mslice/plotting/pyplot.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/mslice/plotting/pyplot.py b/src/mslice/plotting/pyplot.py index b97a4918..6dab96b1 100644 --- a/src/mslice/plotting/pyplot.py +++ b/src/mslice/plotting/pyplot.py @@ -45,6 +45,15 @@ from matplotlib.projections import PolarAxes from matplotlib import mlab # for detrend_none, window_hanning from matplotlib.scale import get_scale_names +from matplotlib.collections import ( + BrokenBarHCollection, + Collection, + EventCollection, + LineCollection, + PathCollection, + PolyCollection, + QuadMesh +) from matplotlib import cm from matplotlib.cm import _colormaps as colormaps, register_cmap From 78cf8784b0f17ab7b73eb52933259ce503d49d1b Mon Sep 17 00:00:00 2001 From: Silke Schomann Date: Mon, 11 Nov 2024 12:10:57 +0000 Subject: [PATCH 11/23] Import Callable --- src/mslice/plotting/pyplot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mslice/plotting/pyplot.py b/src/mslice/plotting/pyplot.py index 6dab96b1..830771c2 100644 --- a/src/mslice/plotting/pyplot.py +++ b/src/mslice/plotting/pyplot.py @@ -20,7 +20,7 @@ import sys import threading import time -from typing import Any, Literal +from typing import Any, Callable, Literal from cycler import cycler import matplotlib From 1127d848468368b64dd9bb1afdb78a9d3df24e86 Mon Sep 17 00:00:00 2001 From: Silke Schomann Date: Mon, 11 Nov 2024 14:52:37 +0000 Subject: [PATCH 12/23] Updated pyplot functions --- src/mslice/plotting/pyplot.py | 1082 ++++++++++++++++++++------------- 1 file changed, 645 insertions(+), 437 deletions(-) diff --git a/src/mslice/plotting/pyplot.py b/src/mslice/plotting/pyplot.py index 830771c2..d9c195a9 100644 --- a/src/mslice/plotting/pyplot.py +++ b/src/mslice/plotting/pyplot.py @@ -9,91 +9,111 @@ see globalfiguremanager.py. """ -from contextlib import ExitStack +# fmt: off + +from __future__ import annotations + +from contextlib import AbstractContextManager, ExitStack from enum import Enum import functools import importlib import inspect import logging -from numbers import Number import re import sys import threading import time -from typing import Any, Callable, Literal +from typing import cast, overload from cycler import cycler import matplotlib import matplotlib.colorbar import matplotlib.image from matplotlib import _api -from matplotlib import rcsetup, style +from matplotlib import ( # Re-exported for typing. + cm as cm, get_backend as get_backend, rcParams as rcParams, style as style) from matplotlib import _pylab_helpers, interactive from matplotlib import cbook - -try: - from matplotlib import _docstring as docstring -except ImportError: - from matplotlib import docstring -from matplotlib.backend_bases import FigureCanvasBase, MouseButton +from matplotlib import _docstring +from matplotlib.backend_bases import ( + FigureCanvasBase, FigureManagerBase, MouseButton) from matplotlib.figure import Figure, FigureBase, figaspect from matplotlib.gridspec import GridSpec, SubplotSpec -from matplotlib import rcParams, rcParamsDefault, get_backend, rcParamsOrig -from matplotlib.rcsetup import interactive_bk as _interactive_bk +from matplotlib import rcsetup, rcParamsDefault, rcParamsOrig from matplotlib.artist import Artist -from matplotlib.axes import Axes, Subplot -from matplotlib.projections import PolarAxes +from matplotlib.axes import Axes, Subplot # type: ignore +from matplotlib.projections import PolarAxes # type: ignore from matplotlib import mlab # for detrend_none, window_hanning from matplotlib.scale import get_scale_names -from matplotlib.collections import ( - BrokenBarHCollection, - Collection, - EventCollection, - LineCollection, - PathCollection, - PolyCollection, - QuadMesh -) - -from matplotlib import cm -from matplotlib.cm import _colormaps as colormaps, register_cmap -try: - from matplotlib.cm import _get_cmap as get_cmap -except ImportError: - from matplotlib.cm import get_cmap +from matplotlib.cm import _colormaps +from matplotlib.cm import register_cmap # type: ignore +from matplotlib.colors import _color_sequences import numpy as np -from numpy.typing import ArrayLike + +from typing import TYPE_CHECKING, cast + +if TYPE_CHECKING: + from collections.abc import Callable, Hashable, Iterable, Sequence + import datetime + import pathlib + import os + from typing import Any, BinaryIO, Literal, TypeVar + from typing_extensions import ParamSpec + + import PIL.Image + from numpy.typing import ArrayLike + + from matplotlib.axis import Tick + from matplotlib.axes._base import _AxesBase + from matplotlib.backend_bases import RendererBase, Event + from matplotlib.cm import ScalarMappable + from matplotlib.contour import ContourSet, QuadContourSet + from matplotlib.collections import ( + Collection, + LineCollection, + BrokenBarHCollection, + PolyCollection, + PathCollection, + EventCollection, + QuadMesh, + ) + from matplotlib.colorbar import Colorbar + from matplotlib.colors import Colormap + from matplotlib.container import ( + BarContainer, + ErrorbarContainer, + StemContainer, + ) + from matplotlib.figure import SubFigure + from matplotlib.legend import Legend + from matplotlib.mlab import GaussianKDE + from matplotlib.image import AxesImage, FigureImage + from matplotlib.patches import FancyArrow, StepPatch, Wedge + from matplotlib.quiver import Barbs, Quiver, QuiverKey + from matplotlib.scale import ScaleBase + from matplotlib.transforms import Transform, Bbox + from matplotlib.typing import ColorType, LineStyleType, MarkerType, HashableList + from matplotlib.widgets import SubplotTool + + _P = ParamSpec('_P') + _R = TypeVar('_R') + _T = TypeVar('_T') + # We may not need the following imports here: -from matplotlib.colors import Normalize, Colormap -from matplotlib.lines import Line2D +from matplotlib.colors import Normalize +from matplotlib.lines import Line2D, AxLine from matplotlib.text import Text, Annotation from matplotlib.patches import Polygon, Rectangle, Circle, Arrow from matplotlib.widgets import Button, Slider, Widget -from matplotlib.ticker import ( - TickHelper, - Formatter, - FixedFormatter, - NullFormatter, - FuncFormatter, - FormatStrFormatter, - ScalarFormatter, - LogFormatter, - LogFormatterExponent, - LogFormatterMathtext, - Locator, - IndexLocator, - FixedLocator, - NullLocator, - LinearLocator, - LogLocator, - AutoLocator, - MultipleLocator, - MaxNLocator, -) +from .ticker import ( + TickHelper, Formatter, FixedFormatter, NullFormatter, FuncFormatter, + FormatStrFormatter, ScalarFormatter, LogFormatter, LogFormatterExponent, + LogFormatterMathtext, Locator, IndexLocator, FixedLocator, NullLocator, + LinearLocator, LogLocator, AutoLocator, MultipleLocator, MaxNLocator) from mslice.plotting.globalfiguremanager import set_category from mslice.plotting.globalfiguremanager import ( @@ -105,17 +125,40 @@ _log = logging.getLogger(__name__) -def _copy_docstring_and_deprecators(method, func=None): +# Explicit rename instead of import-as for typing's sake. +colormaps = _colormaps +color_sequences = _color_sequences + + +@overload +def _copy_docstring_and_deprecators( + method: Any, + func: Literal[None] = None +) -> Callable[[Callable[_P, _R]], Callable[_P, _R]]: ... + + +@overload +def _copy_docstring_and_deprecators( + method: Any, func: Callable[_P, _R]) -> Callable[_P, _R]: ... + + +def _copy_docstring_and_deprecators( + method: Any, + func: Callable[_P, _R] | None = None +) -> Callable[[Callable[_P, _R]], Callable[_P, _R]] | Callable[_P, _R]: if func is None: - return functools.partial(_copy_docstring_and_deprecators, method) - decorators = [docstring.copy(method)] + return cast('Callable[[Callable[_P, _R]], Callable[_P, _R]]', + functools.partial(_copy_docstring_and_deprecators, method)) + decorators: list[Callable[[Callable[_P, _R]], Callable[_P, _R]]] = [ + _docstring.copy(method) + ] # Check whether the definition of *method* includes @_api.rename_parameter # or @_api.make_keyword_only decorators; if so, propagate them to the # pyplot wrapper as well. - while getattr(method, "__wrapped__", None) is not None: - decorator = _api.deprecation.DECORATORS.get(method) - if decorator: - decorators.append(decorator) + while hasattr(method, "__wrapped__"): + potential_decorator = _api.deprecation.DECORATORS.get(method) + if potential_decorator: + decorators.append(potential_decorator) method = method.__wrapped__ for decorator in decorators[::-1]: func = decorator(func) @@ -125,14 +168,14 @@ def _copy_docstring_and_deprecators(method, func=None): ## Global ## -def _draw_all_if_interactive(): +def _draw_all_if_interactive(): -> None: # We will always draw because mslice might be running without # matplotlib interactive for fig in GlobalFigureManager.all_figures(): fig.canvas.draw() -def draw_all(): +def draw_all(): -> None: for fig in GlobalFigureManager.all_figures(): fig.canvas.draw_idle() @@ -142,7 +185,7 @@ def draw_all(): _REPL_DISPLAYHOOK = _ReplDisplayHook.NONE -def install_repl_displayhook(): +def install_repl_displayhook() -> None: """ Connect to the display hook of the current shell. @@ -172,7 +215,7 @@ def install_repl_displayhook(): ip.events.register("post_execute", _draw_all_if_interactive) _REPL_DISPLAYHOOK = _ReplDisplayHook.IPYTHON - from IPython.core.pylabtools import backend2gui + from IPython.core.pylabtools import backend2gui # type: ignore # trigger IPython's eventloop integration, if available ipython_gui_name = backend2gui.get(get_backend()) @@ -180,97 +223,87 @@ def install_repl_displayhook(): ip.enable_gui(ipython_gui_name) -def uninstall_repl_displayhook(): +def uninstall_repl_displayhook() -> None: """Disconnect from the display hook of the current shell.""" global _REPL_DISPLAYHOOK if _REPL_DISPLAYHOOK is _ReplDisplayHook.IPYTHON: - from IPython import get_ipython + from IPython import get_ipython # type: ignore ip = get_ipython() ip.events.unregister("post_execute", _draw_all_if_interactive) _REPL_DISPLAYHOOK = _ReplDisplayHook.NONE - +# Ensure this appears in the pyplot docs. @_copy_docstring_and_deprecators(matplotlib.set_loglevel) -def set_loglevel(*args, **kwargs): # Ensure this appears in the pyplot docs. +def set_loglevel(*args, **kwargs) -> None: return matplotlib.set_loglevel(*args, **kwargs) @_copy_docstring_and_deprecators(Artist.findobj) -def findobj(o=None, match=None, include_self=True): +def findobj( + o: Artist | None = None, + match: Callable[[Artist], bool] | type[Artist] | None = None, + include_self: bool = True +) -> list[Artist]: if o is None: o = gcf() return o.findobj(match, include_self=include_self) -def _get_required_interactive_framework(backend_mod): - if not hasattr( - getattr(backend_mod, "FigureCanvas", None), "required_interactive_framework" - ): - _api.warn_deprecated( - "3.6", - name="Support for FigureCanvases without a " - "required_interactive_framework attribute", - ) - return None - # Inline this once the deprecation elapses. - return backend_mod.FigureCanvas.required_interactive_framework - +_backend_mod: type[matplotlib.backend_bases._Backend] | None = None -_backend_mod = None - -def _get_backend_mod(): +def _get_backend_mod() -> type[matplotlib.backend_bases._Backend]: """ Ensure that a backend is selected and return it. This is currently private, but may be made public in the future. """ if _backend_mod is None: - # Use __getitem__ here to avoid going through the fallback logic (which - # will (re)import pyplot and then call switch_backend if we need to - # resolve the auto sentinel) - switch_backend(dict.__getitem__(rcParams, "backend")) - return _backend_mod + # Use rcParams._get("backend") to avoid going through the fallback + # logic (which will (re)import pyplot and then call switch_backend if + # we need to resolve the auto sentinel) + switch_backend(rcParams._get("backend")) # type: ignore[attr-defined] + return cast(type[matplotlib.backend_bases._Backend], _backend_mod) -def switch_backend(newbackend): +def switch_backend(newbackend: str) -> None: """ - Close all open figures and set the Matplotlib backend. + Set the pyplot backend. + + Switching to an interactive backend is possible only if no event loop for + another interactive backend has started. Switching to and from + non-interactive backends is always possible. - The argument is case-insensitive. Switching to an interactive backend is - possible only if no event loop for another interactive backend has started. - Switching to and from non-interactive backends is always possible. + If the new backend is different than the current backend then all open + Figures will be closed via ``plt.close('all')``. Parameters ---------- newbackend : str - The name of the backend to use. + The case-insensitive name of the backend to use. + """ global _backend_mod # make sure the init is pulled up so we can assign to it later import matplotlib.backends - close("all") - if newbackend is rcsetup._auto_backend_sentinel: current_framework = cbook._get_running_interactive_framework() - mapping = { - "qt": "qtagg", - "gtk3": "gtk3agg", - "gtk4": "gtk4agg", - "wx": "wxagg", - "tk": "tkagg", - "macosx": "macosx", - "headless": "agg", - } - - best_guess = mapping.get(current_framework, None) - if best_guess is not None: - candidates = [best_guess] + mapping = {'qt': 'qtagg', + 'gtk3': 'gtk3agg', + 'gtk4': 'gtk4agg', + 'wx': 'wxagg', + 'tk': 'tkagg', + 'macosx': 'macosx', + 'headless': 'agg'} + + if current_framework in mapping: + candidates = [mapping[current_framework]] else: candidates = [] - candidates += ["macosx", "qtagg", "gtk4agg", "gtk3agg", "tkagg", "wxagg"] + candidates += [ + "macosx", "qtagg", "gtk4agg", "gtk3agg", "tkagg", "wxagg"] # Don't try to fallback on the cairo-based backends as they each have # an additional dependency (pycairo) over the agg-based backend, and @@ -281,7 +314,7 @@ def switch_backend(newbackend): except ImportError: continue else: - rcParamsOrig["backend"] = candidate + rcParamsOrig['backend'] = candidate return else: # Switching to Agg should always succeed; if it doesn't, let the @@ -289,45 +322,41 @@ def switch_backend(newbackend): switch_backend("agg") rcParamsOrig["backend"] = "agg" return + # have to escape the switch on access logic + old_backend = dict.__getitem__(rcParams, 'backend') - backend_mod = importlib.import_module(cbook._backend_module_name(newbackend)) + module = importlib.import_module(cbook._backend_module_name(newbackend)) + canvas_class = module.FigureCanvas - required_framework = _get_required_interactive_framework(backend_mod) + required_framework = canvas_class.required_interactive_framework if required_framework is not None: current_framework = cbook._get_running_interactive_framework() - if ( - current_framework - and required_framework - and current_framework != required_framework - ): + if (current_framework and required_framework + and current_framework != required_framework): raise ImportError( "Cannot load backend {!r} which requires the {!r} interactive " "framework, as {!r} is currently running".format( - newbackend, required_framework, current_framework - ) - ) + newbackend, required_framework, current_framework)) # Load the new_figure_manager() and show() functions from the backend. # Classically, backends can directly export these functions. This should # keep working for backcompat. - new_figure_manager = getattr(backend_mod, "new_figure_manager", None) + new_figure_manager = getattr(module, "new_figure_manager", None) + show = getattr(module, "show", None) - # show = getattr(backend_mod, "show", None) # In that classical approach, backends are implemented as modules, but # "inherit" default method implementations from backend_bases._Backend. # This is achieved by creating a "class" that inherits from # backend_bases._Backend and whose body is filled with the module globals. class backend_mod(matplotlib.backend_bases._Backend): - locals().update(vars(backend_mod)) + locals().update(vars(module)) - # However, the newer approach for defining new_figure_manager (and, in - # the future, show) is to derive them from canvas methods. In that case, - # also update backend_mod accordingly; also, per-backend customization of + # However, the newer approach for defining new_figure_manager and + # show is to derive them from canvas methods. In that case, also + # update backend_mod accordingly; also, per-backend customization of # draw_if_interactive is disabled. if new_figure_manager is None: - # only try to get the canvas class if have opted into the new scheme - canvas_class = backend_mod.FigureCanvas def new_figure_manager_given_figure(num, figure): return canvas_class.new_manager(figure, num) @@ -336,38 +365,68 @@ def new_figure_manager(num, *args, FigureClass=Figure, **kwargs): fig = FigureClass(*args, **kwargs) return new_figure_manager_given_figure(num, fig) - def draw_if_interactive(): + def draw_if_interactive() -> None: if matplotlib.is_interactive(): manager = _pylab_helpers.Gcf.get_active() if manager: manager.canvas.draw_idle() - backend_mod.new_figure_manager_given_figure = new_figure_manager_given_figure - backend_mod.new_figure_manager = new_figure_manager - backend_mod.draw_if_interactive = draw_if_interactive + backend_mod.new_figure_manager_given_figure = ( # type: ignore[method-assign] + new_figure_manager_given_figure) + backend_mod.new_figure_manager = ( # type: ignore[method-assign] + new_figure_manager) + backend_mod.draw_if_interactive = ( # type: ignore[method-assign] + draw_if_interactive) + + # If the manager explicitly overrides pyplot_show, use it even if a global + # show is already present, as the latter may be here for backcompat. + manager_class = getattr(canvas_class, "manager_class", None) + # We can't compare directly manager_class.pyplot_show and FMB.pyplot_show because + # pyplot_show is a classmethod so the above constructs are bound classmethods, and + # thus always different (being bound to different classes). We also have to use + # getattr_static instead of vars as manager_class could have no __dict__. + manager_pyplot_show = inspect.getattr_static(manager_class, "pyplot_show", None) + base_pyplot_show = inspect.getattr_static(FigureManagerBase, "pyplot_show", None) + if (show is None + or (manager_pyplot_show is not None + and manager_pyplot_show != base_pyplot_show)): + if not manager_pyplot_show: + raise ValueError( + f"Backend {newbackend} defines neither FigureCanvas.manager_class nor " + f"a toplevel show function") + _pyplot_show = cast('Any', manager_class).pyplot_show + backend_mod.show = _pyplot_show # type: ignore[method-assign] - _log.debug("Loaded backend %s version %s.", newbackend, backend_mod.backend_version) + _log.debug("Loaded backend %s version %s.", + newbackend, backend_mod.backend_version) - rcParams["backend"] = rcParamsDefault["backend"] = newbackend + rcParams['backend'] = rcParamsDefault['backend'] = newbackend _backend_mod = backend_mod for func_name in ["new_figure_manager", "draw_if_interactive", "show"]: globals()[func_name].__signature__ = inspect.signature( - getattr(backend_mod, func_name) - ) + getattr(backend_mod, func_name)) # Need to keep a global reference to the backend for compatibility reasons. # See https://github.com/matplotlib/matplotlib/issues/6092 - matplotlib.backends.backend = newbackend + matplotlib.backends.backend = newbackend # type: ignore[attr-defined] + + if not cbook._str_equal(old_backend, newbackend): + if get_fignums(): + _api.warn_deprecated("3.8", message=( + "Auto-close()ing of figures upon backend switching is deprecated since " + "%(since)s and will be removed %(removal)s. To suppress this warning, " + "explicitly call plt.close('all') first.")) + close("all") - # make sure the repl display hook is installed in case we become - # interactive + # Make sure the repl display hook is installed in case we become interactive. install_repl_displayhook() -def _warn_if_gui_out_of_main_thread(): +def _warn_if_gui_out_of_main_thread() -> None: warn = False - if _get_required_interactive_framework(_get_backend_mod()): - if hasattr(threading, "get_native_id"): + canvas_class = cast(type[FigureCanvasBase], _get_backend_mod().FigureCanvas) + if canvas_class.required_interactive_framework: + if hasattr(threading, 'get_native_id'): # This compares native thread ids because even if Python-level # Thread objects match, the underlying OS thread (which is what # really matters) may be different on Python implementations with @@ -381,8 +440,8 @@ def _warn_if_gui_out_of_main_thread(): warn = True if warn: _api.warn_external( - "Starting a Matplotlib GUI outside of the main thread will likely " "fail." - ) + "Starting a Matplotlib GUI outside of the main thread will likely " + "fail.") # This function's signature is rewritten upon backend-load by switch_backend. @@ -409,7 +468,7 @@ def draw_if_interactive(*args, **kwargs): # This function's signature is rewritten upon backend-load by switch_backend. -def show(*args, **kwargs): +def show(*args, **kwargs) -> None: """ Display all open figures. @@ -453,10 +512,12 @@ def show(*args, **kwargs): the end of every cell by default. Thus, you usually don't have to call it explicitly there. """ - return gcf().show(*args, **kwargs) + #return gcf().show(*args, **kwargs) + _warn_if_gui_out_of_main_thread() + return _get_backend_mod().show(*args, **kwargs) -def isinteractive(): +def isinteractive() -> bool: """ Return whether plots are updated after every plotting command. @@ -486,7 +547,7 @@ def isinteractive(): return matplotlib.is_interactive() -def ioff(): +def ioff() -> ExitStack: """ Disable interactive mode. @@ -526,7 +587,7 @@ def ioff(): return stack -def ion(): +def ion() -> ExitStack: """ Enable interactive mode. @@ -566,7 +627,7 @@ def ion(): return stack -def pause(interval): +def pause(interval: float) -> None: """ Run the GUI event loop for *interval* seconds. @@ -595,17 +656,20 @@ def pause(interval): @_copy_docstring_and_deprecators(matplotlib.rc) -def rc(group, **kwargs): +def rc(group: str, **kwargs) -> None: matplotlib.rc(group, **kwargs) @_copy_docstring_and_deprecators(matplotlib.rc_context) -def rc_context(rc=None, fname=None): +def rc_context( + rc: dict[str, Any] | None = None, + fname: str | pathlib.Path | os.PathLike | None = None, +) -> AbstractContextManager[None]: return matplotlib.rc_context(rc, fname) @_copy_docstring_and_deprecators(matplotlib.rcdefaults) -def rcdefaults(): +def rcdefaults() -> None: matplotlib.rcdefaults() if matplotlib.is_interactive(): draw_all() @@ -629,13 +693,16 @@ def setp(obj, *args, **kwargs): return matplotlib.artist.setp(obj, *args, **kwargs) -def xkcd(scale=1, length=100, randomness=2): +def xkcd( + scale: float = 1, length: float = 100, randomness: float = 2 +) -> ExitStack: """ - Turn on `xkcd `_ sketch-style drawing mode. This will - only have effect on things drawn after this function is called. + Turn on `xkcd `_ sketch-style drawing mode. - For best results, the "Humor Sans" font should be installed: it is - not included with Matplotlib. + This will only have an effect on things drawn after this function is called. + + For best results, install the `xkcd script `_ + font; xkcd fonts are not packaged with Matplotlib. Parameters ---------- @@ -665,39 +732,32 @@ def xkcd(scale=1, length=100, randomness=2): # This cannot be implemented in terms of contextmanager() or rc_context() # because this needs to work as a non-contextmanager too. - if rcParams["text.usetex"]: - raise RuntimeError("xkcd mode is not compatible with text.usetex = True") + if rcParams['text.usetex']: + raise RuntimeError( + "xkcd mode is not compatible with text.usetex = True") stack = ExitStack() - stack.callback(dict.update, rcParams, rcParams.copy()) + stack.callback(dict.update, rcParams, rcParams.copy()) # type: ignore from matplotlib import patheffects - - rcParams.update( - { - "font.family": [ - "xkcd", - "xkcd Script", - "Humor Sans", - "Comic Neue", - "Comic Sans MS", - ], - "font.size": 14.0, - "path.sketch": (scale, length, randomness), - "path.effects": [patheffects.withStroke(linewidth=4, foreground="w")], - "axes.linewidth": 1.5, - "lines.linewidth": 2.0, - "figure.facecolor": "white", - "grid.linewidth": 0.0, - "axes.grid": False, - "axes.unicode_minus": False, - "axes.edgecolor": "black", - "xtick.major.size": 8, - "xtick.major.width": 3, - "ytick.major.size": 8, - "ytick.major.width": 3, - } - ) + rcParams.update({ + 'font.family': ['xkcd', 'xkcd Script', 'Comic Neue', 'Comic Sans MS'], + 'font.size': 14.0, + 'path.sketch': (scale, length, randomness), + 'path.effects': [ + patheffects.withStroke(linewidth=4, foreground="w")], + 'axes.linewidth': 1.5, + 'lines.linewidth': 2.0, + 'figure.facecolor': 'white', + 'grid.linewidth': 0.0, + 'axes.grid': False, + 'axes.unicode_minus': False, + 'axes.edgecolor': 'black', + 'xtick.major.size': 8, + 'xtick.major.width': 3, + 'ytick.major.size': 8, + 'ytick.major.width': 3, + }) return stack @@ -705,18 +765,124 @@ def xkcd(scale=1, length=100, randomness=2): ## Figures ## -@_api.make_keyword_only("3.6", "facecolor") def figure( - num=None, # autoincrement if None, else integer from 1-N - figsize=None, # defaults to rc figure.figsize - dpi=None, # defaults to rc figure.dpi - facecolor=None, # defaults to rc figure.facecolor - edgecolor=None, # defaults to rc figure.edgecolor - frameon=True, - FigureClass=Figure, - clear=False, - **kwargs, -): + # autoincrement if None, else integer from 1-N + num: int | str | Figure | SubFigure | None = None, + # defaults to rc figure.figsize + figsize: tuple[float, float] | None = None, + # defaults to rc figure.dpi + dpi: float | None = None, + *, + # defaults to rc figure.facecolor + facecolor: ColorType | None = None, + # defaults to rc figure.edgecolor + edgecolor: ColorType | None = None, + frameon: bool = True, + FigureClass: type[Figure] = Figure, + clear: bool = False, + **kwargs +) -> Figure: + """ + Create a new figure, or activate an existing figure. + + Parameters + ---------- + num : int or str or `.Figure` or `.SubFigure`, optional + A unique identifier for the figure. + + If a figure with that identifier already exists, this figure is made + active and returned. An integer refers to the ``Figure.number`` + attribute, a string refers to the figure label. + + If there is no figure with the identifier or *num* is not given, a new + figure is created, made active and returned. If *num* is an int, it + will be used for the ``Figure.number`` attribute, otherwise, an + auto-generated integer value is used (starting at 1 and incremented + for each new figure). If *num* is a string, the figure label and the + window title is set to this value. If num is a ``SubFigure``, its + parent ``Figure`` is activated. + + figsize : (float, float), default: :rc:`figure.figsize` + Width, height in inches. + + dpi : float, default: :rc:`figure.dpi` + The resolution of the figure in dots-per-inch. + + facecolor : color, default: :rc:`figure.facecolor` + The background color. + + edgecolor : color, default: :rc:`figure.edgecolor` + The border color. + + frameon : bool, default: True + If False, suppress drawing the figure frame. + + FigureClass : subclass of `~matplotlib.figure.Figure` + If set, an instance of this subclass will be created, rather than a + plain `.Figure`. + + clear : bool, default: False + If True and the figure already exists, then it is cleared. + + layout : {'constrained', 'compressed', 'tight', 'none', `.LayoutEngine`, None}, \ +default: None + The layout mechanism for positioning of plot elements to avoid + overlapping Axes decorations (labels, ticks, etc). Note that layout + managers can measurably slow down figure display. + + - 'constrained': The constrained layout solver adjusts axes sizes + to avoid overlapping axes decorations. Can handle complex plot + layouts and colorbars, and is thus recommended. + + See :ref:`constrainedlayout_guide` + for examples. + + - 'compressed': uses the same algorithm as 'constrained', but + removes extra space between fixed-aspect-ratio Axes. Best for + simple grids of axes. + + - 'tight': Use the tight layout mechanism. This is a relatively + simple algorithm that adjusts the subplot parameters so that + decorations do not overlap. See `.Figure.set_tight_layout` for + further details. + + - 'none': Do not use a layout engine. + + - A `.LayoutEngine` instance. Builtin layout classes are + `.ConstrainedLayoutEngine` and `.TightLayoutEngine`, more easily + accessible by 'constrained' and 'tight'. Passing an instance + allows third parties to provide their own layout engine. + + If not given, fall back to using the parameters *tight_layout* and + *constrained_layout*, including their config defaults + :rc:`figure.autolayout` and :rc:`figure.constrained_layout.use`. + + **kwargs + Additional keyword arguments are passed to the `.Figure` constructor. + + Returns + ------- + `~matplotlib.figure.Figure` + + Notes + ----- + A newly created figure is passed to the `~.FigureCanvasBase.new_manager` + method or the `new_figure_manager` function provided by the current + backend, which install a canvas and a manager on the figure. + + Once this is done, :rc:`figure.hooks` are called, one at a time, on the + figure; these hooks allow arbitrary customization of the figure (e.g., + attaching callbacks) or of associated elements (e.g., modifying the + toolbar). See :doc:`/gallery/user_interfaces/mplcvd` for an example of + toolbar customization. + + If you are creating many figures, make sure you explicitly call + `.pyplot.close` on the figures you are not using, because this will + enable pyplot to properly clean up the memory. + + `~matplotlib.rcParams` defines the default values, which can be modified + in the matplotlibrc file. + """ return GlobalFigureManager.get_figure_number(num).figure @@ -731,12 +897,9 @@ def _auto_draw_if_interactive(fig, val): fig : Figure A figure object which is assumed to be associated with a canvas """ - if ( - val - and matplotlib.is_interactive() - and not fig.canvas.is_saving() - and not fig.canvas._is_idle_drawing - ): + if (val and matplotlib.is_interactive() + and not fig.canvas.is_saving() + and not fig.canvas._is_idle_drawing): # Some artists can mark themselves as stale in the middle of drawing # (e.g. axes position & tick labels being computed at draw time), but # this shouldn't trigger a redraw because the current redraw will @@ -745,7 +908,7 @@ def _auto_draw_if_interactive(fig, val): fig.canvas.draw_idle() -def gcf(): +def gcf() -> Figure: """ Get the current figure. @@ -753,24 +916,24 @@ def gcf(): return GlobalFigureManager.get_active_figure().figure -def fignum_exists(num): +def fignum_exists(num: int | str) -> bool: """Return whether the figure with the given id exists.""" return GlobalFigureManager.has_fignum(num) or num in get_figlabels() -def get_fignums(): +def get_fignums() -> list[int]: """Return a list of existing figure numbers.""" return sorted(GlobalFigureManager.figs) -def get_figlabels(): +def get_figlabels() -> list[Any]: """Return a list of existing figure labels.""" figManagers = GlobalFigureManager.get_all_fig_managers() figManagers.sort(key=lambda m: m.num) return [m.canvas.figure.get_label() for m in figManagers] -def get_current_fig_manager(): +def get_current_fig_manager() -> FigureManagerBase | None: figManager = GlobalFigureManager.get_active() if figManager is None: gcf() # creates an active figure as a side effect @@ -779,16 +942,16 @@ def get_current_fig_manager(): @_copy_docstring_and_deprecators(FigureCanvasBase.mpl_connect) -def connect(s, func): +def connect(s: str, func: Callable[[Event], Any]) -> int: return get_current_fig_manager().canvas.mpl_connect(s, func) @_copy_docstring_and_deprecators(FigureCanvasBase.mpl_disconnect) -def disconnect(cid): +def disconnect(cid: int) -> None: return get_current_fig_manager().canvas.mpl_disconnect(cid) -def close(fig=None): +def close(fig: None | int | str | Figure | Literal["all"] = None) -> None: """ Close a figure window. @@ -832,12 +995,12 @@ def close(fig=None): ) -def clf(): +def clf() -> None: """Clear the current figure.""" gcf().clear() -def draw(): +def draw() -> None: """ Redraw the current figure. @@ -853,9 +1016,11 @@ def draw(): @_copy_docstring_and_deprecators(Figure.savefig) -def savefig(*args, **kwargs): +def savefig(*args, **kwargs) -> None: fig = gcf() - res = fig.savefig(*args, **kwargs) + # savefig default implementation has no return, so mypy is unhappy + # presumably this is here because subclasses can return? + res = fig.savefig(*args, **kwargs) # type: ignore[func-returns-value] fig.canvas.draw_idle() # Need this if 'transparent=True', to reset colors. return res @@ -863,19 +1028,23 @@ def savefig(*args, **kwargs): ## Putting things in figures ## -def figlegend(*args, **kwargs): +def figlegend(*args, **kwargs) -> Legend: return gcf().legend(*args, **kwargs) - - if Figure.legend.__doc__: - figlegend.__doc__ = Figure.legend.__doc__.replace("legend(", "figlegend(") + figlegend.__doc__ = Figure.legend.__doc__ \ + .replace(" legend(", " figlegend(") \ + .replace("fig.legend(", "plt.figlegend(") \ + .replace("ax.plot(", "plt.plot(") ## Axes ## -@docstring.dedent_interpd -def axes(arg=None, **kwargs): +@_docstring.dedent_interpd +def axes( + arg: None | tuple[float, float, float, float] = None, + **kwargs +) -> matplotlib.axes.Axes: """ Add an Axes to the current figure and make it the current Axes. @@ -892,7 +1061,7 @@ def axes(arg=None, **kwargs): - *None*: A new full window Axes is added using ``subplot(**kwargs)``. - - 4-tuple of floats *rect* = ``[left, bottom, width, height]``. + - 4-tuple of floats *rect* = ``(left, bottom, width, height)``. A new Axes is added with dimensions *rect* in normalized (0, 1) units using `~.Figure.add_axes` on the current figure. @@ -905,7 +1074,7 @@ def axes(arg=None, **kwargs): polar : bool, default: False If True, equivalent to projection='polar'. - sharex, sharey : `~.axes.Axes`, optional + sharex, sharey : `~matplotlib.axes.Axes`, optional Share the x or y `~matplotlib.axis` with sharex and/or sharey. The axis will have the same limits, ticks, and scale as the axis of the shared Axes. @@ -932,17 +1101,6 @@ def axes(arg=None, **kwargs): %(Axes:kwdoc)s - Notes - ----- - If the figure already has an Axes with key (*args*, - *kwargs*) then it will simply make that axes current and - return it. This behavior is deprecated. Meanwhile, if you do - not want this behavior (i.e., you want to force the creation of a - new axes), you must use a unique set of args and kwargs. The Axes - *label* attribute has been exposed for this purpose: if you want - two Axes that are otherwise identical to be added to the figure, - make sure you give them unique labels. - See Also -------- .Figure.add_axes @@ -962,7 +1120,7 @@ def axes(arg=None, **kwargs): plt.axes((left, bottom, width, height), facecolor='grey') """ fig = gcf() - pos = kwargs.pop("position", None) + pos = kwargs.pop('position', None) if arg is None: if pos is None: return fig.add_subplot(**kwargs) @@ -972,7 +1130,7 @@ def axes(arg=None, **kwargs): return fig.add_axes(arg, **kwargs) -def delaxes(ax=None): +def delaxes(ax: matplotlib.axes.Axes | None = None) -> None: """ Remove an `~.axes.Axes` (defaulting to the current axes) from its figure. """ @@ -981,15 +1139,18 @@ def delaxes(ax=None): ax.remove() -def sca(ax): +def sca(ax: Axes) -> None: """ Set the current Axes to *ax* and the current Figure to the parent of *ax*. """ - figure(ax.figure) - ax.figure.sca(ax) + # Mypy sees ax.figure as potentially None, + # but if you are calling this, it won't be None + # Additionally the slight difference between `Figure` and `FigureBase` mypy catches + figure(ax.figure) # type: ignore[arg-type] + ax.figure.sca(ax) # type: ignore[union-attr] -def cla(): +def cla() -> None: """Clear the current axes.""" # Not generated via boilerplate.py to allow a different docstring. return gca().cla() @@ -997,9 +1158,8 @@ def cla(): ## More ways of creating axes ## - -@docstring.dedent_interpd -def subplot(*args, **kwargs): +@_docstring.dedent_interpd +def subplot(*args, **kwargs) -> Axes: """ Add an Axes to the current figure or retrieve an existing Axes. @@ -1040,7 +1200,7 @@ def subplot(*args, **kwargs): polar : bool, default: False If True, equivalent to projection='polar'. - sharex, sharey : `~.axes.Axes`, optional + sharex, sharey : `~matplotlib.axes.Axes`, optional Share the x or y `~matplotlib.axis` with sharex and/or sharey. The axis will have the same limits, ticks, and scale as the axis of the shared axes. @@ -1050,13 +1210,11 @@ def subplot(*args, **kwargs): Returns ------- - `.axes.SubplotBase`, or another subclass of `~.axes.Axes` + `~.axes.Axes` - The axes of the subplot. The returned axes base class depends on - the projection used. It is `~.axes.Axes` if rectilinear projection - is used and `.projections.polar.PolarAxes` if polar projection - is used. The returned axes is then a subplot subclass of the - base class. + The Axes of the subplot. The returned Axes can actually be an instance + of a subclass, such as `.projections.polar.PolarAxes` for polar + projections. Other Parameters ---------------- @@ -1137,16 +1295,16 @@ def subplot(*args, **kwargs): # Here we will only normalize `polar=True` vs `projection='polar'` and let # downstream code deal with the rest. unset = object() - projection = kwargs.get("projection", unset) - polar = kwargs.pop("polar", unset) + projection = kwargs.get('projection', unset) + polar = kwargs.pop('polar', unset) if polar is not unset and polar: # if we got mixed messages from the user, raise - if projection is not unset and projection != "polar": + if projection is not unset and projection != 'polar': raise ValueError( f"polar={polar}, yet projection={projection!r}. " "Only one of these arguments should be supplied." ) - kwargs["projection"] = projection = "polar" + kwargs['projection'] = projection = 'polar' # if subplot called without arguments, create subplot(1, 1, 1) if len(args) == 0: @@ -1158,17 +1316,13 @@ def subplot(*args, **kwargs): # because what was intended to be the sharex argument is instead treated as # a subplot index for subplot() if len(args) >= 3 and isinstance(args[2], bool): - _api.warn_external( - "The subplot index argument to subplot() appears " - "to be a boolean. Did you intend to use " - "subplots()?" - ) + _api.warn_external("The subplot index argument to subplot() appears " + "to be a boolean. Did you intend to use " + "subplots()?") # Check for nrows and ncols, which are not valid subplot args: - if "nrows" in kwargs or "ncols" in kwargs: - raise TypeError( - "subplot() got an unexpected keyword argument 'ncols' " - "and/or 'nrows'. Did you intend to call subplots()?" - ) + if 'nrows' in kwargs or 'ncols' in kwargs: + raise TypeError("subplot() got an unexpected keyword argument 'ncols' " + "and/or 'nrows'. Did you intend to call subplots()?") fig = gcf() @@ -1176,53 +1330,33 @@ def subplot(*args, **kwargs): key = SubplotSpec._from_subplot_args(fig, args) for ax in fig.axes: - # if we found an Axes at the position sort out if we can re-use it - if hasattr(ax, "get_subplotspec") and ax.get_subplotspec() == key: - # if the user passed no kwargs, re-use - if kwargs == {}: - break - # if the axes class and kwargs are identical, reuse - elif ax._projection_init == fig._process_projection_requirements( - *args, **kwargs - ): - break + # If we found an Axes at the position, we can re-use it if the user passed no + # kwargs or if the axes class and kwargs are identical. + if (ax.get_subplotspec() == key + and (kwargs == {} + or (ax._projection_init + == fig._process_projection_requirements(**kwargs)))): + break else: # we have exhausted the known Axes and none match, make a new one! ax = fig.add_subplot(*args, **kwargs) fig.sca(ax) - axes_to_delete = [ - other - for other in fig.axes - if other != ax and ax.bbox.fully_overlaps(other.bbox) - ] - if axes_to_delete: - _api.warn_deprecated( - "3.6", - message="Auto-removal of overlapping axes is deprecated " - "since %(since)s and will be removed %(removal)s; explicitly call " - "ax.remove() as needed.", - ) - for ax_to_del in axes_to_delete: - delaxes(ax_to_del) - return ax def subplots( - nrows=1, - ncols=1, - *, - sharex=False, - sharey=False, - squeeze=True, - width_ratios=None, - height_ratios=None, - subplot_kw=None, - gridspec_kw=None, - **fig_kw, -): + nrows: int = 1, ncols: int = 1, *, + sharex: bool | Literal["none", "all", "row", "col"] = False, + sharey: bool | Literal["none", "all", "row", "col"] = False, + squeeze: bool = True, + width_ratios: Sequence[float] | None = None, + height_ratios: Sequence[float] | None = None, + subplot_kw: dict[str, Any] | None = None, + gridspec_kw: dict[str, Any] | None = None, + **fig_kw +) -> tuple[Figure, Any]: """ Create a figure and a set of subplots. @@ -1296,7 +1430,7 @@ def subplots( ------- fig : `.Figure` - ax : `~.axes.Axes` or array of Axes + ax : `~matplotlib.axes.Axes` or array of Axes *ax* can be either a single `~.axes.Axes` object, or an array of Axes objects if more than one subplot was created. The dimensions of the resulting array can be controlled with the squeeze keyword, see above. @@ -1367,43 +1501,84 @@ def subplots( """ fig = figure(**fig_kw) - axs = fig.subplots( - nrows=nrows, - ncols=ncols, - sharex=sharex, - sharey=sharey, - squeeze=squeeze, - subplot_kw=subplot_kw, - gridspec_kw=gridspec_kw, - height_ratios=height_ratios, - width_ratios=width_ratios, - ) + axs = fig.subplots(nrows=nrows, ncols=ncols, sharex=sharex, sharey=sharey, + squeeze=squeeze, subplot_kw=subplot_kw, + gridspec_kw=gridspec_kw, height_ratios=height_ratios, + width_ratios=width_ratios) return fig, axs +@overload def subplot_mosaic( - mosaic, + mosaic: str, *, - sharex=False, - sharey=False, - width_ratios=None, - height_ratios=None, - empty_sentinel=".", - subplot_kw=None, - gridspec_kw=None, - **fig_kw, -): + sharex: bool = ..., + sharey: bool = ..., + width_ratios: ArrayLike | None = ..., + height_ratios: ArrayLike | None = ..., + empty_sentinel: str = ..., + subplot_kw: dict[str, Any] | None = ..., + gridspec_kw: dict[str, Any] | None = ..., + per_subplot_kw: dict[str | tuple[str, ...], dict[str, Any]] | None = ..., + **fig_kw: Any +) -> tuple[Figure, dict[str, matplotlib.axes.Axes]]: ... + + +@overload +def subplot_mosaic( + mosaic: list[HashableList[_T]], + *, + sharex: bool = ..., + sharey: bool = ..., + width_ratios: ArrayLike | None = ..., + height_ratios: ArrayLike | None = ..., + empty_sentinel: _T = ..., + subplot_kw: dict[str, Any] | None = ..., + gridspec_kw: dict[str, Any] | None = ..., + per_subplot_kw: dict[_T | tuple[_T, ...], dict[str, Any]] | None = ..., + **fig_kw: Any +) -> tuple[Figure, dict[_T, matplotlib.axes.Axes]]: ... + + +@overload +def subplot_mosaic( + mosaic: list[HashableList[Hashable]], + *, + sharex: bool = ..., + sharey: bool = ..., + width_ratios: ArrayLike | None = ..., + height_ratios: ArrayLike | None = ..., + empty_sentinel: Any = ..., + subplot_kw: dict[str, Any] | None = ..., + gridspec_kw: dict[str, Any] | None = ..., + per_subplot_kw: dict[Hashable | tuple[Hashable, ...], dict[str, Any]] | None = ..., + **fig_kw: Any +) -> tuple[Figure, dict[Hashable, matplotlib.axes.Axes]]: ... + + +def subplot_mosaic( + mosaic: str | list[HashableList[_T]] | list[HashableList[Hashable]], + *, + sharex: bool = False, + sharey: bool = False, + width_ratios: ArrayLike | None = None, + height_ratios: ArrayLike | None = None, + empty_sentinel: Any = '.', + subplot_kw: dict[str, Any] | None = None, + gridspec_kw: dict[str, Any] | None = None, + per_subplot_kw: dict[str | tuple[str, ...], dict[str, Any]] | + dict[_T | tuple[_T, ...], dict[str, Any]] | + dict[Hashable | tuple[Hashable, ...], dict[str, Any]] | None = None, + **fig_kw: Any +) -> tuple[Figure, dict[str, matplotlib.axes.Axes]] | \ + tuple[Figure, dict[_T, matplotlib.axes.Axes]] | \ + tuple[Figure, dict[Hashable, matplotlib.axes.Axes]]: """ Build a layout of Axes based on ASCII art or nested lists. This is a helper function to build complex GridSpec layouts visually. - .. note:: - - This API is provisional and may be revised in the future based on - early user feedback. - - See :doc:`/tutorials/provisional/mosaic` + See :ref:`mosaic` for an example and full API documentation Parameters @@ -1463,7 +1638,21 @@ def subplot_mosaic( subplot_kw : dict, optional Dictionary with keywords passed to the `.Figure.add_subplot` call - used to create each subplot. + used to create each subplot. These values may be overridden by + values in *per_subplot_kw*. + + per_subplot_kw : dict, optional + A dictionary mapping the Axes identifiers or tuples of identifiers + to a dictionary of keyword arguments to be passed to the + `.Figure.add_subplot` call used to create each subplot. The values + in these dictionaries have precedence over the values in + *subplot_kw*. + + If *mosaic* is a string, and thus all keys are single characters, + it is possible to use a single string instead of a tuple as keys; + i.e. ``"AB"`` is equivalent to ``("A", "B")``. + + .. versionadded:: 3.7 gridspec_kw : dict, optional Dictionary with keywords passed to the `.GridSpec` constructor used @@ -1485,20 +1674,23 @@ def subplot_mosaic( """ fig = figure(**fig_kw) - ax_dict = fig.subplot_mosaic( - mosaic, - sharex=sharex, - sharey=sharey, - height_ratios=height_ratios, - width_ratios=width_ratios, - subplot_kw=subplot_kw, - gridspec_kw=gridspec_kw, + ax_dict = fig.subplot_mosaic( # type: ignore[misc] + mosaic, # type: ignore[arg-type] + sharex=sharex, sharey=sharey, + height_ratios=height_ratios, width_ratios=width_ratios, + subplot_kw=subplot_kw, gridspec_kw=gridspec_kw, empty_sentinel=empty_sentinel, + per_subplot_kw=per_subplot_kw, # type: ignore[arg-type] ) return fig, ax_dict -def subplot2grid(shape, loc, rowspan=1, colspan=1, fig=None, **kwargs): +def subplot2grid( + shape: tuple[int, int], loc: tuple[int, int], + rowspan: int = 1, colspan: int = 1, + fig: Figure | None = None, + **kwargs +) -> matplotlib.axes.Axes: """ Create a subplot at a specific location inside a regular grid. @@ -1519,12 +1711,11 @@ def subplot2grid(shape, loc, rowspan=1, colspan=1, fig=None, **kwargs): Returns ------- - `.axes.SubplotBase`, or another subclass of `~.axes.Axes` + `~.axes.Axes` - The axes of the subplot. The returned axes base class depends on the - projection used. It is `~.axes.Axes` if rectilinear projection is used - and `.projections.polar.PolarAxes` if polar projection is used. The - returned axes is then a subplot subclass of the base class. + The Axes of the subplot. The returned Axes can actually be an instance + of a subclass, such as `.projections.polar.PolarAxes` for polar + projections. Notes ----- @@ -1538,35 +1729,15 @@ def subplot2grid(shape, loc, rowspan=1, colspan=1, fig=None, **kwargs): gs = fig.add_gridspec(nrows, ncols) ax = fig.add_subplot(gs[row:row+rowspan, col:col+colspan]) """ - if fig is None: fig = gcf() - rows, cols = shape gs = GridSpec._check_gridspec_exists(fig, rows, cols) - subplotspec = gs.new_subplotspec(loc, rowspan=rowspan, colspan=colspan) - ax = fig.add_subplot(subplotspec, **kwargs) - - axes_to_delete = [ - other - for other in fig.axes - if other != ax and ax.bbox.fully_overlaps(other.bbox) - ] - if axes_to_delete: - _api.warn_deprecated( - "3.6", - message="Auto-removal of overlapping axes is deprecated " - "since %(since)s and will be removed %(removal)s; explicitly call " - "ax.remove() as needed.", - ) - for ax_to_del in axes_to_delete: - delaxes(ax_to_del) - - return ax + return fig.add_subplot(subplotspec, **kwargs) -def twinx(ax=None): +def twinx(ax: matplotlib.axes.Axes | None = None) -> _AxesBase: """ Make and return a second axes that shares the *x*-axis. The new axes will overlay *ax* (or the current axes if *ax* is *None*), and its ticks will be @@ -1582,7 +1753,7 @@ def twinx(ax=None): return ax1 -def twiny(ax=None): +def twiny(ax: matplotlib.axes.Axes | None = None) -> _AxesBase: """ Make and return a second axes that shares the *y*-axis. The new axes will overlay *ax* (or the current axes if *ax* is *None*), and its ticks will be @@ -1598,7 +1769,7 @@ def twiny(ax=None): return ax1 -def subplot_tool(targetfig=None): +def subplot_tool(targetfig: Figure | None = None) -> SubplotTool | None: """ Launch a subplot tool window for a figure. @@ -1627,7 +1798,7 @@ def subplot_tool(targetfig=None): return ret -def box(on=None): +def box(on: bool | None = None) -> None: """ Turn the axes box on or off on the current axes. @@ -1651,7 +1822,7 @@ def box(on=None): ## Axis ## -def xlim(*args, **kwargs): +def xlim(*args, **kwargs) -> tuple[float, float]: """ Get or set the x limits of the current axes. @@ -1688,7 +1859,7 @@ def xlim(*args, **kwargs): return ret -def ylim(*args, **kwargs): +def ylim(*args, **kwargs) -> tuple[float, float]: """ Get or set the y-limits of the current axes. @@ -1725,7 +1896,13 @@ def ylim(*args, **kwargs): return ret -def xticks(ticks=None, labels=None, *, minor=False, **kwargs): +def xticks( + ticks: ArrayLike | None = None, + labels: Sequence[str] | None = None, + *, + minor: bool = False, + **kwargs +) -> tuple[list[Tick] | np.ndarray, list[Text]]: """ Get or set the current tick locations and labels of the x-axis. @@ -1789,7 +1966,13 @@ def xticks(ticks=None, labels=None, *, minor=False, **kwargs): return locs, labels -def yticks(ticks=None, labels=None, *, minor=False, **kwargs): +def yticks( + ticks: ArrayLike | None = None, + labels: Sequence[str] | None = None, + *, + minor: bool = False, + **kwargs +) -> tuple[list[Tick] | np.ndarray, list[Text]]: """ Get or set the current tick locations and labels of the y-axis. @@ -1853,7 +2036,13 @@ def yticks(ticks=None, labels=None, *, minor=False, **kwargs): return locs, labels -def rgrids(radii=None, labels=None, angle=None, fmt=None, **kwargs): +def rgrids( + radii: ArrayLike | None = None, + labels: Sequence[str | Text] | None = None, + angle: float | None = None, + fmt: str | None = None, + **kwargs +) -> tuple[list[Line2D], list[Text]]: """ Get or set the radial gridlines on the current polar plot. @@ -1925,7 +2114,12 @@ def rgrids(radii=None, labels=None, angle=None, fmt=None, **kwargs): return lines, labels -def thetagrids(angles=None, labels=None, fmt=None, **kwargs): +def thetagrids( + angles: ArrayLike | None = None, + labels: Sequence[str | Text] | None = None, + fmt: str | None = None, + **kwargs +) -> tuple[list[Line2D], list[Text]]: """ Get or set the theta gridlines on the current polar plot. @@ -1992,60 +2186,53 @@ def thetagrids(angles=None, labels=None, fmt=None, **kwargs): return lines, labels -_NON_PLOT_COMMANDS = { - "connect", - "disconnect", - "get_current_fig_manager", - "ginput", - "new_figure_manager", - "waitforbuttonpress", -} - - -def get_plot_commands(): +@_api.deprecated("3.7", pending=True) +def get_plot_commands() -> list[str]: """ Get a sorted list of all of the plotting commands. """ + NON_PLOT_COMMANDS = { + 'connect', 'disconnect', 'get_current_fig_manager', 'ginput', + 'new_figure_manager', 'waitforbuttonpress'} + return [name for name in _get_pyplot_commands() + if name not in NON_PLOT_COMMANDS] + + +def _get_pyplot_commands() -> list[str]: # This works by searching for all functions in this module and removing # a few hard-coded exclusions, as well as all of the colormap-setting # functions, and anything marked as private with a preceding underscore. - exclude = { - "colormaps", - "colors", - "get_plot_commands", - *_NON_PLOT_COMMANDS, - *colormaps, - } + exclude = {'colormaps', 'colors', 'get_plot_commands', *colormaps} this_module = inspect.getmodule(get_plot_commands) return sorted( - name - for name, obj in globals().items() - if not name.startswith("_") - and name not in exclude - and inspect.isfunction(obj) - and inspect.getmodule(obj) is this_module - ) + name for name, obj in globals().items() + if not name.startswith('_') and name not in exclude + and inspect.isfunction(obj) + and inspect.getmodule(obj) is this_module) ## Plotting part 1: manually generated functions and wrappers ## @_copy_docstring_and_deprecators(Figure.colorbar) -def colorbar(mappable=None, cax=None, ax=None, **kwargs): +def colorbar( + mappable: ScalarMappable | None = None, + cax: matplotlib.axes.Axes | None = None, + ax: matplotlib.axes.Axes | Iterable[matplotlib.axes.Axes] | None = None, + **kwargs +) -> Colorbar: if mappable is None: mappable = gci() if mappable is None: - raise RuntimeError( - "No mappable was found to use for colorbar " - "creation. First define a mappable such as " - "an image (with imshow) or a contour set (" - "with contourf)." - ) + raise RuntimeError('No mappable was found to use for colorbar ' + 'creation. First define a mappable such as ' + 'an image (with imshow) or a contour set (' + 'with contourf).') ret = gcf().colorbar(mappable, cax=cax, ax=ax, **kwargs) return ret -def clim(vmin=None, vmax=None): +def clim(vmin: float | None = None, vmax: float | None = None) -> None: """ Set the color limits of the current image. @@ -2061,12 +2248,22 @@ def clim(vmin=None, vmax=None): """ im = gci() if im is None: - raise RuntimeError("You must first define an image, e.g., with imshow") + raise RuntimeError('You must first define an image, e.g., with imshow') im.set_clim(vmin, vmax) -def set_cmap(cmap): +# eventually this implementation should move here, use indirection for now to +# avoid having two copies of the code floating around. +def get_cmap( + name: Colormap | str | None = None, + lut: int | None = None +) -> Colormap: + return cm._get_cmap(name=name, lut=lut) # type: ignore +get_cmap.__doc__ = cm._get_cmap.__doc__ # type: ignore + + +def set_cmap(cmap: Colormap | str) -> None: """ Set the default colormap, and applies it to the current image if any. @@ -2083,7 +2280,7 @@ def set_cmap(cmap): """ cmap = get_cmap(cmap) - rc("image", cmap=cmap.name) + rc('image', cmap=cmap.name) im = gci() if im is not None: @@ -2091,16 +2288,20 @@ def set_cmap(cmap): @_copy_docstring_and_deprecators(matplotlib.image.imread) -def imread(fname, format=None): +def imread( + fname: str | pathlib.Path | BinaryIO, format: str | None = None +) -> np.ndarray: return matplotlib.image.imread(fname, format) @_copy_docstring_and_deprecators(matplotlib.image.imsave) -def imsave(fname, arr, **kwargs): - return matplotlib.image.imsave(fname, arr, **kwargs) +def imsave( + fname: str | os.PathLike | BinaryIO, arr: ArrayLike, **kwargs +) -> None: + matplotlib.image.imsave(fname, arr, **kwargs) -def matshow(A, fignum=None, **kwargs): +def matshow(A: ArrayLike, fignum: None | int = None, **kwargs) -> AxesImage: """ Display an array as a matrix in a new figure window. @@ -2116,19 +2317,16 @@ def matshow(A, fignum=None, **kwargs): A : 2D array-like The matrix to be displayed. - fignum : None or int or False - If *None*, create a new figure window with automatic numbering. - - If a nonzero integer, draw into the figure with the given number - (create it if it does not exist). - - If 0, use the current axes (or create one if it does not exist). + fignum : None or int + If *None*, create a new, appropriately sized figure window. - .. note:: + If 0, use the current Axes (creating one if there is none, without ever + adjusting the figure size). - Because of how `.Axes.matshow` tries to set the figure aspect - ratio to be the one of the array, strange things may happen if you - reuse an existing figure. + Otherwise, create a new Axes on the figure with the given number + (creating it at the appropriate size if it does not exist, but not + adjusting the figure size otherwise). Note that this will be drawn on + top of any preexisting Axes on the figure. Returns ------- @@ -2146,13 +2344,13 @@ def matshow(A, fignum=None, **kwargs): # Extract actual aspect ratio of array and make appropriately sized # figure. fig = figure(fignum, figsize=figaspect(A)) - ax = fig.add_axes([0.15, 0.09, 0.775, 0.775]) + ax = fig.add_axes((0.15, 0.09, 0.775, 0.775)) im = ax.matshow(A, **kwargs) sci(im) return im -def polar(*args, **kwargs): +def polar(*args, **kwargs) -> list[Line2D]: """ Make a polar plot. @@ -2167,15 +2365,25 @@ def polar(*args, **kwargs): if gcf().get_axes(): ax = gca() if not isinstance(ax, PolarAxes): - _api.warn_external( - "Trying to create polar plot on an Axes " - "that does not have a polar projection." - ) + _api.warn_external('Trying to create polar plot on an Axes ' + 'that does not have a polar projection.') else: ax = axes(projection="polar") return ax.plot(*args, **kwargs) +# If rcParams['backend_fallback'] is true, and an interactive backend is +# requested, ignore rcParams['backend'] and force selection of a backend that +# is compatible with the current running interactive framework. +if (rcParams["backend_fallback"] + and rcParams._get_backend_or_none() in ( # type: ignore + set(rcsetup.interactive_bk) - {'WebAgg', 'nbAgg'}) + and cbook._get_running_interactive_framework()): # type: ignore + rcParams._set("backend", rcsetup._auto_backend_sentinel) # type: ignore + +# fmt: on + + ################# REMAINING CONTENT GENERATED BY boilerplate.py ############## From 9f9e7ef6431d3a71aa25c1eccf2249e7b37c137d Mon Sep 17 00:00:00 2001 From: Silke Schomann Date: Mon, 11 Nov 2024 14:57:23 +0000 Subject: [PATCH 13/23] Corrected typo --- src/mslice/plotting/pyplot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mslice/plotting/pyplot.py b/src/mslice/plotting/pyplot.py index d9c195a9..c3e1c558 100644 --- a/src/mslice/plotting/pyplot.py +++ b/src/mslice/plotting/pyplot.py @@ -168,7 +168,7 @@ def _copy_docstring_and_deprecators( ## Global ## -def _draw_all_if_interactive(): -> None: +def _draw_all_if_interactive() -> None: # We will always draw because mslice might be running without # matplotlib interactive for fig in GlobalFigureManager.all_figures(): From 89bb20848916aa97bad698fb33d75a8dc1025f69 Mon Sep 17 00:00:00 2001 From: Silke Schomann Date: Mon, 11 Nov 2024 15:00:38 +0000 Subject: [PATCH 14/23] Corrected more typos --- src/mslice/plotting/pyplot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mslice/plotting/pyplot.py b/src/mslice/plotting/pyplot.py index c3e1c558..867f4893 100644 --- a/src/mslice/plotting/pyplot.py +++ b/src/mslice/plotting/pyplot.py @@ -175,7 +175,7 @@ def _draw_all_if_interactive() -> None: fig.canvas.draw() -def draw_all(): -> None: +def draw_all() -> None: for fig in GlobalFigureManager.all_figures(): fig.canvas.draw_idle() From de0648ad0b3bdd7bec5b21f2c662a6da983cc56a Mon Sep 17 00:00:00 2001 From: Silke Schomann Date: Mon, 11 Nov 2024 15:14:31 +0000 Subject: [PATCH 15/23] Re-generate pyplot after changes --- src/mslice/plotting/pyplot.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/mslice/plotting/pyplot.py b/src/mslice/plotting/pyplot.py index 867f4893..5e985690 100644 --- a/src/mslice/plotting/pyplot.py +++ b/src/mslice/plotting/pyplot.py @@ -2401,7 +2401,7 @@ def figimage( origin: Literal["upper", "lower"] | None = None, resize: bool = False, **kwargs, -) -> matplotlib.image.FigureImage: +) -> FigureImage: return gcf().figimage( X, xo=xo, @@ -2433,7 +2433,7 @@ def gca() -> Axes: # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Figure._gci) -def gci() -> matplotlib.cm.ScalarMappable | None: +def gci() -> ScalarMappable | None: return gcf()._gci() @@ -4060,7 +4060,7 @@ def xcorr( # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes._sci) @set_category(CATEGORY_CUT) -def sci(im: matplotlib.cm.ScalarMappable) -> None: +def sci(im: ScalarMappable) -> None: gca()._sci(im) @@ -4305,7 +4305,7 @@ def tick_params(axis: Literal["both", "x", "y"] = "both", **kwargs) -> None: # Autogenerated by boilerplate.py. Do not edit as changes will be lost. @_copy_docstring_and_deprecators(Axes._sci) -def sci(im: matplotlib.cm.ScalarMappable) -> None: +def sci(im: ScalarMappable) -> None: gca()._sci(im) From 33a59e1932c48dd26e69691dca5de85905b0f3dc Mon Sep 17 00:00:00 2001 From: Silke Schomann Date: Mon, 11 Nov 2024 15:19:18 +0000 Subject: [PATCH 16/23] Matplotlib.ticker instead of .ticker --- src/mslice/plotting/pyplot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mslice/plotting/pyplot.py b/src/mslice/plotting/pyplot.py index 5e985690..4133e96e 100644 --- a/src/mslice/plotting/pyplot.py +++ b/src/mslice/plotting/pyplot.py @@ -109,7 +109,7 @@ from matplotlib.patches import Polygon, Rectangle, Circle, Arrow from matplotlib.widgets import Button, Slider, Widget -from .ticker import ( +from matplotlib.ticker import ( TickHelper, Formatter, FixedFormatter, NullFormatter, FuncFormatter, FormatStrFormatter, ScalarFormatter, LogFormatter, LogFormatterExponent, LogFormatterMathtext, Locator, IndexLocator, FixedLocator, NullLocator, From 5c99e30eb3e6c7692e00bfaaf4898b08999b21bd Mon Sep 17 00:00:00 2001 From: Silke Schomann Date: Mon, 11 Nov 2024 15:40:26 +0000 Subject: [PATCH 17/23] Changed Python version to 3.12 for envs --- .github/actions/publish-package/action.yml | 2 +- README.md | 2 +- environment.yml | 2 +- pyproject.toml | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/actions/publish-package/action.yml b/.github/actions/publish-package/action.yml index 18bbe913..863270ea 100644 --- a/.github/actions/publish-package/action.yml +++ b/.github/actions/publish-package/action.yml @@ -22,7 +22,7 @@ runs: shell: bash -l {0} run: | conda config --set always_yes yes --set changeps1 no - conda create -n build-env python=3.10 + conda create -n build-env python=3.12 conda activate build-env mamba install -c conda-forge mamba conda-build anaconda-client conda-verify boa conda config --add channels mantid/label/nightly diff --git a/README.md b/README.md index 10a8be15..09b0f018 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ You will also need to edit the run configurations: You can now also develop MSlice using a Mantid conda environment. First install Mantid using `conda env create -f mslice-developer.yml`, then add this interpreter by going to the `File->Settings` in PyCharm, then `Project: mslice -> Python Interpreter`, -click the cog on the right side to add an existing interpreter and select `Conda` and `Python 3.10 (mantidnightly)`. +click the cog on the right side to add an existing interpreter and select `Conda` and `Python 3.12 (mantidnightly)`. Then go to `Run -> Edit Configurations` and create new configuration with this interpreter. Specify `start_mslice.py` as the startup script. diff --git a/environment.yml b/environment.yml index 4039100b..bd9c2162 100644 --- a/environment.yml +++ b/environment.yml @@ -13,4 +13,4 @@ dependencies: - pyqt - qtconsole - qtpy - - python=3.10 + - python=3.12 diff --git a/pyproject.toml b/pyproject.toml index a3e65972..0ac3239b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -12,9 +12,9 @@ authors = [ ] description = "Visualise and slice data from Mantid" readme = "README.md" -requires-python = ">=3.10" +requires-python = ">=3.12" classifiers = [ - "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.12", "License :: OSI Approved :: GNU General Public License v3 (GPLv3)", "Operating System :: OS Independent", "Topic :: Scientific/Engineering", From eb656cb25e7fd17206af4b283532a6082219a8f9 Mon Sep 17 00:00:00 2001 From: Silke Schomann Date: Mon, 11 Nov 2024 15:48:01 +0000 Subject: [PATCH 18/23] Remove pin for coveralls --- environment.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/environment.yml b/environment.yml index bd9c2162..c0d87d15 100644 --- a/environment.yml +++ b/environment.yml @@ -5,7 +5,7 @@ channels: - mantid/label/nightly dependencies: - coverage - - coveralls=3.3.1 # Pinned to a version that works with more recent versions of coverage + - coveralls #=3.3.1 # Pinned to a version that works with more recent versions of coverage - ipython - mock - pip From dfbbf3304fe32e6a97139e9fd811c8eb36e7b6d1 Mon Sep 17 00:00:00 2001 From: Silke Schomann Date: Mon, 11 Nov 2024 15:58:58 +0000 Subject: [PATCH 19/23] Follow Mantid with python version --- .github/actions/publish-package/action.yml | 2 +- README.md | 2 +- conda/conda_build_config.yaml | 2 +- environment.yml | 2 +- pyproject.toml | 4 ++-- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/actions/publish-package/action.yml b/.github/actions/publish-package/action.yml index 863270ea..f6cfbc39 100644 --- a/.github/actions/publish-package/action.yml +++ b/.github/actions/publish-package/action.yml @@ -22,7 +22,7 @@ runs: shell: bash -l {0} run: | conda config --set always_yes yes --set changeps1 no - conda create -n build-env python=3.12 + conda create -n build-env conda activate build-env mamba install -c conda-forge mamba conda-build anaconda-client conda-verify boa conda config --add channels mantid/label/nightly diff --git a/README.md b/README.md index 09b0f018..10a8be15 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ You will also need to edit the run configurations: You can now also develop MSlice using a Mantid conda environment. First install Mantid using `conda env create -f mslice-developer.yml`, then add this interpreter by going to the `File->Settings` in PyCharm, then `Project: mslice -> Python Interpreter`, -click the cog on the right side to add an existing interpreter and select `Conda` and `Python 3.12 (mantidnightly)`. +click the cog on the right side to add an existing interpreter and select `Conda` and `Python 3.10 (mantidnightly)`. Then go to `Run -> Edit Configurations` and create new configuration with this interpreter. Specify `start_mslice.py` as the startup script. diff --git a/conda/conda_build_config.yaml b/conda/conda_build_config.yaml index 15919a78..7f60f684 100644 --- a/conda/conda_build_config.yaml +++ b/conda/conda_build_config.yaml @@ -1,2 +1,2 @@ python: - - 3.12 + - '>=3.10' diff --git a/environment.yml b/environment.yml index c0d87d15..a5050d46 100644 --- a/environment.yml +++ b/environment.yml @@ -13,4 +13,4 @@ dependencies: - pyqt - qtconsole - qtpy - - python=3.12 + - python #=3.12 diff --git a/pyproject.toml b/pyproject.toml index 0ac3239b..a3e65972 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -12,9 +12,9 @@ authors = [ ] description = "Visualise and slice data from Mantid" readme = "README.md" -requires-python = ">=3.12" +requires-python = ">=3.10" classifiers = [ - "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.10", "License :: OSI Approved :: GNU General Public License v3 (GPLv3)", "Operating System :: OS Independent", "Topic :: Scientific/Engineering", From d30411b1a4be0fa6fc44f64c0e6577e320df46f3 Mon Sep 17 00:00:00 2001 From: Silke Schomann Date: Mon, 11 Nov 2024 16:05:03 +0000 Subject: [PATCH 20/23] Use mamba instead of conda --- .github/workflows/unit_tests.yml | 2 +- .github/workflows/unit_tests_nightly.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/unit_tests.yml b/.github/workflows/unit_tests.yml index 22da0e45..78018d94 100644 --- a/.github/workflows/unit_tests.yml +++ b/.github/workflows/unit_tests.yml @@ -25,7 +25,7 @@ jobs: - name: Install Mantid run: | - conda install -c mantid/label/nightly mantid mantidqt + mamba install -c mantid/label/nightly mantid mantidqt - name: Run Tests and Coverage run: | diff --git a/.github/workflows/unit_tests_nightly.yml b/.github/workflows/unit_tests_nightly.yml index b850514e..66749997 100644 --- a/.github/workflows/unit_tests_nightly.yml +++ b/.github/workflows/unit_tests_nightly.yml @@ -25,7 +25,7 @@ jobs: - name: Install Mantid run: | - conda install -c mantid/label/nightly mantid mantidqt + mamba install -c mantid/label/nightly mantid mantidqt - name: Run Tests and Coverage run: | From 3621bf142cfe6b2cfd0d1a82380bae72d609b834 Mon Sep 17 00:00:00 2001 From: Silke Schomann Date: Mon, 11 Nov 2024 16:19:23 +0000 Subject: [PATCH 21/23] Pin python in env --- conda/conda_build_config.yaml | 2 +- environment.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/conda/conda_build_config.yaml b/conda/conda_build_config.yaml index 7f60f684..44b5bc9d 100644 --- a/conda/conda_build_config.yaml +++ b/conda/conda_build_config.yaml @@ -1,2 +1,2 @@ python: - - '>=3.10' + - =3.12 diff --git a/environment.yml b/environment.yml index a5050d46..bfdd79ce 100644 --- a/environment.yml +++ b/environment.yml @@ -13,4 +13,4 @@ dependencies: - pyqt - qtconsole - qtpy - - python #=3.12 + - python=3.10 From 56259382871d7facbe3f64f1f5efbb0463e7d099 Mon Sep 17 00:00:00 2001 From: Silke Schomann Date: Tue, 12 Nov 2024 08:37:07 +0000 Subject: [PATCH 22/23] Ignore deprecation warnings --- docs/source/quickstart.rst | 4 ++-- pyproject.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/source/quickstart.rst b/docs/source/quickstart.rst index 1ca5ade8..9a22a1db 100644 --- a/docs/source/quickstart.rst +++ b/docs/source/quickstart.rst @@ -15,8 +15,8 @@ You can then copy the ``mslice`` subfolder (the folder containing a file called ``scripts/ExternalInterfaces/`` folder of *Mantid*, which will make the new version accessible from *MantidWorkbench*. Alternatively, Mslice is available as a conda package via anaconda.org on the `mantid channel `_. -To install the released conda package do ``conda install -c mantid mslice``. -To install the latest nightly conda package do ``conda install -c mantid/label/nightly mslice``. The nightly conda package includes +To install the released conda package do ``mamba install -c mantid mslice``. +To install the latest nightly conda package do ``mamba install -c mantid/label/nightly mslice``. The nightly conda package includes all recent changes of the development version up to and including the day before and is only created when all tests have run successfully. In both cases MSlice can be started by typing ``mslice`` on the command line after activating your conda environment. diff --git a/pyproject.toml b/pyproject.toml index a3e65972..118adce8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -60,7 +60,7 @@ where = ["src"] [tool.pytest.ini_options] pythonpath = ["src"] testpaths = ["tests"] -filterwarnings = ["error"] +filterwarnings = ["error", "ignore::DeprecationWarning"] [tool.coverage.report] include = [ From c07224ad86f70453f6854c92758bbf423656da27 Mon Sep 17 00:00:00 2001 From: Silke Schomann Date: Tue, 12 Nov 2024 08:47:09 +0000 Subject: [PATCH 23/23] Removed unnecessary comment --- environment.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/environment.yml b/environment.yml index bfdd79ce..5a5c2b99 100644 --- a/environment.yml +++ b/environment.yml @@ -5,7 +5,7 @@ channels: - mantid/label/nightly dependencies: - coverage - - coveralls #=3.3.1 # Pinned to a version that works with more recent versions of coverage + - coveralls - ipython - mock - pip