@@ -358,7 +358,7 @@ def test_axvline_converts():
358358
359359
360360def test_axline_converts ():
361- """axline converts to a layout shape spanning the whole axes box ."""
361+ """axline converts to a layout shape extended in data coordinates ."""
362362 fig , ax = plt .subplots ()
363363 ax .axline ((0.5 , 0.5 ), slope = 1 )
364364
@@ -368,12 +368,77 @@ def test_axline_converts():
368368 assert len (plotly_fig .layout .shapes ) == 1
369369 shape = plotly_fig .layout .shapes [0 ]
370370 assert shape .type == "line"
371- x0 , x1 = ax .get_xlim ()
372- y0 , y1 = ax .get_ylim ()
373- assert abs (shape .x0 - x0 ) < 1e-9
374- assert abs (shape .x1 - x1 ) < 1e-9
375- assert abs (shape .y0 - y0 ) < 1e-9
376- assert abs (shape .y1 - y1 ) < 1e-9
371+ assert shape .xref == "x"
372+ assert shape .yref == "y"
373+ x_min , x_max = ax .get_xlim ()
374+ assert shape .x0 < x_min
375+ assert shape .x1 > x_max
376+ slope = (shape .y1 - shape .y0 ) / (shape .x1 - shape .x0 )
377+ assert abs (slope - 1.0 ) < 1e-9
378+ # Passes through (0.5, 0.5)
379+ y_at_05 = shape .y0 + slope * (0.5 - shape .x0 )
380+ assert abs (y_at_05 - 0.5 ) < 1e-9
381+
382+
383+ def test_axline_arbitrary_slope_and_limits ():
384+ """axline with non-trivial slopes and limits extends in data coordinates."""
385+ fig , ax = plt .subplots ()
386+ ax .scatter ([1 , 2 , 4 , 7 , 9 ], [2 , 5 , 4 , 8 , 10 ])
387+ ax .axline ((0 , 1 ), slope = 1.0 )
388+ ax .axline ((1 , 8 ), (8 , 2 ))
389+ ax .set_xlim (0 , 10 )
390+ ax .set_ylim (0 , 12 )
391+
392+ plotly_fig = tls .mpl_to_plotly (fig )
393+ shapes = plotly_fig .layout .shapes
394+ assert len (shapes ) == 2
395+
396+ # Line 1: (0, 1), slope 1, xlim [0, 10], ylim [0, 12]
397+ assert shapes [0 ].xref == "x"
398+ assert shapes [0 ].yref == "y"
399+ assert shapes [0 ].x0 < - 500
400+ assert shapes [0 ].x1 > 500
401+ slope1 = (shapes [0 ].y1 - shapes [0 ].y0 ) / (shapes [0 ].x1 - shapes [0 ].x0 )
402+ assert abs (slope1 - 1.0 ) < 1e-9
403+ y_at_0 = shapes [0 ].y0 + slope1 * (0.0 - shapes [0 ].x0 )
404+ assert abs (y_at_0 - 1.0 ) < 1e-9
405+
406+ # Line 2: (1, 8) to (8, 2) with slope -6/7
407+ assert shapes [1 ].xref == "x"
408+ assert shapes [1 ].yref == "y"
409+ assert shapes [1 ].x0 < - 500
410+ assert shapes [1 ].x1 > 500
411+ slope2 = (shapes [1 ].y1 - shapes [1 ].y0 ) / (shapes [1 ].x1 - shapes [1 ].x0 )
412+ assert abs (slope2 - (- 6.0 / 7.0 )) < 1e-9
413+ y_at_1 = shapes [1 ].y0 + slope2 * (1.0 - shapes [1 ].x0 )
414+ assert abs (y_at_1 - 8.0 ) < 1e-9
415+
416+
417+ def test_axline_horizontal_and_vertical ():
418+ """Horizontal and vertical axline use domain coordinates appropriately."""
419+ fig , ax = plt .subplots ()
420+ ax .axline ((0 , 5 ), slope = 0 )
421+ ax .axline ((3 , 0 ), (3 , 10 ))
422+
423+ plotly_fig = tls .mpl_to_plotly (fig )
424+ shapes = plotly_fig .layout .shapes
425+ assert len (shapes ) == 2
426+
427+ # Horizontal axline: xref is domain, y is data
428+ assert shapes [0 ].xref == "x domain"
429+ assert shapes [0 ].yref == "y"
430+ assert abs (shapes [0 ].x0 - 0.0 ) < 1e-9
431+ assert abs (shapes [0 ].x1 - 1.0 ) < 1e-9
432+ assert abs (shapes [0 ].y0 - 5.0 ) < 1e-9
433+ assert abs (shapes [0 ].y1 - 5.0 ) < 1e-9
434+
435+ # Vertical axline: xref is data, yref is domain
436+ assert shapes [1 ].xref == "x"
437+ assert shapes [1 ].yref == "y domain"
438+ assert abs (shapes [1 ].x0 - 3.0 ) < 1e-9
439+ assert abs (shapes [1 ].x1 - 3.0 ) < 1e-9
440+ assert abs (shapes [1 ].y0 - 0.0 ) < 1e-9
441+ assert abs (shapes [1 ].y1 - 1.0 ) < 1e-9
377442
378443
379444def test_axvline_and_axhline_on_date_xaxis ():
0 commit comments