renderer.py 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. from __future__ import annotations
  2. from abc import ABC, abstractmethod
  3. from typing import TYPE_CHECKING, Any
  4. import numpy as np
  5. if TYPE_CHECKING:
  6. import io
  7. from numpy.typing import ArrayLike
  8. from contourpy._contourpy import CoordinateArray, FillReturn, FillType, LineReturn, LineType
  9. class Renderer(ABC):
  10. """Abstract base class for renderers."""
  11. def _grid_as_2d(self, x: ArrayLike, y: ArrayLike) -> tuple[CoordinateArray, CoordinateArray]:
  12. x = np.asarray(x)
  13. y = np.asarray(y)
  14. if x.ndim == 1:
  15. x, y = np.meshgrid(x, y)
  16. return x, y
  17. @abstractmethod
  18. def filled(
  19. self,
  20. filled: FillReturn,
  21. fill_type: FillType | str,
  22. ax: Any = 0,
  23. color: str = "C0",
  24. alpha: float = 0.7,
  25. ) -> None:
  26. pass
  27. @abstractmethod
  28. def grid(
  29. self,
  30. x: ArrayLike,
  31. y: ArrayLike,
  32. ax: Any = 0,
  33. color: str = "black",
  34. alpha: float = 0.1,
  35. point_color: str | None = None,
  36. quad_as_tri_alpha: float = 0,
  37. ) -> None:
  38. pass
  39. @abstractmethod
  40. def lines(
  41. self,
  42. lines: LineReturn,
  43. line_type: LineType | str,
  44. ax: Any = 0,
  45. color: str = "C0",
  46. alpha: float = 1.0,
  47. linewidth: float = 1,
  48. ) -> None:
  49. pass
  50. @abstractmethod
  51. def mask(
  52. self,
  53. x: ArrayLike,
  54. y: ArrayLike,
  55. z: ArrayLike | np.ma.MaskedArray[Any, Any],
  56. ax: Any = 0,
  57. color: str = "black",
  58. ) -> None:
  59. pass
  60. def multi_filled(
  61. self,
  62. multi_filled: list[FillReturn],
  63. fill_type: FillType | str,
  64. ax: Any = 0,
  65. color: str | None = None,
  66. **kwargs: Any,
  67. ) -> None:
  68. """Plot multiple sets of filled contours on a single axes.
  69. Args:
  70. multi_filled (list of filled contour arrays): Multiple filled contour sets as returned
  71. by :meth:`.ContourGenerator.multi_filled`.
  72. fill_type (FillType or str): Type of filled data as returned by
  73. :attr:`~.ContourGenerator.fill_type`, or string equivalent.
  74. ax (int or Renderer-specific axes or figure object, optional): Which axes to plot on,
  75. default ``0``.
  76. color (str or None, optional): If a string color then this same color is used for all
  77. filled contours. If ``None``, the default, then the filled contour sets use colors
  78. from the ``tab10`` colormap in order, wrapping around to the beginning if more than
  79. 10 sets of filled contours are rendered.
  80. kwargs: All other keyword argument are passed on to
  81. :meth:`.Renderer.filled` unchanged.
  82. .. versionadded:: 1.3.0
  83. """
  84. if color is not None:
  85. kwargs["color"] = color
  86. for i, filled in enumerate(multi_filled):
  87. if color is None:
  88. kwargs["color"] = f"C{i % 10}"
  89. self.filled(filled, fill_type, ax, **kwargs)
  90. def multi_lines(
  91. self,
  92. multi_lines: list[LineReturn],
  93. line_type: LineType | str,
  94. ax: Any = 0,
  95. color: str | None = None,
  96. **kwargs: Any,
  97. ) -> None:
  98. """Plot multiple sets of contour lines on a single axes.
  99. Args:
  100. multi_lines (list of contour line arrays): Multiple contour line sets as returned by
  101. :meth:`.ContourGenerator.multi_lines`.
  102. line_type (LineType or str): Type of line data as returned by
  103. :attr:`~.ContourGenerator.line_type`, or string equivalent.
  104. ax (int or Renderer-specific axes or figure object, optional): Which axes to plot on,
  105. default ``0``.
  106. color (str or None, optional): If a string color then this same color is used for all
  107. lines. If ``None``, the default, then the line sets use colors from the ``tab10``
  108. colormap in order, wrapping around to the beginning if more than 10 sets of lines
  109. are rendered.
  110. kwargs: All other keyword argument are passed on to
  111. :meth:`Renderer.lines` unchanged.
  112. .. versionadded:: 1.3.0
  113. """
  114. if color is not None:
  115. kwargs["color"] = color
  116. for i, lines in enumerate(multi_lines):
  117. if color is None:
  118. kwargs["color"] = f"C{i % 10}"
  119. self.lines(lines, line_type, ax, **kwargs)
  120. @abstractmethod
  121. def save(self, filename: str, transparent: bool = False) -> None:
  122. pass
  123. @abstractmethod
  124. def save_to_buffer(self) -> io.BytesIO:
  125. pass
  126. @abstractmethod
  127. def show(self) -> None:
  128. pass
  129. @abstractmethod
  130. def title(self, title: str, ax: Any = 0, color: str | None = None) -> None:
  131. pass
  132. @abstractmethod
  133. def z_values(
  134. self,
  135. x: ArrayLike,
  136. y: ArrayLike,
  137. z: ArrayLike,
  138. ax: Any = 0,
  139. color: str = "green",
  140. fmt: str = ".1f",
  141. quad_as_tri: bool = False,
  142. ) -> None:
  143. pass