Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 42e5fc0

Browse filesBrowse files
committed
Create axline() using slope
1 parent 17ef13b commit 42e5fc0
Copy full SHA for 42e5fc0

File tree

Expand file treeCollapse file tree

3 files changed

+58
-8
lines changed
Filter options
Expand file treeCollapse file tree

3 files changed

+58
-8
lines changed

‎lib/matplotlib/axes/_axes.py

Copy file name to clipboardExpand all lines: lib/matplotlib/axes/_axes.py
+32-6Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -905,18 +905,27 @@ def axvline(self, x=0, ymin=0, ymax=1, **kwargs):
905905
return l
906906

907907
@docstring.dedent_interpd
908-
def axline(self, xy1, xy2, **kwargs):
908+
def axline(self, xy1, xy2=None, *, slope=None, **kwargs):
909909
"""
910-
Add an infinitely long straight line that passes through two points.
910+
Add an infinitely long straight line.
911+
912+
The line can be defined either by two points *xy1* and *xy2*, or
913+
by one point *xy1* and a *slope*.
911914
912915
This draws a straight line "on the screen", regardless of the x and y
913916
scales, and is thus also suitable for drawing exponential decays in
914-
semilog plots, power laws in loglog plots, etc.
917+
semilog plots, power laws in loglog plots, etc. However, *slope*
918+
should only be used with linear scales; It has no clear meaning for
919+
all other scales, and thus the behavior is undefined. Please specify
920+
the line using the points *xy1*, *xy2* for non-linear scales.
915921
916922
Parameters
917923
----------
918924
xy1, xy2 : (float, float)
919925
Points for the line to pass through.
926+
Either *xy2* or *slope* has to be given.
927+
slope : float, optional
928+
The slope of the line. Either *xy2* or *slope* has to be given.
920929
921930
Returns
922931
-------
@@ -941,12 +950,29 @@ def axline(self, xy1, xy2, **kwargs):
941950
942951
>>> axline((0, 0), (1, 1), linewidth=4, color='r')
943952
"""
953+
def _to_points(xy1, xy2, slope):
954+
"""
955+
Check for a valid combination of input parameters and convert
956+
to two points, if necessary.
957+
"""
958+
if (xy2 is None and slope is None or
959+
xy2 is not None and slope is not None):
960+
raise TypeError(
961+
"Exactly one of 'xy2' and 'slope' must be given")
962+
if xy2 is None:
963+
x1, y1 = xy1
964+
xy2 = (x1, y1 + 1) if np.isinf(slope) else (x1 + 1, y1 + slope)
965+
return xy1, xy2
944966

945967
if "transform" in kwargs:
946968
raise TypeError("'transform' is not allowed as a kwarg; "
947969
"axline generates its own transform")
948-
x1, y1 = xy1
949-
x2, y2 = xy2
970+
if slope is not None and (self.get_xscale() != 'linear' or
971+
self.get_yscale() != 'linear'):
972+
raise TypeError("'slope' cannot be used with non-linear scales")
973+
974+
datalim = [xy1] if xy2 is None else [xy1, xy2]
975+
(x1, y1), (x2, y2) = _to_points(xy1, xy2, slope)
950976
line = mlines._AxLine([x1, x2], [y1, y2], **kwargs)
951977
# Like add_line, but correctly handling data limits.
952978
self._set_artist_props(line)
@@ -956,7 +982,7 @@ def axline(self, xy1, xy2, **kwargs):
956982
line.set_label(f"_line{len(self.lines)}")
957983
self.lines.append(line)
958984
line._remove_method = self.lines.remove
959-
self.update_datalim([xy1, xy2])
985+
self.update_datalim(datalim)
960986

961987
self._request_autoscale_view()
962988
return line

‎lib/matplotlib/pyplot.py

Copy file name to clipboardExpand all lines: lib/matplotlib/pyplot.py
+2-2Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2290,8 +2290,8 @@ def axis(*args, emit=True, **kwargs):
22902290

22912291
# Autogenerated by boilerplate.py. Do not edit as changes will be lost.
22922292
@_copy_docstring_and_deprecators(Axes.axline)
2293-
def axline(xy1, xy2, **kwargs):
2294-
return gca().axline(xy1, xy2, **kwargs)
2293+
def axline(xy1, xy2=None, *, slope=None, **kwargs):
2294+
return gca().axline(xy1, xy2=xy2, slope=slope, **kwargs)
22952295

22962296

22972297
# Autogenerated by boilerplate.py. Do not edit as changes will be lost.

‎lib/matplotlib/tests/test_axes.py

Copy file name to clipboardExpand all lines: lib/matplotlib/tests/test_axes.py
+24Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3929,12 +3929,36 @@ def test_axline(fig_test, fig_ref):
39293929
ax.axline((0, 0), (1, 1))
39303930
ax.axline((0, 0), (1, 0), color='C1')
39313931
ax.axline((0, 0.5), (1, 0.5), color='C2')
3932+
# slopes
3933+
ax.axline((-0.7, -0.5), slope=0, color='C3')
3934+
ax.axline((1, -0.5), slope=-0.5, color='C4')
3935+
ax.axline((-0.5, 1), slope=float('inf'), color='C5')
39323936

39333937
ax = fig_ref.subplots()
39343938
ax.set(xlim=(-1, 1), ylim=(-1, 1))
39353939
ax.plot([-1, 1], [-1, 1])
39363940
ax.axhline(0, color='C1')
39373941
ax.axhline(0.5, color='C2')
3942+
# slopes
3943+
ax.axhline(-0.5, color='C3')
3944+
ax.plot([-1, 1], [0.5, -0.5], color='C4')
3945+
ax.axvline(-0.5, color='C5')
3946+
3947+
3948+
def test_axline_args():
3949+
"""Exactly one of *xy2* and *slope* must be specified."""
3950+
fig, ax = plt.subplots()
3951+
with pytest.raises(TypeError):
3952+
ax.axline((0, 0)) # missing second parameter
3953+
with pytest.raises(TypeError):
3954+
ax.axline((0, 0), (1, 1), slope=1) # redundant parameters
3955+
ax.set_xscale('log')
3956+
with pytest.raises(TypeError):
3957+
ax.axline((0, 0), slope=1)
3958+
ax.set_xscale('linear')
3959+
ax.set_yscale('log')
3960+
with pytest.raises(TypeError):
3961+
ax.axline((0, 0), slope=1)
39383962

39393963

39403964
@image_comparison(['vlines_basic', 'vlines_with_nan', 'vlines_masked'],

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.