22import typing
33
44from frozendict import frozendict
5+ import numpy as np
56
67from matplotlib .axes import Axes as mpl_Axes
78from matplotlib .collections import PathCollection as mpl_PathCollection
9+ from matplotlib .container import ErrorbarContainer as mpl_ErrorbarContainer
10+
11+ from ._align_marker import align_marker
812
913
1014def draw_edge_marker (
@@ -26,8 +30,7 @@ def draw_edge_marker(
2630 The x and y coordinates of the point.
2731 """
2832 xlim , ylim = ax .get_xlim (), ax .get_ylim ()
29- edge_x , edge_y , marker , annotation = x , y , None , ""
30- ha , va , xytext = "left" , "center" , (5 , 0 ) # default alignment and offset
33+ edge_x , edge_y , markers = x , y , list ()
3134
3235 xwidth = - operator .__sub__ (* xlim )
3336 ywidth = - operator .__sub__ (* ylim )
@@ -36,39 +39,23 @@ def draw_edge_marker(
3639 if x < xlim [0 ]:
3740 amount = int ((xlim [0 ] - x ) / xwidth )
3841 backslash = "\\ "
39- edge_x , marker , annotation , ha = (
40- xlim [0 ] - xoff ,
41- f"$◅{ backslash * amount } $" ,
42- f"{ x :.0f} " ,
43- "right" ,
44- )
42+ edge_x = xlim [0 ] - xoff
43+ markers .append (f"$◅{ backslash * amount } $" )
4544 elif x > xlim [1 ]:
4645 amount = int ((x - xlim [1 ]) / xwidth )
47- edge_x , marker , annotation , ha = (
48- xlim [1 ] + xoff ,
49- rf"$| \!\! \leftrightarrow \!\!|{{\times}}{ amount } \rangle\!\rangle\!\rangle$" ,
50- f"{ x :.0f} " ,
51- "left" ,
52- )
46+ m = rf"$| \!\! \leftrightarrow \!\!|{{\times}}{ amount } \rangle\!\rangle\!\rangle$"
47+ edge_x = xlim [1 ] + xoff
48+ # markers.append(align_marker(m, halign="left"))
49+ markers .append (align_marker (m , halign = "right" , pad = 1.3 ))
5350
5451 if y < ylim [0 ]:
55- edge_y , marker , annotation , va , xytext = (
56- ylim [0 ] - yoff ,
57- "^" ,
58- f"{ y :.2f} " if not annotation else f"({ annotation } , { y :.2f} )" ,
59- "bottom" ,
60- (0 , 5 ),
61- )
52+ edge_y = ylim [0 ] - yoff
53+ markers .append ("^" )
6254 elif y > ylim [1 ]:
63- edge_y , marker , annotation , va , xytext = (
64- ylim [1 ] + yoff ,
65- "v" ,
66- f"{ y :.2f} " if not annotation else f"({ annotation } , { y :.2f} )" ,
67- "top" ,
68- (0 , - 5 ),
69- )
55+ edge_y = ylim [1 ] + yoff
56+ markers .append ("v" )
7057
71- if marker :
58+ for marker in markers :
7259 ax .plot (
7360 edge_x ,
7461 edge_y ,
@@ -84,17 +71,6 @@ def draw_edge_marker(
8471 ** marker_kwargs ,
8572 },
8673 )
87- ax .annotate (
88- annotation ,
89- (edge_x , edge_y ),
90- ** {
91- "ha" : ha ,
92- "va" : va ,
93- "textcoords" : "offset points" ,
94- "xytext" : xytext ,
95- ** annotation_kwargs ,
96- },
97- )
9874
9975 return edge_x , edge_y
10076
@@ -118,19 +94,50 @@ def draw_edge_markers(
11894 for collection in ax .collections :
11995 if isinstance (collection , mpl_PathCollection ):
12096 # Extract points from the line
121- points = list (collection .get_offsets ())
122-
12397 new_offsets = []
124- for x , y in points :
98+ for x , y in collection . get_offsets () :
12599 # Draw edge marker if the point is out of bounds
126100 if x < xlim [0 ] or x > xlim [1 ] or y < ylim [0 ] or y > ylim [1 ]:
127- x_ , y_ = draw_edge_marker (
101+ x , y = draw_edge_marker (
128102 ax ,
129103 x ,
130104 y ,
131105 annotation_kwargs = annotation_kwargs ,
132106 marker_kwargs = marker_kwargs ,
133107 offset = offset ,
134108 )
135- else :
136- new_offsets .append ((x , y ))
109+ new_offsets .append ((x , y ))
110+
111+ collection .set_offsets (new_offsets )
112+ collection .set (clip_on = False )
113+
114+ x_width = - operator .__sub__ (* xlim )
115+ x_thresh = xlim [1 ]
116+ x_offset = x_thresh + x_width * offset
117+ for container in ax .containers :
118+ if isinstance (container , mpl_ErrorbarContainer ):
119+ # Unpack the container
120+ (
121+ plotline , # Line2D instance of x, y plot markers and/or line
122+ caplines , # A tuple of Line2D instances of the error bar caps
123+ # A tuple of LineCollection with the horizontal and vertical
124+ # error ranges.
125+ barlinecols ,
126+ ) = container
127+
128+ # Adjust each error bar
129+ for barlinecol in barlinecols :
130+ segments = barlinecol .get_segments ()
131+ new_segments = []
132+ for segment in segments :
133+ (x0 , y0 ), (x1 , y1 ) = segment
134+ if x0 > x_thresh :
135+ assert x0 == x1
136+ x0 , x1 = x_offset , x_offset
137+ print (f"{ x0 = } , { x1 = } " )
138+ print (f"{ y0 = } , { y1 = } " )
139+ new_segment = [(x0 , y0 ), (x1 , y1 )]
140+ new_segments .append (new_segment )
141+
142+ barlinecol .set_segments (new_segments )
143+ barlinecol .set (clip_on = False )
0 commit comments