Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Deprecate positional use of most arguments of plotting functions #27786

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions doc/api/next_api_changes/deprecations/27786-TH.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Positional parameters in plotting functions
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Many plotting functions will restrict positional arguments to the first few parameters
in the future. All further configuration parameters will have to be passed as keyword
Comment on lines +4 to +5
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any way to have some measure of consistency on which parameters are positional only (like for example the data parameters?)

Copy link
Member Author

@timhoffm timhoffm Feb 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The central question is: Is code using the positional parameters understandable without knowing the signature? Mostly this results in positional data parameters. But with some exceptions:

  • fmt is allowed positionally - inspired by plot
  • I’ve still allowed bins in histograms because from hist(data, 20) it's conceivable that the inter is bins(debatable, but err on the permissive side)
  • With hlines I've gone to the extreme and still allowed color and linestyles because if somebody has written hlines(y, xmin, xmax, 'red', 'dashed') that's quite clear and I don't want to break their code.

arguments. This is to enforce better code and and allow for future changes with reduced
risk of breaking existing code.
2 changes: 1 addition & 1 deletion galleries/examples/lines_bars_and_markers/cohere.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
axs[0].set_ylabel('s1 and s2')
axs[0].grid(True)

cxy, f = axs[1].cohere(s1, s2, 256, 1. / dt)
cxy, f = axs[1].cohere(s1, s2, NFFT=256, Fs=1. / dt)
axs[1].set_ylabel('Coherence')

plt.show()
2 changes: 1 addition & 1 deletion galleries/examples/lines_bars_and_markers/csd_demo.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
ax1.set_ylabel('s1 and s2')
ax1.grid(True)

cxy, f = ax2.csd(s1, s2, 256, 1. / dt)
cxy, f = ax2.csd(s1, s2, NFFT=256, Fs=1. / dt)
ax2.set_ylabel('CSD (dB)')

plt.show()
2 changes: 1 addition & 1 deletion galleries/examples/lines_bars_and_markers/psd_demo.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
ax0.plot(t, s)
ax0.set_xlabel('Time (s)')
ax0.set_ylabel('Signal')
ax1.psd(s, 512, 1 / dt)
ax1.psd(s, NFFT=512, Fs=1 / dt)

plt.show()

Expand Down
10 changes: 5 additions & 5 deletions galleries/examples/statistics/boxplot_demo.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,23 +34,23 @@
axs[0, 0].set_title('basic plot')

# notched plot
axs[0, 1].boxplot(data, 1)
axs[0, 1].boxplot(data, notch=True)
axs[0, 1].set_title('notched plot')

# change outlier point symbols
axs[0, 2].boxplot(data, 0, 'gD')
axs[0, 2].boxplot(data, sym='gD')
axs[0, 2].set_title('change outlier\npoint symbols')

# don't show outlier points
axs[1, 0].boxplot(data, 0, '')
axs[1, 0].boxplot(data, sym='')
axs[1, 0].set_title("don't show\noutlier points")

# horizontal boxes
axs[1, 1].boxplot(data, 0, 'rs', 0)
axs[1, 1].boxplot(data, sym='rs', vert=False)
axs[1, 1].set_title('horizontal boxes')

# change whisker length
axs[1, 2].boxplot(data, 0, 'rs', 0, 0.75)
axs[1, 2].boxplot(data, sym='rs', vert=False, whis=0.75)
axs[1, 2].set_title('change whisker length')

fig.subplots_adjust(left=0.08, right=0.98, bottom=0.05, top=0.9,
Expand Down
3 changes: 2 additions & 1 deletion lib/matplotlib/_api/deprecation.py
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,8 @@ def make_keyword_only(since, name, func=None):
assert (name in signature.parameters
and signature.parameters[name].kind == POK), (
f"Matplotlib internal error: {name!r} must be a positional-or-keyword "
f"parameter for {func.__name__}()")
f"parameter for {func.__name__}(). If this error happens on a function with a "
f"pyplot wrapper, make sure make_keyword_only() is the outermost decorator.")
names = [*signature.parameters]
name_idx = names.index(name)
kwonly = [name for name in names[name_idx:]
Expand Down
22 changes: 22 additions & 0 deletions lib/matplotlib/axes/_axes.py
Original file line number Diff line number Diff line change
Expand Up @@ -1100,6 +1100,7 @@ def axvspan(self, xmin, xmax, ymin=0, ymax=1, **kwargs):
self._request_autoscale_view("x")
return p

@_api.make_keyword_only("3.9", "label")
@_preprocess_data(replace_names=["y", "xmin", "xmax", "colors"],
label_namer="y")
def hlines(self, y, xmin, xmax, colors=None, linestyles='solid',
Expand Down Expand Up @@ -1191,6 +1192,7 @@ def hlines(self, y, xmin, xmax, colors=None, linestyles='solid',
self._request_autoscale_view()
return lines

@_api.make_keyword_only("3.9", "label")
@_preprocess_data(replace_names=["x", "ymin", "ymax", "colors"],
label_namer="x")
def vlines(self, x, ymin, ymax, colors=None, linestyles='solid',
Expand Down Expand Up @@ -1282,6 +1284,7 @@ def vlines(self, x, ymin, ymax, colors=None, linestyles='solid',
self._request_autoscale_view()
return lines

@_api.make_keyword_only("3.9", "orientation")
@_preprocess_data(replace_names=["positions", "lineoffsets",
"linelengths", "linewidths",
"colors", "linestyles"])
Expand Down Expand Up @@ -2088,6 +2091,7 @@ def acorr(self, x, **kwargs):
"""
return self.xcorr(x, x, **kwargs)

@_api.make_keyword_only("3.9", "normed")
@_preprocess_data(replace_names=["x", "y"], label_namer="y")
def xcorr(self, x, y, normed=True, detrend=mlab.detrend_none,
usevlines=True, maxlags=10, **kwargs):
Expand Down Expand Up @@ -3155,6 +3159,7 @@ def stem(self, *args, linefmt=None, markerfmt=None, basefmt=None, bottom=0,
self.add_container(stem_container)
return stem_container

@_api.make_keyword_only("3.9", "explode")
@_preprocess_data(replace_names=["x", "explode", "labels", "colors"])
def pie(self, x, explode=None, labels=None, colors=None,
autopct=None, pctdistance=0.6, shadow=False, labeldistance=1.1,
Expand Down Expand Up @@ -3434,6 +3439,7 @@ def _errorevery_to_mask(x, errorevery):
everymask[errorevery] = True
return everymask

@_api.make_keyword_only("3.9", "ecolor")
@_preprocess_data(replace_names=["x", "y", "xerr", "yerr"],
label_namer="y")
@_docstring.dedent_interpd
Expand Down Expand Up @@ -3810,6 +3816,7 @@ def apply_mask(arrays, mask):

return errorbar_container # (l0, caplines, barcols)

@_api.make_keyword_only("3.9", "notch")
@_preprocess_data()
@_api.rename_parameter("3.9", "labels", "tick_labels")
def boxplot(self, x, notch=None, sym=None, vert=None, whis=None,
Expand Down Expand Up @@ -4144,6 +4151,7 @@ def boxplot(self, x, notch=None, sym=None, vert=None, whis=None,
capwidths=capwidths, label=label)
return artists

@_api.make_keyword_only("3.9", "widths")
def bxp(self, bxpstats, positions=None, widths=None, vert=True,
patch_artist=False, shownotches=False, showmeans=False,
showcaps=True, showbox=True, showfliers=True,
Expand Down Expand Up @@ -4636,6 +4644,7 @@ def invalid_shape_exception(csize, xsize):
colors = None # use cmap, norm after collection is created
return c, colors, edgecolors

@_api.make_keyword_only("3.9", "marker")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can see an arguament for pushing this one deeper

ax.scatter(x, y, s, c, 'o')

scans reasonably well, but I suspect is rare.

@_preprocess_data(replace_names=["x", "y", "s", "linewidths",
"edgecolors", "c", "facecolor",
"facecolors", "color"],
Expand Down Expand Up @@ -4916,6 +4925,7 @@ def scatter(self, x, y, s=None, c=None, marker=None, cmap=None, norm=None,

return collection

@_api.make_keyword_only("3.9", "gridsize")
@_preprocess_data(replace_names=["x", "y", "C"], label_namer="y")
@_docstring.dedent_interpd
def hexbin(self, x, y, C=None, gridsize=100, bins=None,
Expand Down Expand Up @@ -6698,6 +6708,7 @@ def clabel(self, CS, levels=None, **kwargs):

#### Data analysis

@_api.make_keyword_only("3.9", "range")
@_preprocess_data(replace_names=["x", 'weights'], label_namer="x")
def hist(self, x, bins=None, range=None, density=False, weights=None,
cumulative=False, bottom=None, histtype='bar', align='mid',
Expand Down Expand Up @@ -7245,6 +7256,7 @@ def stairs(self, values, edges=None, *,
self._request_autoscale_view()
return patch

@_api.make_keyword_only("3.9", "range")
@_preprocess_data(replace_names=["x", "y", "weights"])
@_docstring.dedent_interpd
def hist2d(self, x, y, bins=10, range=None, density=False, weights=None,
Expand Down Expand Up @@ -7454,6 +7466,7 @@ def ecdf(self, x, weights=None, *, complementary=False,
line.sticky_edges.x[:] = [0, 1]
return line

@_api.make_keyword_only("3.9", "NFFT")
@_preprocess_data(replace_names=["x"])
@_docstring.dedent_interpd
def psd(self, x, NFFT=None, Fs=None, Fc=None, detrend=None,
Expand Down Expand Up @@ -7565,6 +7578,7 @@ def psd(self, x, NFFT=None, Fs=None, Fc=None, detrend=None,
else:
return pxx, freqs, line

@_api.make_keyword_only("3.9", "NFFT")
@_preprocess_data(replace_names=["x", "y"], label_namer="y")
@_docstring.dedent_interpd
def csd(self, x, y, NFFT=None, Fs=None, Fc=None, detrend=None,
Expand Down Expand Up @@ -7667,6 +7681,7 @@ def csd(self, x, y, NFFT=None, Fs=None, Fc=None, detrend=None,
else:
return pxy, freqs, line

@_api.make_keyword_only("3.9", "Fs")
@_preprocess_data(replace_names=["x"])
@_docstring.dedent_interpd
def magnitude_spectrum(self, x, Fs=None, Fc=None, window=None,
Expand Down Expand Up @@ -7753,6 +7768,7 @@ def magnitude_spectrum(self, x, Fs=None, Fc=None, window=None,

return spec, freqs, line

@_api.make_keyword_only("3.9", "Fs")
@_preprocess_data(replace_names=["x"])
@_docstring.dedent_interpd
def angle_spectrum(self, x, Fs=None, Fc=None, window=None,
Expand Down Expand Up @@ -7822,6 +7838,7 @@ def angle_spectrum(self, x, Fs=None, Fc=None, window=None,

return spec, freqs, lines[0]

@_api.make_keyword_only("3.9", "Fs")
@_preprocess_data(replace_names=["x"])
@_docstring.dedent_interpd
def phase_spectrum(self, x, Fs=None, Fc=None, window=None,
Expand Down Expand Up @@ -7891,6 +7908,7 @@ def phase_spectrum(self, x, Fs=None, Fc=None, window=None,

return spec, freqs, lines[0]

@_api.make_keyword_only("3.9", "NFFT")
@_preprocess_data(replace_names=["x", "y"])
@_docstring.dedent_interpd
def cohere(self, x, y, NFFT=256, Fs=2, Fc=0, detrend=mlab.detrend_none,
Expand Down Expand Up @@ -7955,6 +7973,7 @@ def cohere(self, x, y, NFFT=256, Fs=2, Fc=0, detrend=mlab.detrend_none,

return cxy, freqs

@_api.make_keyword_only("3.9", "NFFT")
@_preprocess_data(replace_names=["x"])
@_docstring.dedent_interpd
def specgram(self, x, NFFT=None, Fs=None, Fc=None, detrend=None,
Expand Down Expand Up @@ -8111,6 +8130,7 @@ def specgram(self, x, NFFT=None, Fs=None, Fc=None, detrend=None,

return spec, freqs, t, im

@_api.make_keyword_only("3.9", "precision")
@_docstring.dedent_interpd
def spy(self, Z, precision=0, marker=None, markersize=None,
aspect='equal', origin="upper", **kwargs):
Expand Down Expand Up @@ -8301,6 +8321,7 @@ def matshow(self, Z, **kwargs):
mticker.MaxNLocator(nbins=9, steps=[1, 2, 5, 10], integer=True))
return im

@_api.make_keyword_only("3.9", "vert")
@_preprocess_data(replace_names=["dataset"])
def violinplot(self, dataset, positions=None, vert=True, widths=0.5,
showmeans=False, showextrema=True, showmedians=False,
Expand Down Expand Up @@ -8412,6 +8433,7 @@ def _kde_method(X, coords):
widths=widths, showmeans=showmeans,
showextrema=showextrema, showmedians=showmedians, side=side)

@_api.make_keyword_only("3.9", "vert")
def violin(self, vpstats, positions=None, vert=True, widths=0.5,
showmeans=False, showextrema=True, showmedians=False, side='both'):
"""
Expand Down
Loading