pyplot.py 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
  1. import asyncio
  2. import io
  3. from typing import Any
  4. import matplotlib.pyplot as plt
  5. from .. import background_tasks, globals
  6. from ..element import Element
  7. class Pyplot(Element):
  8. def __init__(self, *, close: bool = True, **kwargs: Any) -> None:
  9. """Pyplot Context
  10. Create a context to configure a `Matplotlib <https://matplotlib.org/>`_ plot.
  11. :param close: whether the figure should be closed after exiting the context; set to `False` if you want to update it later (default: `True`)
  12. :param kwargs: arguments like `figsize` which should be passed to `pyplot.figure <https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.figure.html>`_
  13. """
  14. super().__init__('div')
  15. self.close = close
  16. self.fig = plt.figure(**kwargs)
  17. self._convert_to_html()
  18. if not self.client.shared:
  19. background_tasks.create(self._auto_close(), name='auto-close plot figure')
  20. def _convert_to_html(self) -> None:
  21. with io.StringIO() as output:
  22. self.fig.savefig(output, format='svg')
  23. self._props['innerHTML'] = output.getvalue()
  24. def __enter__(self):
  25. plt.figure(self.fig)
  26. return self
  27. def __exit__(self, *_):
  28. self._convert_to_html()
  29. if self.close:
  30. plt.close(self.fig)
  31. self.update()
  32. async def _auto_close(self) -> None:
  33. while self.client.id in globals.clients:
  34. await asyncio.sleep(1.0)
  35. plt.close(self.fig)