11"""
2- Manage figures for pyplot interface.
2+ Manage figures for the pyplot interface.
33"""
44
55import atexit
6+ from collections import OrderedDict
67import gc
78
89
910class Gcf :
1011 """
11- Singleton to manage a set of integer-numbered figures.
12+ Singleton to maintain the relation between figures and their managers, and
13+ keep track of and "active" figure and manager.
1214
13- This class is never instantiated; it consists of two class
14- attributes (a list and a dictionary), and a set of static
15- methods that operate on those attributes, accessing them
16- directly as class attributes.
15+ The canvas of a figure created through pyplot is associated with a figure
16+ manager, which handles the interaction between the figure and the backend.
17+ pyplot keeps track of figure managers using an identifier, the "figure
18+ number" or "manager number" (which can actually be any hashable value);
19+ this number is available as the :attr:`number` attribute of the manager.
20+
21+ This class is never instantiated; it consists of an `OrderedDict` mapping
22+ figure/manager numbers to managers, and a set of class methods that
23+ manipulate this `OrderedDict`.
1724
1825 Attributes
1926 ----------
20- figs
21- dictionary of the form {*num*: *manager*, ...}
22- _activeQue
23- list of *managers*, with active one at the end
24-
27+ figs : OrderedDict
28+ `OrderedDict` mapping numbers to managers; the active manager is at the
29+ end.
2530 """
26- _activeQue = []
27- figs = {}
31+
32+ figs = OrderedDict ()
2833
2934 @classmethod
3035 def get_fig_manager (cls , num ):
3136 """
32- If figure manager *num* exists, make it the active
33- figure and return the manager; otherwise return *None*.
37+ If manager number *num* exists, make it the active one and return it;
38+ otherwise return *None*.
3439 """
3540 manager = cls .figs .get (num , None )
3641 if manager is not None :
@@ -40,90 +45,73 @@ def get_fig_manager(cls, num):
4045 @classmethod
4146 def destroy (cls , num ):
4247 """
43- Try to remove all traces of figure *num*.
48+ Destroy figure number *num*.
4449
45- In the interactive backends, this is bound to the
46- window "destroy" and "delete" events.
50+ In the interactive backends, this is bound to the window "destroy" and
51+ "delete" events.
4752 """
4853 if not cls .has_fignum (num ):
4954 return
50- manager = cls .figs [ num ]
55+ manager = cls .figs . pop ( num )
5156 manager .canvas .mpl_disconnect (manager ._cidgcf )
52- cls ._activeQue .remove (manager )
53- del cls .figs [num ]
5457 manager .destroy ()
5558 gc .collect (1 )
5659
5760 @classmethod
5861 def destroy_fig (cls , fig ):
59- "*fig* is a Figure instance "
60- num = next (( manager . num for manager in cls . figs . values ( )
61- if manager . canvas . figure == fig ) , None )
62- if num is not None :
63- cls .destroy (num )
62+ """Destroy figure *fig*."" "
63+ canvas = getattr ( fig , "canvas" , None )
64+ manager = getattr ( canvas , "manager" , None )
65+ num = getattr ( manager , "num" , None )
66+ cls .destroy (num )
6467
6568 @classmethod
6669 def destroy_all (cls ):
67- # this is need to ensure that gc is available in corner cases
68- # where modules are being torn down after install with easy_install
69- import gc # noqa
70+ """Destroy all figures."""
71+ # Reimport gc in case the module globals have already been removed
72+ # during interpreter shutdown.
73+ import gc
7074 for manager in list (cls .figs .values ()):
7175 manager .canvas .mpl_disconnect (manager ._cidgcf )
7276 manager .destroy ()
73-
74- cls ._activeQue = []
7577 cls .figs .clear ()
7678 gc .collect (1 )
7779
7880 @classmethod
7981 def has_fignum (cls , num ):
80- """
81- Return *True* if figure *num* exists.
82- """
82+ """Return whether figure number *num* exists."""
8383 return num in cls .figs
8484
8585 @classmethod
8686 def get_all_fig_managers (cls ):
87- """
88- Return a list of figure managers.
89- """
87+ """Return a list of figure managers."""
9088 return list (cls .figs .values ())
9189
9290 @classmethod
9391 def get_num_fig_managers (cls ):
94- """
95- Return the number of figures being managed.
96- """
92+ """Return the number of figures being managed."""
9793 return len (cls .figs )
9894
9995 @classmethod
10096 def get_active (cls ):
101- """
102- Return the manager of the active figure, or *None*.
103- """
104- if len (cls ._activeQue ) == 0 :
105- return None
106- else :
107- return cls ._activeQue [- 1 ]
97+ """Return the active manager, or *None* if there is no manager."""
98+ return next (reversed (cls .figs .values ())) if cls .figs else None
10899
109100 @classmethod
110101 def set_active (cls , manager ):
111- """
112- Make the figure corresponding to *manager* the active one.
113- """
114- oldQue = cls ._activeQue [:]
115- cls ._activeQue = [m for m in oldQue if m != manager ]
116- cls ._activeQue .append (manager )
102+ """Make *manager* the active manager."""
117103 cls .figs [manager .num ] = manager
104+ cls .figs .move_to_end (manager .num )
118105
119106 @classmethod
120107 def draw_all (cls , force = False ):
121108 """
122- Redraw all figures registered with the pyplot
123- state machine .
109+ Redraw all stale managed figures, or, if *force* is True, all managed
110+ figures .
124111 """
125- for f_mgr in cls .get_all_fig_managers ():
126- if force or f_mgr .canvas .figure .stale :
127- f_mgr .canvas .draw_idle ()
112+ for manager in cls .get_all_fig_managers ():
113+ if force or manager .canvas .figure .stale :
114+ manager .canvas .draw_idle ()
115+
128116
129117atexit .register (Gcf .destroy_all )
0 commit comments