1
1
"""
2
- Manage figures for pyplot interface.
2
+ Manage figures for the pyplot interface.
3
3
"""
4
4
5
5
import atexit
6
+ from collections import OrderedDict
6
7
import gc
7
8
8
9
9
- class Gcf ( object ) :
10
+ class Gcf :
10
11
"""
11
- Singleton to manage a set of integer-numbered figures.
12
-
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.
17
-
18
- Attributes:
19
-
20
- *figs*:
21
- dictionary of the form {*num*: *manager*, ...}
22
-
23
- *_activeQue*:
24
- list of *managers*, with active one at the end
25
-
12
+ Singleton to maintain the relation between figures and their managers, and
13
+ keep track of and "active" figure and manager.
14
+
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`.
24
+
25
+ Attributes
26
+ ----------
27
+ figs : OrderedDict
28
+ `OrderedDict` mapping numbers to managers; the active manager is at the
29
+ end.
26
30
"""
27
- _activeQue = []
28
- figs = {}
31
+
32
+ figs = OrderedDict ()
29
33
30
34
@classmethod
31
35
def get_fig_manager (cls , num ):
32
36
"""
33
- If figure manager *num* exists, make it the active
34
- 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*.
35
39
"""
36
40
manager = cls .figs .get (num , None )
37
41
if manager is not None :
@@ -41,90 +45,73 @@ def get_fig_manager(cls, num):
41
45
@classmethod
42
46
def destroy (cls , num ):
43
47
"""
44
- Try to remove all traces of figure *num*.
48
+ Destroy figure number *num*.
45
49
46
- In the interactive backends, this is bound to the
47
- window "destroy" and "delete" events.
50
+ In the interactive backends, this is bound to the window "destroy" and
51
+ "delete" events.
48
52
"""
49
53
if not cls .has_fignum (num ):
50
54
return
51
- manager = cls .figs [ num ]
55
+ manager = cls .figs . pop ( num )
52
56
manager .canvas .mpl_disconnect (manager ._cidgcf )
53
- cls ._activeQue .remove (manager )
54
- del cls .figs [num ]
55
57
manager .destroy ()
56
58
gc .collect (1 )
57
59
58
60
@classmethod
59
61
def destroy_fig (cls , fig ):
60
- "*fig* is a Figure instance "
61
- num = next (( manager . num for manager in cls . figs . values ( )
62
- if manager . canvas . figure == fig ) , None )
63
- if num is not None :
64
- 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 )
65
67
66
68
@classmethod
67
69
def destroy_all (cls ):
68
- # this is need to ensure that gc is available in corner cases
69
- # where modules are being torn down after install with easy_install
70
- 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
71
74
for manager in list (cls .figs .values ()):
72
75
manager .canvas .mpl_disconnect (manager ._cidgcf )
73
76
manager .destroy ()
74
-
75
- cls ._activeQue = []
76
77
cls .figs .clear ()
77
78
gc .collect (1 )
78
79
79
80
@classmethod
80
81
def has_fignum (cls , num ):
81
- """
82
- Return *True* if figure *num* exists.
83
- """
82
+ """Return whether figure number *num* exists."""
84
83
return num in cls .figs
85
84
86
85
@classmethod
87
86
def get_all_fig_managers (cls ):
88
- """
89
- Return a list of figure managers.
90
- """
87
+ """Return a list of figure managers."""
91
88
return list (cls .figs .values ())
92
89
93
90
@classmethod
94
91
def get_num_fig_managers (cls ):
95
- """
96
- Return the number of figures being managed.
97
- """
92
+ """Return the number of figures being managed."""
98
93
return len (cls .figs )
99
94
100
95
@classmethod
101
96
def get_active (cls ):
102
- """
103
- Return the manager of the active figure, or *None*.
104
- """
105
- if len (cls ._activeQue ) == 0 :
106
- return None
107
- else :
108
- 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
109
99
110
100
@classmethod
111
101
def set_active (cls , manager ):
112
- """
113
- Make the figure corresponding to *manager* the active one.
114
- """
115
- oldQue = cls ._activeQue [:]
116
- cls ._activeQue = [m for m in oldQue if m != manager ]
117
- cls ._activeQue .append (manager )
102
+ """Make *manager* the active manager."""
118
103
cls .figs [manager .num ] = manager
104
+ cls .figs .move_to_end (manager .num )
119
105
120
106
@classmethod
121
107
def draw_all (cls , force = False ):
122
108
"""
123
- Redraw all figures registered with the pyplot
124
- state machine .
109
+ Redraw all stale managed figures, or, if *force* is True, all managed
110
+ figures .
125
111
"""
126
- for f_mgr in cls .get_all_fig_managers ():
127
- if force or f_mgr .canvas .figure .stale :
128
- 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
+
129
116
130
117
atexit .register (Gcf .destroy_all )
0 commit comments