@@ -905,18 +905,27 @@ def axvline(self, x=0, ymin=0, ymax=1, **kwargs):
905
905
return l
906
906
907
907
@docstring .dedent_interpd
908
- def axline (self , xy1 , xy2 , ** kwargs ):
908
+ def axline (self , xy1 , xy2 = None , * , slope = None , ** kwargs ):
909
909
"""
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*.
911
914
912
915
This draws a straight line "on the screen", regardless of the x and y
913
916
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.
915
921
916
922
Parameters
917
923
----------
918
924
xy1, xy2 : (float, float)
919
925
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.
920
929
921
930
Returns
922
931
-------
@@ -941,12 +950,29 @@ def axline(self, xy1, xy2, **kwargs):
941
950
942
951
>>> axline((0, 0), (1, 1), linewidth=4, color='r')
943
952
"""
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
944
966
945
967
if "transform" in kwargs :
946
968
raise TypeError ("'transform' is not allowed as a kwarg; "
947
969
"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 )
950
976
line = mlines ._AxLine ([x1 , x2 ], [y1 , y2 ], ** kwargs )
951
977
# Like add_line, but correctly handling data limits.
952
978
self ._set_artist_props (line )
@@ -956,7 +982,7 @@ def axline(self, xy1, xy2, **kwargs):
956
982
line .set_label (f"_line{ len (self .lines )} " )
957
983
self .lines .append (line )
958
984
line ._remove_method = self .lines .remove
959
- self .update_datalim ([ xy1 , xy2 ] )
985
+ self .update_datalim (datalim )
960
986
961
987
self ._request_autoscale_view ()
962
988
return line
0 commit comments