@@ -614,6 +614,10 @@ def __str__(self):
614614 return "{0}({1[0]:g},{1[1]:g};{1[2]:g}x{1[3]:g})" .format (
615615 type (self ).__name__ , self ._position .bounds )
616616
617+ def set_zorder (self , level ):
618+ super ().set_zorder (level )
619+ self ._update_twinned_axes_patch_visibility ()
620+
617621 def __init__ (self , fig ,
618622 * args ,
619623 facecolor = None , # defaults to rc axes.facecolor
@@ -2470,20 +2474,6 @@ def _add_text(self, txt):
24702474 self .stale = True
24712475 return txt
24722476
2473- def _point_in_data_domain (self , x , y ):
2474- """
2475- Check if the data point (x, y) is within the valid domain of the axes
2476- scales.
2477-
2478- Returns False if the point is outside the data range
2479- (e.g. negative coordinates with a log scale).
2480- """
2481- for val , axis in zip ([x , y ], self ._axis_map .values ()):
2482- vmin , vmax = axis .limit_range_for_scale (val , val )
2483- if vmin != val or vmax != val :
2484- return False
2485- return True
2486-
24872477 def _update_line_limits (self , line ):
24882478 """
24892479 Figures out the data limit of the given line, updating `.Axes.dataLim`.
@@ -3316,6 +3306,7 @@ def set_frame_on(self, b):
33163306 b : bool
33173307 """
33183308 self ._frameon = b
3309+ self ._update_twinned_axes_patch_visibility ()
33193310 self .stale = True
33203311
33213312 def get_axisbelow (self ):
@@ -4683,7 +4674,31 @@ def get_tightbbox(self, renderer=None, *, call_axes_locator=True,
46834674 return mtransforms .Bbox .union (
46844675 [b for b in bb if b .width != 0 or b .height != 0 ])
46854676
4686- def _make_twin_axes (self , * args , ** kwargs ):
4677+ def _update_twinned_axes_patch_visibility (self ):
4678+ """
4679+ Update patch visibility for a group of twinned Axes.
4680+
4681+ Only the bottom-most Axes in the group (lowest zorder, breaking ties by
4682+ creation/insertion order) has a visible background patch.
4683+ """
4684+ if self not in self ._twinned_axes :
4685+ return
4686+ twinned = list (self ._twinned_axes .get_siblings (self ))
4687+ if not twinned :
4688+ return
4689+ fig = self .get_figure (root = False )
4690+ fig_axes = fig .axes if fig is not None else []
4691+ insertion_order = {ax : idx for idx , ax in enumerate (fig_axes )}
4692+
4693+ twinned .sort (key = lambda ax : (ax .get_zorder (),
4694+ insertion_order .get (ax , len (fig_axes ))))
4695+ bottom = twinned [0 ]
4696+ for ax in twinned :
4697+ patch = getattr (ax , "patch" , None )
4698+ if patch is not None :
4699+ patch .set_visible ((ax is bottom ) and ax .get_frame_on ())
4700+
4701+ def _make_twin_axes (self , * args , delta_zorder = None , ** kwargs ):
46874702 """Make a twinx Axes of self. This is used for twinx and twiny."""
46884703 if 'sharex' in kwargs and 'sharey' in kwargs :
46894704 # The following line is added in v2.2 to avoid breaking Seaborn,
@@ -4700,12 +4715,15 @@ def _make_twin_axes(self, *args, **kwargs):
47004715 [0 , 0 , 1 , 1 ], self .transAxes ))
47014716 self .set_adjustable ('datalim' )
47024717 twin .set_adjustable ('datalim' )
4703- twin .set_zorder (self .zorder )
4718+ original_zorder = self .get_zorder ()
4719+ twin .set_zorder (original_zorder if delta_zorder is None
4720+ else original_zorder + delta_zorder )
47044721
47054722 self ._twinned_axes .join (self , twin )
4723+ self ._update_twinned_axes_patch_visibility ()
47064724 return twin
47074725
4708- def twinx (self , axes_class = None , ** kwargs ):
4726+ def twinx (self , axes_class = None , * , delta_zorder = None , * *kwargs ):
47094727 """
47104728 Create a twin Axes sharing the xaxis.
47114729
@@ -4726,6 +4744,12 @@ def twinx(self, axes_class=None, **kwargs):
47264744
47274745 .. versionadded:: 3.11
47284746
4747+ delta_zorder : float, optional
4748+ A zorder offset for the twin Axes, relative to the original Axes.
4749+ The twin's zorder is set to ``self.get_zorder() + delta_zorder``.
4750+ By default (*delta_zorder* is None), the twin has the same zorder
4751+ as the original Axes.
4752+
47294753 kwargs : dict
47304754 The keyword arguments passed to `.Figure.add_subplot` or `.Figure.add_axes`.
47314755
@@ -4743,18 +4767,18 @@ def twinx(self, axes_class=None, **kwargs):
47434767 """
47444768 if axes_class :
47454769 kwargs ["axes_class" ] = axes_class
4746- ax2 = self ._make_twin_axes (sharex = self , ** kwargs )
4770+ ax2 = self ._make_twin_axes (sharex = self , delta_zorder = delta_zorder ,
4771+ ** kwargs )
47474772 ax2 .yaxis .tick_right ()
47484773 ax2 .yaxis .set_label_position ('right' )
47494774 ax2 .yaxis .set_offset_position ('right' )
47504775 ax2 .set_autoscalex_on (self .get_autoscalex_on ())
47514776 self .yaxis .tick_left ()
47524777 ax2 .xaxis .set_visible (False )
4753- ax2 .patch .set_visible (False )
47544778 ax2 .xaxis .units = self .xaxis .units
47554779 return ax2
47564780
4757- def twiny (self , axes_class = None , ** kwargs ):
4781+ def twiny (self , axes_class = None , * , delta_zorder = None , * *kwargs ):
47584782 """
47594783 Create a twin Axes sharing the yaxis.
47604784
@@ -4775,6 +4799,12 @@ def twiny(self, axes_class=None, **kwargs):
47754799
47764800 .. versionadded:: 3.11
47774801
4802+ delta_zorder : float, optional
4803+ A zorder offset for the twin Axes, relative to the original Axes.
4804+ The twin's zorder is set to ``self.get_zorder() + delta_zorder``.
4805+ By default (*delta_zorder* is None), the twin has the same zorder
4806+ as the original Axes.
4807+
47784808 kwargs : dict
47794809 The keyword arguments passed to `.Figure.add_subplot` or `.Figure.add_axes`.
47804810
@@ -4792,13 +4822,13 @@ def twiny(self, axes_class=None, **kwargs):
47924822 """
47934823 if axes_class :
47944824 kwargs ["axes_class" ] = axes_class
4795- ax2 = self ._make_twin_axes (sharey = self , ** kwargs )
4825+ ax2 = self ._make_twin_axes (sharey = self , delta_zorder = delta_zorder ,
4826+ ** kwargs )
47964827 ax2 .xaxis .tick_top ()
47974828 ax2 .xaxis .set_label_position ('top' )
47984829 ax2 .set_autoscaley_on (self .get_autoscaley_on ())
47994830 self .xaxis .tick_bottom ()
48004831 ax2 .yaxis .set_visible (False )
4801- ax2 .patch .set_visible (False )
48024832 ax2 .yaxis .units = self .yaxis .units
48034833 return ax2
48044834
0 commit comments