_pylab_helpers.py 3.6 KB

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