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

Skip to content

Commit c65e836

Browse files
committed
Create axline() using slope
1 parent c58ca60 commit c65e836

File tree

3 files changed

+57
-8
lines changed

3 files changed

+57
-8
lines changed

lib/matplotlib/axes/_axes.py

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -904,18 +904,26 @@ def axvline(self, x=0, ymin=0, ymax=1, **kwargs):
904904
return l
905905

906906
@docstring.dedent_interpd
907-
def axline(self, xy1, xy2, **kwargs):
907+
def axline(self, xy1, xy2=None, *, slope=None, **kwargs):
908908
"""
909-
Add an infinitely long straight line that passes through two points.
909+
Add an infinitely long straight line.
910+
911+
The line can be defined either by two points *xy1* and *xy2*, or
912+
by one point *xy1* and a *slope*.
910913
911914
This draws a straight line "on the screen", regardless of the x and y
912915
scales, and is thus also suitable for drawing exponential decays in
913-
semilog plots, power laws in loglog plots, etc.
916+
semilog plots, power laws in loglog plots, etc. However, *slope*
917+
can only be used with linear scales; for all other scales, please
918+
specify the line using the points *xy1*, *xy2*.
914919
915920
Parameters
916921
----------
917922
xy1, xy2 : (float, float)
918923
Points for the line to pass through.
924+
Either *xy2* or *slope* has to be given.
925+
slope : float, optional
926+
The slope of the line. Either *xy2* or *slope* has to be given.
919927
920928
Returns
921929
-------
@@ -940,12 +948,29 @@ def axline(self, xy1, xy2, **kwargs):
940948
axhline : for horizontal lines
941949
axvline : for vertical lines
942950
"""
951+
def _to_points(xy1, xy2, slope):
952+
"""
953+
Check for a valid combination of input parameters and convert
954+
to two points, if necessary.
955+
"""
956+
if (xy2 is None and slope is None or
957+
xy2 is not None and slope is not None):
958+
raise TypeError(
959+
"Exactly one of 'xy2' and 'slope' must be given")
960+
if xy2 is None:
961+
x1, y1 = xy1
962+
xy2 = (x1, y1 + 1) if np.isinf(slope) else (x1 + 1, y1 + slope)
963+
return xy1, xy2
943964

944965
if "transform" in kwargs:
945966
raise TypeError("'transform' is not allowed as a kwarg; "
946967
"axline generates its own transform")
947-
x1, y1 = xy1
948-
x2, y2 = xy2
968+
if slope is not None and (self.get_xscale() != 'linear' or
969+
self.get_yscale() != 'linear'):
970+
raise TypeError("'slope' cannot be used with non-linear scales")
971+
972+
datalim = [xy1] if xy2 is None else [xy1, xy2]
973+
(x1, y1), (x2, y2) = _to_points(xy1, xy2, slope)
949974
line = mlines._AxLine([x1, x2], [y1, y2], **kwargs)
950975
# Like add_line, but correctly handling data limits.
951976
self._set_artist_props(line)
@@ -955,7 +980,7 @@ def axline(self, xy1, xy2, **kwargs):
955980
line.set_label(f"_line{len(self.lines)}")
956981
self.lines.append(line)
957982
line._remove_method = self.lines.remove
958-
self.update_datalim([xy1, xy2])
983+
self.update_datalim(datalim)
959984

960985
self._request_autoscale_view()
961986
return line

lib/matplotlib/pyplot.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2208,8 +2208,8 @@ def axis(*args, emit=True, **kwargs):
22082208

22092209
# Autogenerated by boilerplate.py. Do not edit as changes will be lost.
22102210
@docstring.copy(Axes.axline)
2211-
def axline(xy1, xy2, **kwargs):
2212-
return gca().axline(xy1, xy2, **kwargs)
2211+
def axline(xy1, xy2=None, *, slope=None, **kwargs):
2212+
return gca().axline(xy1, xy2=xy2, slope=slope, **kwargs)
22132213

22142214

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

lib/matplotlib/tests/test_axes.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3833,12 +3833,36 @@ def test_axline(fig_test, fig_ref):
38333833
ax.axline((0, 0), (1, 1))
38343834
ax.axline((0, 0), (1, 0), color='C1')
38353835
ax.axline((0, 0.5), (1, 0.5), color='C2')
3836+
# slopes
3837+
ax.axline((-0.7, -0.5), slope=0, color='C3')
3838+
ax.axline((1, -0.5), slope=-0.5, color='C4')
3839+
ax.axline((-0.5, 1), slope=float('inf'), color='C5')
38363840

38373841
ax = fig_ref.subplots()
38383842
ax.set(xlim=(-1, 1), ylim=(-1, 1))
38393843
ax.plot([-1, 1], [-1, 1])
38403844
ax.axhline(0, color='C1')
38413845
ax.axhline(0.5, color='C2')
3846+
# slopes
3847+
ax.axhline(-0.5, color='C3')
3848+
ax.plot([-1, 1], [0.5, -0.5], color='C4')
3849+
ax.axvline(-0.5, color='C5')
3850+
3851+
3852+
def test_axline_args():
3853+
"""Exactly one of *xy2* and *slope* must be specified."""
3854+
fig, ax = plt.subplots()
3855+
with pytest.raises(TypeError):
3856+
ax.axline((0, 0)) # missing second parameter
3857+
with pytest.raises(TypeError):
3858+
ax.axline((0, 0), (1, 1), slope=1) # redundant parameters
3859+
ax.set_xscale('log')
3860+
with pytest.raises(TypeError):
3861+
ax.axline((0, 0), slope=1)
3862+
ax.set_xscale('linear')
3863+
ax.set_yscale('log')
3864+
with pytest.raises(TypeError):
3865+
ax.axline((0, 0), slope=1)
38423866

38433867

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

0 commit comments

Comments
 (0)