@@ -904,18 +904,26 @@ def axvline(self, x=0, ymin=0, ymax=1, **kwargs):
904
904
return l
905
905
906
906
@docstring .dedent_interpd
907
- def axline (self , xy1 , xy2 , ** kwargs ):
907
+ def axline (self , xy1 , xy2 = None , * , slope = None , ** kwargs ):
908
908
"""
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*.
910
913
911
914
This draws a straight line "on the screen", regardless of the x and y
912
915
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*.
914
919
915
920
Parameters
916
921
----------
917
922
xy1, xy2 : (float, float)
918
923
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.
919
927
920
928
Returns
921
929
-------
@@ -940,12 +948,29 @@ def axline(self, xy1, xy2, **kwargs):
940
948
axhline : for horizontal lines
941
949
axvline : for vertical lines
942
950
"""
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
943
964
944
965
if "transform" in kwargs :
945
966
raise TypeError ("'transform' is not allowed as a kwarg; "
946
967
"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 )
949
974
line = mlines ._AxLine ([x1 , x2 ], [y1 , y2 ], ** kwargs )
950
975
# Like add_line, but correctly handling data limits.
951
976
self ._set_artist_props (line )
@@ -955,7 +980,7 @@ def axline(self, xy1, xy2, **kwargs):
955
980
line .set_label (f"_line{ len (self .lines )} " )
956
981
self .lines .append (line )
957
982
line ._remove_method = self .lines .remove
958
- self .update_datalim ([ xy1 , xy2 ] )
983
+ self .update_datalim (datalim )
959
984
960
985
self ._request_autoscale_view ()
961
986
return line
0 commit comments