@@ -550,36 +550,36 @@ def __init__(self, major):
550550 def __get__ (self , instance , owner ):
551551 if instance is None :
552552 return self
553+ # instance._get_tick() can itself try to access the majorTicks
554+ # attribute (e.g. in certain projection classes which override
555+ # e.g. get_xaxis_text1_transform). In order to avoid infinite
556+ # recursion, first set the majorTicks on the instance temporarily
557+ # to an empty list. Then create the tick; note that _get_tick()
558+ # may call reset_ticks(). Therefore, the final tick list is
559+ # created and assigned afterwards.
560+ attr = 'majorTicks' if self ._major else 'minorTicks'
561+ setattr (instance , attr , [])
562+ # Build the Tick (and its sub-artists) under the rcParams snapshot
563+ # taken at the last ``Axis.clear`` so that a lazily-materialized
564+ # Tick matches the values an eager (pre-lazy) Tick would have had
565+ # (see ``Axis._rc_snapshot``). Use ``_update_raw`` rather than
566+ # ``rc_context`` to bypass validators that would otherwise fire
567+ # spurious warnings when re-applying settings like
568+ # ``rcParams['toolbar'] = 'toolmanager'``.
569+ snapshot = instance ._rc_snapshot
570+ if snapshot is not None :
571+ rc = mpl .rcParams
572+ orig = dict (rc )
573+ rc ._update_raw (snapshot )
574+ try :
575+ tick = instance ._get_tick (major = self ._major )
576+ finally :
577+ rc ._update_raw (orig )
553578 else :
554- # instance._get_tick() can itself try to access the majorTicks
555- # attribute (e.g. in certain projection classes which override
556- # e.g. get_xaxis_text1_transform). In order to avoid infinite
557- # recursion, first set the majorTicks on the instance temporarily
558- # to an empty list. Then create the tick; note that _get_tick()
559- # may call reset_ticks(). Therefore, the final tick list is
560- # created and assigned afterwards.
561- if self ._major :
562- instance .majorTicks = []
563- tick = instance ._get_tick (major = True )
564- tick .clipbox = instance .clipbox
565- tick ._clippath = instance ._clippath
566- tick ._clipon = instance ._clipon
567- tick .gridline .clipbox = instance .clipbox
568- tick .gridline ._clippath = instance ._clippath
569- tick .gridline ._clipon = instance ._clipon
570- instance .majorTicks = [tick ]
571- return instance .majorTicks
572- else :
573- instance .minorTicks = []
574- tick = instance ._get_tick (major = False )
575- tick .clipbox = instance .clipbox
576- tick ._clippath = instance ._clippath
577- tick ._clipon = instance ._clipon
578- tick .gridline .clipbox = instance .clipbox
579- tick .gridline ._clippath = instance ._clippath
580- tick .gridline ._clipon = instance ._clipon
581- instance .minorTicks = [tick ]
582- return instance .minorTicks
579+ tick = instance ._get_tick (major = self ._major )
580+ instance ._propagate_axis_state_to_tick (tick )
581+ setattr (instance , attr , [tick ])
582+ return getattr (instance , attr )
583583
584584
585585class Axis (martist .Artist ):
@@ -684,6 +684,13 @@ def __init__(self, axes, *, pickradius=15, clear=True):
684684 # Initialize here for testing; later add API
685685 self ._major_tick_kw = dict ()
686686 self ._minor_tick_kw = dict ()
687+ # Snapshot of rcParams at the time of the last ``Axis.clear`` (or
688+ # ``set_tick_params(reset=True)``). ``_LazyTickList`` applies this
689+ # via ``rc_context`` when it lazily creates a Tick so that the Tick
690+ # and its sub-artists see the same rcParams an eager (pre-lazy)
691+ # materialization would have seen. See ``_propagate_axis_state_to_tick``
692+ # for the clip-state counterpart.
693+ self ._rc_snapshot = None
687694
688695 if clear :
689696 self .clear ()
@@ -858,17 +865,36 @@ def get_children(self):
858865 return [self .label , self .offsetText ,
859866 * self .get_major_ticks (), * self .get_minor_ticks ()]
860867
868+ def _propagate_axis_state_to_tick (self , tick ):
869+ """
870+ Copy Axis clip state onto a lazily-created Tick.
871+
872+ `Axis.set_clip_path` runs during ``Axes.__clear`` before any Tick
873+ exists under the lazy-init refactor, so the clip stored on the
874+ Axis must be re-stamped onto the first Tick when it materializes
875+ (only the Tick itself and its gridline are clipped, matching
876+ `Tick.set_clip_path`). Per-Artist rcParams like ``path.sketch`` /
877+ ``path.effects`` are handled by the ``rc_context`` wrapping in
878+ `_LazyTickList.__get__`, not here.
879+ """
880+ for artist in (tick , tick .gridline ):
881+ artist .clipbox = self .clipbox
882+ artist ._clippath = self ._clippath
883+ artist ._clipon = self ._clipon
884+
861885 def _reset_major_tick_kw (self ):
862886 self ._major_tick_kw .clear ()
863887 self ._major_tick_kw ['gridOn' ] = (
864888 mpl .rcParams ['axes.grid' ] and
865889 mpl .rcParams ['axes.grid.which' ] in ('both' , 'major' ))
890+ self ._rc_snapshot = dict (mpl .rcParams )
866891
867892 def _reset_minor_tick_kw (self ):
868893 self ._minor_tick_kw .clear ()
869894 self ._minor_tick_kw ['gridOn' ] = (
870895 mpl .rcParams ['axes.grid' ] and
871896 mpl .rcParams ['axes.grid.which' ] in ('both' , 'minor' ))
897+ self ._rc_snapshot = dict (mpl .rcParams )
872898
873899 def clear (self ):
874900 """
@@ -899,6 +925,11 @@ def clear(self):
899925 # Clear the callback registry for this axis, or it may "leak"
900926 self .callbacks = cbook .CallbackRegistry (signals = ["units" ])
901927
928+ # Snapshot current rcParams so that a Tick materialized later by
929+ # ``_LazyTickList`` (possibly outside any ``rc_context`` active
930+ # now) sees the same rcParams an eager pre-lazy tick would have.
931+ self ._rc_snapshot = dict (mpl .rcParams )
932+
902933 # whether the grids are on
903934 self ._major_tick_kw ['gridOn' ] = (
904935 mpl .rcParams ['axes.grid' ] and
@@ -939,9 +970,7 @@ def _existing_ticks(self, major=None):
939970 doing so would
940971
941972 (a) create throwaway Tick objects during ``Axes.__init__`` and
942- ``Axes.__clear`` -- defeating the whole point of the lazy lists --
943- and
944-
973+ ``Axes.__clear``
945974 (b) risk re-entering the
946975 ``Spine.set_position -> Axis.reset_ticks -> Axis.set_clip_path
947976 -> _LazyTickList.__get__ -> Tick.__init__ -> Spine.set_position``
0 commit comments