Source code for graphinglib.data_plotting_2d

from __future__ import annotations

from copy import deepcopy
from dataclasses import dataclass
from typing import Callable, Literal, Optional

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.colors import Colormap
from matplotlib.image import imread
from numpy.typing import ArrayLike
from scipy.interpolate import griddata

try:
    from typing import Self
except ImportError:
    from typing_extensions import Self


[docs] @dataclass class Heatmap: """ The class implements heatmaps. Parameters ---------- image : ArrayLike or str Image to display as an array of values or from a file. x_axis_range, y_axis_range : tuple[float, float], optional The range of x and y values used for the axes as tuples containing the start and end of the range. color_map : str, Colormap The color map to use for the :class:`~graphinglib.data_plotting_2d.Heatmap`. Can either be specified as a string (named colormap from Matplotlib) or a Colormap object. Default depends on the ``figure_style`` configuration. show_color_bar : bool Whether or not to display the color bar next to the plot. Defaults to ``True``. alpha_value : float Opacity value of the :class:`~graphinglib.data_plotting_2d.Heatmap`. Defaults to 1.0. aspect_ratio : str or float Aspect ratio of the axes. Default depends on the ``figure_style`` configuration. origin_position : str Position of the origin of the axes (upper left or lower left corner). Default depends on the ``figure_style`` configuration. interpolation : str Interpolation method to be applied to the image. Defaults to ``"none"``. .. seealso:: For other interpolation methods, refer to `Interpolations for imshow <https://matplotlib.org/stable/gallery/images_contours_and_fields/interpolation_methods.html>`_. """
[docs] def __init__( self, image: ArrayLike | str, x_axis_range: Optional[tuple[float, float]] = None, y_axis_range: Optional[tuple[float, float]] = None, color_map: str | Colormap = "default", show_color_bar: bool | Literal["default"] = "default", alpha_value: float = 1.0, aspect_ratio: str | float = "default", origin_position: str = "default", interpolation: str = "none", ) -> None: """ The class implements heatmaps. Parameters ---------- image : ArrayLike or str Image to display as an array of values or from a file. x_axis_range, y_axis_range : tuple[float, float], optional The range of x and y values used for the axes as tuples containing the start and end of the range. color_map : str, Colormap The color map to use for the :class:`~graphinglib.data_plotting_2d.Heatmap`. Can either be specified as a string (named colormap from Matplotlib) or a Colormap object. Default depends on the ``figure_style`` configuration. show_color_bar : bool Whether or not to display the color bar next to the plot. Defaults to ``True``. alpha_value : float Opacity value of the :class:`~graphinglib.data_plotting_2d.Heatmap`. Defaults to 1.0. aspect_ratio : str or float Aspect ratio of the axes. Default depends on the ``figure_style`` configuration. origin_position : str Position of the origin of the axes (upper left or lower left corner). Default depends on the ``figure_style`` configuration. interpolation : str Interpolation method to be applied to the image. Defaults to ``"none"``. .. seealso:: For other interpolation methods, refer to `Interpolations for imshow <https://matplotlib.org/stable/gallery/images_contours_and_fields/interpolation_methods.html>`_. """ self._image = image self._x_axis_range = x_axis_range self._y_axis_range = y_axis_range self._color_map = color_map self._show_color_bar = show_color_bar self._alpha_value = alpha_value self._aspect_ratio = aspect_ratio self._origin_position = origin_position self._interpolation = interpolation if isinstance(self._image, str): self._image = imread(self._image) self._show_color_bar = False else: self._image = np.asarray(self._image) if self._x_axis_range is not None and self._y_axis_range is not None: self._xy_range = self._x_axis_range + self._y_axis_range
[docs] @classmethod def from_function( cls, func: Callable[[ArrayLike, ArrayLike], ArrayLike], x_axis_range: tuple[float, float], y_axis_range: tuple[float, float], color_map: str | Colormap = "default", show_color_bar: bool = True, alpha_value: float = 1.0, aspect_ratio: str | float = "default", origin_position: str = "default", interpolation: str = "none", number_of_points: tuple[int, int] = (50, 50), ) -> Self: """ Creates a heatmap from a function. Parameters ---------- func : Callable[[ArrayLike, ArrayLike], ArrayLike] Function to be plotted. Works with regular functions and lambda functions. x_axis_range, y_axis_range : tuple[float, float], optional The range of x and y values used for the axes as tuples containing the start and end of the range. color_map : str, Colormap The color map to use for the :class:`~graphinglib.data_plotting_2d.Heatmap`. Can either be specified as a string (named colormap from Matplotlib) or a Colormap object. Default depends on the ``figure_style`` configuration. show_color_bar : bool Whether or not to display the color bar next to the plot. Defaults to ``True``. alpha_value : float Opacity value of the :class:`~graphinglib.data_plotting_2d.Heatmap`. Defaults to 1.0. aspect_ratio : str or float Aspect ratio of the axes. Default depends on the ``figure_style`` configuration. origin_position : str Position of the origin of the axes (upper left or lower left corner). Default depends on the ``figure_style`` configuration. interpolation : str Interpolation method to be applied to the image. Defaults to ``"none"``. .. seealso:: For other interpolation methods, refer to `Interpolations for imshow <https://matplotlib.org/stable/gallery/images_contours_and_fields/interpolation_methods.html>`_. number_of_points : tuple[int, int] Number of points in the x and y coordinates. Defaults to ``(50, 50)``. Returns ------- A :class:`~graphinglib.data_plotting_2d.Heatmap` object created from a function. """ x = np.linspace(x_axis_range[0], x_axis_range[1], number_of_points[0]) y = np.linspace(y_axis_range[0], y_axis_range[1], number_of_points[1]) x_grid, y_grid = np.meshgrid(x, y) z = func(x_grid, y_grid) return cls( z, x_axis_range, y_axis_range, color_map, show_color_bar, alpha_value, aspect_ratio, origin_position, interpolation, )
[docs] @classmethod def from_points( cls, points: ArrayLike, values: ArrayLike, x_axis_range: tuple[float, float], y_axis_range: tuple[float, float], grid_interpolation: str = "nearest", fill_value: float = np.nan, color_map: str | Colormap = "default", show_color_bar: bool = True, alpha_value: float = 1.0, aspect_ratio: str | float = "default", origin_position: str = "default", interpolation: str = "none", number_of_points: tuple[int, int] = (50, 50), ): """ Creates a heatmap by interpolating unevenly distributed data points on a grid. Parameters ---------- points : ArrayLike The list or array of points at which values are known. values : ArrayLike The list or array of values at given points. x_axis_range, y_axis_range : tuple[float, float], optional The range of x and y values used for the axes as tuples containing the start and end of the range. grid_interpolation : str Interpolation method to be used when interpolating the uneavenly distributed data on a grid. Must be one of {"nearest", "linear", "cubic"}. color_map : str, Colormap The color map to use for the :class:`~graphinglib.data_plotting_2d.Heatmap`. Can either be specified as a string (named colormap from Matplotlib) or a Colormap object. Default depends on the ``figure_style`` configuration. show_color_bar : bool Whether or not to display the color bar next to the plot. Defaults to ``True``. alpha_value : float Opacity value of the :class:`~graphinglib.data_plotting_2d.Heatmap`. Defaults to 1.0. aspect_ratio : str or float Aspect ratio of the axes. Default depends on the ``figure_style`` configuration. origin_position : str Position of the origin of the axes (upper left or lower left corner). Default depends on the ``figure_style`` configuration. interpolation : str Interpolation method to be applied to the image. Defaults to ``"none"``. .. seealso:: For other interpolation methods, refer to `Interpolations for imshow <https://matplotlib.org/stable/gallery/images_contours_and_fields/interpolation_methods.html>`_. number_of_points : tuple[int, int] Number of points in the x and y coordinates. Defaults to ``(50, 50)``. Returns ------- A :class:`~graphinglib.data_plotting_2d.Heatmap` object created from data points. """ x = np.linspace(x_axis_range[0], x_axis_range[1], number_of_points[0]) y = np.linspace(y_axis_range[0], y_axis_range[1], number_of_points[1]) x_grid, y_grid = np.meshgrid(x, y) grid = griddata( points, values, (x_grid, y_grid), method=grid_interpolation, fill_value=fill_value, ) return cls( grid, x_axis_range, y_axis_range, color_map, show_color_bar, alpha_value, aspect_ratio, origin_position, interpolation, )
@property def image(self) -> ArrayLike: return self._image @image.setter def image(self, image: ArrayLike | str) -> None: if isinstance(image, str): self._image = imread(image) else: self._image = np.asarray(image) @property def x_axis_range(self) -> Optional[tuple[float, float]]: return self._x_axis_range @x_axis_range.setter def x_axis_range(self, x_axis_range: Optional[tuple[float, float]]) -> None: self._x_axis_range = x_axis_range @property def y_axis_range(self) -> Optional[tuple[float, float]]: return self._y_axis_range @y_axis_range.setter def y_axis_range(self, y_axis_range: Optional[tuple[float, float]]) -> None: self._y_axis_range = y_axis_range @property def color_map(self) -> str | Colormap: return self._color_map @color_map.setter def color_map(self, color_map: str | Colormap) -> None: self._color_map = color_map @property def show_color_bar(self) -> bool: return self._show_color_bar @show_color_bar.setter def show_color_bar(self, show_color_bar: bool) -> None: self._show_color_bar = show_color_bar @property def alpha_value(self) -> float: return self._alpha_value @alpha_value.setter def alpha_value(self, alpha_value: float) -> None: self._alpha_value = alpha_value @property def aspect_ratio(self) -> str | float: return self._aspect_ratio @aspect_ratio.setter def aspect_ratio(self, aspect_ratio: str | float) -> None: self._aspect_ratio = aspect_ratio @property def origin_position(self) -> str: return self._origin_position @origin_position.setter def origin_position(self, origin_position: str) -> None: self._origin_position = origin_position @property def interpolation(self) -> str: return self._interpolation @interpolation.setter def interpolation(self, interpolation: str) -> None: self._interpolation = interpolation
[docs] def copy(self) -> Self: """ Returns a deep copy of the :class:`~graphinglib.data_plotting_2d.Heatmap`. """ return deepcopy(self)
def _plot_element(self, axes: plt.Axes, z_order: int, **kwargs) -> None: """ Plots the element in the specified `Axes <https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.html>`_. """ if self._x_axis_range is not None and self._y_axis_range is not None: params = { "cmap": self._color_map, "alpha": self._alpha_value, "aspect": self._aspect_ratio, "origin": self._origin_position, "interpolation": self._interpolation, "extent": self._xy_range, } params = {k: v for k, v in params.items() if v != "default"} image = axes.imshow( self._image, zorder=z_order, **params, ) else: params = { "cmap": self._color_map, "alpha": self._alpha_value, "aspect": self._aspect_ratio, "origin": self._origin_position, "interpolation": self._interpolation, } params = {k: v for k, v in params.items() if v != "default"} image = axes.imshow( self._image, zorder=z_order, **params, ) fig = axes.get_figure() if self._show_color_bar: fig.colorbar(image, ax=axes)
[docs] @dataclass class VectorField: """ This class implements vector fields. Parameters ---------- x_data, y_data : ArrayLike x and y coordinates of the vectors. u_data, v_data : ArrayLike Magnitudes in the x and y coordinates. arrow_width : float Width of the arrow shaft. Acts as a multiplier for the standard arrow width. Default depends on the ``figure_style`` configuration. arrow_head_size : float Size of the arrow head. Acts as a multiplier for the standard arrow head size. Default depends on the ``figure_style`` configuration. scale : float Scaling of the arrow lengths. If ``None``, the arrows will be automatically scaled to look nice. Use 1 for no scaling. angle_in_data_coords : bool Wheter to use the screen coordinates or the data coordinates to determine the vector directions. Defaults to ``True``. color : str Color of the vector arrows. Default depends on the ``figure_style`` configuration. """
[docs] def __init__( self, x_data: ArrayLike, y_data: ArrayLike, u_data: ArrayLike, v_data: ArrayLike, arrow_width: float | Literal["default"] = "default", arrow_head_size: float | Literal["default"] = "default", scale: Optional[float] = None, make_angles_axes_independent: bool = False, color: str | Literal["default"] = "default", ) -> None: """ This class implements vector fields. Parameters ---------- x_data, y_data : ArrayLike x and y coordinates of the vectors. u_data, v_data : ArrayLike Magnitudes in the x and y coordinates. arrow_width : float Width of the arrow shaft. Acts as a multiplier for the standard arrow width. Default depends on the ``figure_style`` configuration. arrow_head_size : float Size of the arrow head. Acts as a multiplier for the standard arrow head size. Default depends on the ``figure_style`` configuration. scale : float Scaling of the arrow lengths. If ``None``, the arrows will be automatically scaled to look nice. Use 1 for no scaling. Default is ``None``. make_angles_axes_independent : bool Whether to use the screen coordinates or the data coordinates to determine the vector directions. If ``True``, vectors with u = v will always appear as 45 degree angles with respect to the screen, regardless of the axes limits. If ``False``, the vectors will scale with the aspect ratio of the axes. Defaults to ``False``. color : str Color of the vector arrows. Default depends on the ``figure_style`` configuration. """ self._x_data = np.asarray(x_data) self._y_data = np.asarray(y_data) self._u_data = np.asarray(u_data) self._v_data = np.asarray(v_data) self._arrow_width = arrow_width self._arrow_head_size = arrow_head_size self._scale = scale self._make_angles_axes_independent = make_angles_axes_independent self._color = color
[docs] @classmethod def from_function( cls, func: Callable[[ArrayLike, ArrayLike], tuple[ArrayLike, ArrayLike]], x_axis_range: tuple[float, float], y_axis_range: tuple[float, float], number_of_arrows_x: int = 10, number_of_arrows_y: int = 10, arrow_width: float | Literal["default"] = "default", arrow_head_size: float | Literal["default"] = "default", scale: Optional[float] = None, make_angles_axes_independent: bool = False, color: str | Literal["default"] = "default", ) -> Self: """ Creates a :class:`~graphinglib.data_plotting_2d.VectorField` from a function. Parameters ---------- func : Callable[[ArrayLike, ArrayLike], tuple[ArrayLike, ArrayLike]] Function to be plotted. Works with regular functions and lambda functions. x_data, y_data : ArrayLike x and y coordinates of the vectors. u_data, v_data : ArrayLike Magnitudes in the x and y coordinates. number_of_arrows_x, number_of_arrows_y : int Number of arrows to plot in the x and y direction. Defaults to 10. arrow_width : float Width of the arrow shaft. Acts as a multiplier for the standard arrow width. Default depends on the ``figure_style`` configuration. arrow_head_size : float Size of the arrow head. Acts as a multiplier for the standard arrow head size. Default depends on the ``figure_style`` configuration. scale : float Scaling of the arrow lengths. If ``None``, the arrows will be automatically scaled to look nice. Use 1 for no scaling. Default is ``None``. make_angles_axes_independent : bool Whether to use the screen coordinates or the data coordinates to determine the vector directions. If ``True``, vectors with u = v will always appear as 45 degree angles with respect to the screen, regardless of the axes limits. If ``False``, the vectors will scale with the aspect ratio of the axes. Defaults to ``False``. color : str Color of the vector arrows. Default depends on the ``figure_style`` configuration. Returns ------- A :class:`~graphinglib.data_plotting_2d.VectorField` object from a function. """ x = np.linspace(x_axis_range[0], x_axis_range[-1], number_of_arrows_x) y = np.linspace(y_axis_range[0], y_axis_range[-1], number_of_arrows_y) x_grid, y_grid = np.meshgrid(x, y) u, v = func(x_grid, y_grid) return cls( x_grid, y_grid, u, v, arrow_width, arrow_head_size, scale, make_angles_axes_independent, color, )
@property def x_data(self) -> ArrayLike: return self._x_data @x_data.setter def x_data(self, x_data: ArrayLike) -> None: self._x_data = np.asarray(x_data) @property def y_data(self) -> ArrayLike: return self._y_data @y_data.setter def y_data(self, y_data: ArrayLike) -> None: self._y_data = np.asarray(y_data) @property def u_data(self) -> ArrayLike: return self._u_data @u_data.setter def u_data(self, u_data: ArrayLike) -> None: self._u_data = np.asarray(u_data) @property def v_data(self) -> ArrayLike: return self._v_data @v_data.setter def v_data(self, v_data: ArrayLike) -> None: self._v_data = np.asarray(v_data) @property def arrow_width(self) -> float: return self._arrow_width @arrow_width.setter def arrow_width(self, arrow_width: float) -> None: self._arrow_width = arrow_width @property def arrow_head_size(self) -> float: return self._arrow_head_size @arrow_head_size.setter def arrow_head_size(self, arrow_head_size: float) -> None: self._arrow_head_size = arrow_head_size @property def scale(self) -> Optional[float]: return self._scale @scale.setter def scale(self, scale: Optional[float]) -> None: self._scale = scale @property def make_angles_axes_independent(self) -> bool: return self._make_angles_axes_independent @make_angles_axes_independent.setter def make_angles_axes_independent(self, value: bool) -> None: self._make_angles_axes_independent = value @property def color(self) -> str: return self._color @color.setter def color(self, color: str) -> None: self._color = color
[docs] def copy(self) -> Self: """ Returns a deep copy of the :class:`~graphinglib.data_plotting_2d.VectorField`. """ return deepcopy(self)
def _plot_element(self, axes: plt.Axes, z_order: int, **kwargs) -> None: """ Plots the element in the specified `Axes <https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.html>`_. """ if self._make_angles_axes_independent: angle = "uv" else: angle = "xy" params = { "angles": angle, "width": 0.005 * self._arrow_width, "headwidth": 4 * self._arrow_head_size / self._arrow_width, "headlength": 4 * self._arrow_head_size / self._arrow_width, "headaxislength": 4 * self._arrow_head_size / self._arrow_width, "color": self._color, "scale": 1 / self._scale if self._scale is not None else None, "scale_units": "xy", } params = {k: v for k, v in params.items() if v != "default"} axes.quiver( self._x_data, self._y_data, self._u_data, self._v_data, zorder=z_order, **params, )
[docs] @dataclass class Contour: """ This class implements contour plots. Parameters ---------- x_mesh, y_mesh : ArrayLike x and y coordinates of the mesh grid. z_data : ArrayLike Data for each point of the mesh. number_of_levels : int Number of distinct levels of contour plot. Default depends on the ``figure_style`` configuration. color_map : str or Colormap The color map to use for the :class:`~graphinglib.data_plotting_2d.Heatmap`. Can either be specified as a string (named colormap from Matplotlib) or a Colormap object. Default depends on the ``figure_style`` configuration. show_color_bar : bool Whether or not to display the color bar next to the plot. Default depends on the ``figure_style`` configuration. filled : bool Wheter or not to fill the contour with color. Default depends on the ``figure_style`` configuration. alpha : float Opacity of the filled contour. Default depends on the ``figure_style`` configuration. """ _x_mesh: ArrayLike _y_mesh: ArrayLike _z_data: ArrayLike _number_of_levels: int | Literal["default"] = "default" _color_map: str | Colormap | Literal["default"] = "default" _show_color_bar: bool | Literal["default"] = "default" _filled: bool | Literal["default"] = "default" _alpha: float | Literal["default"] = "default"
[docs] def __init__( self, x_mesh: ArrayLike, y_mesh: ArrayLike, z_data: ArrayLike, number_of_levels: int | Literal["default"] = "default", color_map: str | Colormap | Literal["default"] = "default", show_color_bar: bool | Literal["default"] = "default", filled: bool | Literal["default"] = "default", alpha: float | Literal["default"] = "default", ) -> None: """ This class implements contour plots. Parameters ---------- x_mesh, y_mesh : ArrayLike x and y coordinates of the mesh grid. z_data : ArrayLike Data for each point of the mesh. number_of_levels : int Number of distinct levels of contour plot. Default depends on the ``figure_style`` configuration. color_map : str or Colormap The color map to use for the :class:`~graphinglib.data_plotting_2d.Heatmap`. Can either be specified as a string (named colormap from Matplotlib) or a Colormap object. Default depends on the ``figure_style`` configuration. show_color_bar : bool Whether or not to display the color bar next to the plot. Default depends on the ``figure_style`` configuration. filled : bool Wheter or not to fill the contour with color. Default depends on the ``figure_style`` configuration. alpha : float Opacity of the filled contour. Default depends on the ``figure_style`` configuration. """ self._x_mesh = np.asarray(x_mesh) self._y_mesh = np.asarray(y_mesh) self._z_data = np.asarray(z_data) self._number_of_levels = number_of_levels self._color_map = color_map self._show_color_bar = show_color_bar self._filled = filled self._alpha = alpha
[docs] @classmethod def from_function( cls, func: Callable[[ArrayLike, ArrayLike], ArrayLike], x_axis_range: tuple[float, float], y_axis_range: tuple[float, float], number_of_levels: int | Literal["default"] = "default", color_map: str | Colormap | Literal["default"] = "default", show_color_bar: bool | Literal["default"] = "default", filled: bool | Literal["default"] = "default", alpha: float | Literal["default"] = "default", number_of_points: tuple[int, int] = (500, 500), ) -> Self: """ Creates a Contour object from a function. Parameters ---------- func : Callable[[ArrayLike, ArrayLike], ArrayLike] Function to be plotted. Works with regular functions and lambda functions. x_mesh, y_mesh : ArrayLike x and y coordinates of the mesh grid. z_data : ArrayLike Data for each point of the mesh. number_of_levels : int Number of distinct levels of contour plot. Default depends on the ``figure_style`` configuration. color_map : str or Colormap The color map to use for the :class:`~graphinglib.data_plotting_2d.Heatmap`. Can either be specified as a string (named colormap from Matplotlib) or a Colormap object. Default depends on the ``figure_style`` configuration. show_color_bar : bool Whether or not to display the color bar next to the plot. Default depends on the ``figure_style`` configuration. filled : bool Wheter or not to fill the contour with color. Default depends on the ``figure_style`` configuration. alpha : float Opacity of the filled contour. Default depends on the ``figure_style`` configuration. Returns ------- A :class:`~graphinglib.data_plotting_2d.Contour` object from a function. """ x = np.linspace(x_axis_range[0], x_axis_range[1], number_of_points[0]) y = np.linspace(y_axis_range[0], y_axis_range[1], number_of_points[1]) x_mesh, y_mesh = np.meshgrid(x, y) z_data = func(x_mesh, y_mesh) return cls( x_mesh, y_mesh, z_data, number_of_levels, color_map, show_color_bar, filled, alpha, )
@property def x_mesh(self) -> ArrayLike: return self._x_mesh @x_mesh.setter def x_mesh(self, x_mesh: ArrayLike) -> None: self._x_mesh = np.asarray(x_mesh) @property def y_mesh(self) -> ArrayLike: return self._y_mesh @y_mesh.setter def y_mesh(self, y_mesh: ArrayLike) -> None: self._y_mesh = np.asarray(y_mesh) @property def z_data(self) -> ArrayLike: return self._z_data @z_data.setter def z_data(self, z_data: ArrayLike) -> None: self._z_data = np.asarray(z_data) @property def number_of_levels(self) -> int: return self._number_of_levels @number_of_levels.setter def number_of_levels(self, number_of_levels: int) -> None: self._number_of_levels = number_of_levels @property def color_map(self) -> str | Colormap: return self._color_map @color_map.setter def color_map(self, color_map: str | Colormap) -> None: self._color_map = color_map @property def show_color_bar(self) -> bool: return self._show_color_bar @show_color_bar.setter def show_color_bar(self, show_color_bar: bool) -> None: self._show_color_bar = show_color_bar @property def filled(self) -> bool: return self._filled @filled.setter def filled(self, filled: bool) -> None: self._filled = filled @property def alpha(self) -> float: return self._alpha @alpha.setter def alpha(self, alpha: float) -> None: self._alpha = alpha
[docs] def copy(self) -> Self: """ Returns a deep copy of the :class:`~graphinglib.data_plotting_2d.Contour`. """ return deepcopy(self)
def _plot_element(self, axes: plt.Axes, z_order: int, **kwargs) -> None: """ Plots the element in the specified `Axes <https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.html>`_. """ params = { "levels": self._number_of_levels, "cmap": self._color_map, "alpha": self._alpha, } params = {k: v for k, v in params.items() if v != "default"} if self._filled: cont = axes.contourf( self._x_mesh, self._y_mesh, self._z_data, zorder=z_order, **params, ) else: cont = axes.contour( self._x_mesh, self._y_mesh, self._z_data, zorder=z_order, **params, ) if self._show_color_bar: fig = axes.get_figure() fig.colorbar(cont, ax=axes)
[docs] @dataclass class Stream: """ This class implements stream plots. Parameters ---------- x_data, y_data : ArrayLike x and y coordinates of the vectors as a mesh grid. u_data, v_data : ArrayLike Magnitudes of the vectors for each point of the mesh grid. density : float or tuple[float, float] Density of stream lines. Can be specified independently for the x and y coordinates by specifying a density tuple instead. Defaults to 1. line_width : float Width of the stream lines. Default depends on the ``figure_style`` configuration. color : str or ArrayLike Color of the stream lines. If an array of intensities is provided, the values are mapped to the specified color map. Default depends on the ``figure_style`` configuration. color_map : str or Colormap Color map of the stream lines, to be used in combination with the color parameter to specify intensity. Default depends on the ``figure_style`` configuration. arrow_size : float Arrow size multiplier. Default depends on the ``figure_style`` configuration. """
[docs] def __init__( self, x_data: ArrayLike, y_data: ArrayLike, u_data: ArrayLike, v_data: ArrayLike, density: float | tuple[float, float] = 1, line_width: float | Literal["default"] = "default", color: str | ArrayLike | Literal["default"] = "default", color_map: str | Colormap | Literal["default"] = "default", arrow_size: float | Literal["default"] = "default", ) -> None: """ This class implements stream plots. Parameters ---------- x_data, y_data : ArrayLike x and y coordinates of the vectors as a mesh grid. u_data, v_data : ArrayLike Magnitudes of the vectors for each point of the mesh grid. density : float or tuple[float, float] Density of stream lines. Can be specified independently for the x and y coordinates by specifying a density tuple instead. Defaults to 1. line_width : float Width of the stream lines. Default depends on the ``figure_style`` configuration. color : str or ArrayLike Color of the stream lines. If an array of intensities is provided, the values are mapped to the specified color map. Default depends on the ``figure_style`` configuration. color_map : str or Colormap Color map of the stream lines, to be used in combination with the color parameter to specify intensity. Default depends on the ``figure_style`` configuration. arrow_size : float Arrow size multiplier. Default depends on the ``figure_style`` configuration. """ self._x_data = np.asarray(x_data) self._y_data = np.asarray(y_data) self._u_data = np.asarray(u_data) self._v_data = np.asarray(v_data) self._density = density self._line_width = line_width self._color = color self._color_map = color_map self._arrow_size = arrow_size
[docs] @classmethod def from_function( cls, func: Callable[[ArrayLike, ArrayLike], tuple[ArrayLike, ArrayLike]], x_axis_range: tuple[float, float], y_axis_range: tuple[float, float], number_of_points_x: int = 30, number_of_points_y: int = 30, density: float | tuple[float, float] = 1, line_width: float | Literal["default"] = "default", color: str | Literal["default"] = "default", color_map: str | Colormap | Literal["default"] = "default", arrow_size: float | Literal["default"] = "default", ) -> Self: """ Creates a :class:`~graphinglib.data_plotting_2d.Stream` from a function. Parameters ---------- func : Callable[[ArrayLike, ArrayLike], [ArrayLike, ArrayLike]] Function to be plotted. Works with regular functions and lambda functions. x_axis_range : tuple[float, float] Range of x values. y_axis_range : tuple[float, float] Range of y values. number_of_points_x : int Number of points to fill the x range. Defaults to 30. number_of_points_y : int Number of points to fill the y range. Defaults to 30. density : float or tuple[float, float] Density of stream lines. Can be specified independently for the x and y coordinates by specifying a density tuple instead. Defaults to 1. line_width : float Width of the stream lines. Default depends on the ``figure_style`` configuration. color : str Color of the stream lines. Default depends on the ``figure_style`` configuration. color_map : str or Colormap Color map of the stream lines. Default depends on the ``figure_style`` configuration. arrow_size : float Arrow size multiplier. Default depends on the ``figure_style`` configuration. Returns ------- A :class:`~graphinglib.data_plotting_2d.Stream` object from a function. """ x = np.linspace(x_axis_range[0], x_axis_range[1], number_of_points_x) y = np.linspace(y_axis_range[0], y_axis_range[1], number_of_points_y) x_grid, y_grid = np.meshgrid(x, y) u, v = func(x_grid, y_grid) return cls(x, y, u, v, density, line_width, color, color_map, arrow_size)
[docs] def copy(self) -> Self: """ Returns a deep copy of the :class:`~graphinglib.data_plotting_2d.Stream`. """ return deepcopy(self)
def _plot_element(self, axes: plt.Axes, z_order: int, **kwargs) -> None: """ Plots the element in the specified Axes. """ params = { "density": self._density, "linewidth": self._line_width, "cmap": self._color_map, "arrowsize": self._arrow_size, } params = {k: v for k, v in params.items() if v != "default"} if isinstance(self._color, str) and self._color == "default": pass else: params["color"] = self._color axes.streamplot( x=self._x_data, y=self._y_data, u=self._u_data, v=self._v_data, zorder=z_order, **params, )