Source code for osaft.plotting.scattering.fluid_plots

from __future__ import annotations

from collections.abc import Callable
from functools import partial

import numpy as np
from matplotlib import colors
from matplotlib import pyplot as plt
from matplotlib.animation import FuncAnimation
from matplotlib.cm import ScalarMappable
from matplotlib.quiver import Quiver

from osaft.core.functions import pi, sqrt
from osaft.plotting.datacontainers.scattering_datacontainer import (
    FluidScatteringData,
)
from osaft.plotting.scattering.base_scattering_plots import (
    BaseScatteringPlots,
)
from osaft.plotting.scattering.tri_plotter import TriangulationPlotter
from osaft.solutions.base_scattering import BaseScattering

NDArray = np.ndarray


[docs]class FluidScatteringPlot(BaseScatteringPlots): """Class for plotting scattering field of the fluid Plots the acoustic field in the fluid around the scatterer using Matplotlib tricontourf or tripcolor plotting methods. :param sol: solution to be plotted :param r_max: radial limit of plot range :param resolution: if tuple (radial resolution, tangential resolution) :param n_quiver_points: anchor points along z for quiver :param cmap: color map :param div_cmap: diverging color map """ def __init__( self, sol: BaseScattering, r_max: float, resolution: int | tuple[int, int] = 100, n_quiver_points: int = 21, cmap: str = "winter", div_cmap: str = "coolwarm", ): """Constructor method""" self.data = FluidScatteringData( sol, sqrt(2) * r_max, res=resolution, n_quiver_points=n_quiver_points, ) self.plotter = TriangulationPlotter(False, cmap, div_cmap) # ------------------------------------------------------------------------- # Attributes # ------------------------------------------------------------------------- @property def cmap(self) -> str: """Colormap for plotting :getter: return the colormap choice :setter: sets the colormap choice """ return self.plotter.cmap @cmap.setter def cmap(self, value: str) -> None: self.plotter.cmap = value @property def div_cmap(self) -> str: """Diverging Colormap for plotting :getter: return the diverging colormap choice :setter: sets the diverging colormap choice """ return self.plotter.div_cmap @div_cmap.setter def div_cmap(self, value: str) -> None: self.plotter.div_cmap = value # ------------------------------------------------------------------------- # API # -------------------------------------------------------------------------
[docs] def plot_velocity_potential( self, inst: bool = True, phase: float = 0, symmetric: bool = True, mode: None | int = None, scattered: bool = True, incident: bool = True, tripcolor: bool = False, ax: None | plt.Axes = None, **kwargs, ) -> tuple[plt.Figure, plt.Axes]: """Tricontourf plot for acoustic velocity potential Plots the velocity amplitude of the first-order acoustic velocity field of the fluid using Matplotlib's `tricontourf <https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot .tricontour.html>`_ or `tripcolor <https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot .tripcolor.html>`_ if ``tripcolor = True`` :param inst: if ``True`` instantaneous amplitude is plotted :param phase: phase :math:`[0, 2\\pi]` :param mode: mode of oscillation :param scattered: if ``True`` scattering field is plotted :param incident: if ``True`` incident field is plotted :param symmetric: if ``True`` the symmetry of the solution is used :param tripcolor: switches between tripcolor and tricontourf plot :param ax: if ``ax`` is passed, plot will be drawn on ``ax`` :param kwargs: passed through to tricontourf() """ data = self.data.get_velocity_potential( inst, phase, mode, scattered, incident, ) abs_max = np.abs(data[-1]).max() if inst and abs_max != 0: norm = colors.TwoSlopeNorm( vmin=-abs_max, vcenter=0.0, vmax=abs_max, ) use_div_cmap = True else: norm = colors.Normalize(vmin=0, vmax=abs_max) use_div_cmap = False return self._triangulation_plot( data=data, cbar_label="Acoustic Velocity Potential [m^2/s]", tripcolor=tripcolor, mode=mode, symmetric=symmetric, use_diverging_cmap=use_div_cmap, ax=ax, norm=norm, **kwargs, )
[docs] def plot_pressure( self, inst: bool = True, phase: float = 0, symmetric: bool = True, mode: None | int = None, scattered: bool = True, incident: bool = True, tripcolor: bool = False, ax: None | plt.Axes = None, **kwargs, ) -> tuple[plt.Figure, plt.Axes]: """Tricontourf plot for acoustic pressure Plots the velocity amplitude of the first-order acoustic velocity field of the fluid using Matplotlib's `tricontourf <https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot .tricontour.html>`_ or `tripcolor <https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot .tripcolor.html>`_ if ``tripcolor = True`` :param inst: if ``True`` instantaneous amplitude is plotted :param phase: phase :math:`[0, 2\\pi]` :param mode: mode of oscillation :param scattered: if ``True`` scattering field is plotted :param incident: if ``True`` incident field is plotted :param symmetric: if ``True`` the symmetry of the solution is used :param tripcolor: switches between tripcolor and tricontourf plot :param ax: if ``ax`` is passed, plot will be drawn on ``ax`` :param kwargs: passed through to tricontourf() """ data = self.data.get_pressure( inst, phase, mode, scattered, incident, ) abs_max = np.abs(data[-1]).max() if inst and abs_max != 0: norm = colors.TwoSlopeNorm( vmin=-abs_max, vcenter=0.0, vmax=abs_max, ) use_div_cmap = True else: norm = colors.Normalize(vmin=0, vmax=abs_max) use_div_cmap = False return self._triangulation_plot( data=data, cbar_label="Acoustic Pressure [Pa]", tripcolor=tripcolor, mode=mode, symmetric=symmetric, use_diverging_cmap=use_div_cmap, ax=ax, norm=norm, **kwargs, )
[docs] def plot_velocity( self, inst: bool = True, phase: float = 0, mode: None | int = None, scattered: bool = True, incident: bool = True, symmetric: bool = True, quiver_color: None | str = None, tripcolor: bool = False, ax: None | plt.Axes = None, **kwargs, ) -> tuple[plt.Figure, plt.Axes]: """Tricontourf plot for acoustic velocity field of the fluid Plots the velocity amplitude of the first-order acoustic velocity field of the fluid using Matplotlib's `tricontourf <https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot .tricontour.html>`_ or `tripcolor <https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot .tripcolor.html>`_ if ``tripcolor = True`` :param inst: if ``True`` instantaneous amplitude is plotted :param phase: phase ``[0, 2 * pi]`` :param mode: mode of oscillation :param scattered: if ``True`` scattering field is plotted :param incident: if ``True`` incident field is plotted :param symmetric: if ``True`` the symmetry of the solution is used :param tripcolor: switches between tripcolor and tricontourf plot :param ax: if ``ax`` is passed, plot will be drawn on ``ax`` :param kwargs: passed through to tricontourf() """ data = self.data.get_velocity_magnitude( inst, phase, mode, scattered, incident, ) fig, ax = self._triangulation_plot( data=data, cbar_label="Acoustic Velocity [m/s]", tripcolor=tripcolor, mode=mode, symmetric=symmetric, use_diverging_cmap=False, ax=ax, **kwargs, ) if quiver_color: self._overlay_quiver( ax, phase, scattered, incident, mode, symmetric, quiver_color, animation=False, ) return fig, ax
[docs] def animate_pressure( self, frames: int = 64, interval: float = 100.0, mode: None | int = None, scattered: bool = True, incident: bool = True, symmetric: bool = True, tripcolor: bool = False, ax: None | plt.Axes = None, **kwargs, ) -> FuncAnimation: """Tricontourf animation for acoustic pressure of the fluid Animates the pressure of the first-order acoustic velocity field of the fluid over one period using Matplotlib's `tricontourf <https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot .tricontour.html>`_ or `tripcolor <https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot .tripcolor.html>`_ if ``tripcolor = True`` :param frames: number of frames for the animation :param interval: interval between frames in ms :param mode: mode of oscillation :param scattered: if ``True`` scattering field is plotted :param incident: if ``True`` incident field is plotted :param symmetric: if ``True`` the symmetry of the solution is used :param tripcolor: switches between tripcolor and tricontourf plot :param ax: if ``ax`` is passed, plot will be drawn on ``ax`` :param kwargs: passed through to tricontourf() """ data_meth = self.data.get_pressure return self._triangulation_animation( data_meth, tripcolor=tripcolor, frames=frames, interval=interval, mode=mode, scattered=scattered, incident=incident, symmetric=symmetric, ax=ax, cbar_label="Acoustic Pressure [Pa]", use_diverging_cmap=True, **kwargs, )
[docs] def animate_velocity_potential( self, frames: int = 64, interval: float = 100.0, mode: None | int = None, scattered: bool = True, incident: bool = True, symmetric: bool = True, tripcolor: bool = False, ax: None | plt.Axes = None, **kwargs, ) -> FuncAnimation: """Tricontourf animation for acoustic velocity potential of the fluid Animates the velocity potential of the first-order acoustic velocity field of the fluid over one period using Matplotlib's `tricontourf <https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot .tricontour.html>`_ or `tripcolor <https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot .tripcolor.html>`_ if ``tripcolor = True`` :param frames: number of frames for the animation :param interval: interval between frames in ms :param mode: mode of oscillation :param scattered: if ``True`` scattering field is plotted :param incident: if ``True`` incident field is plotted :param symmetric: if ``True`` the symmetry of the solution is used :param tripcolor: switches between tripcolor and tricontourf plot :param ax: if ``ax`` is passed, plot will be drawn on ``ax`` :param kwargs: passed through to tricontourf() """ data_meth = self.data.get_velocity_potential return self._triangulation_animation( data_meth, tripcolor=tripcolor, frames=frames, interval=interval, mode=mode, scattered=scattered, incident=incident, symmetric=symmetric, ax=ax, cbar_label="Acoustic Velocity Potential [m^2/s]", use_diverging_cmap=True, **kwargs, )
[docs] def animate_velocity( self, frames: int = 64, interval: float = 100.0, mode: None | int = None, scattered: bool = True, incident: bool = True, symmetric: bool = True, quiver_color: None | str = None, tripcolor: bool = False, ax: None | plt.Axes = None, **kwargs, ) -> FuncAnimation: """Tricontourf animation for acoustic velocity field of the fluid Animates the velocity amplitude of the first-order acoustic velocity field of the fluid over one period using Matplotlib's `tricontourf <https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot .tricontour.html>`_ or `tripcolor <https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot .tripcolor.html>`_ if ``tripcolor = True`` :param frames: number of frames for the animation :param interval: interval between frames in ms :param mode: mode of oscillation :param scattered: if ``True`` scattering field is plotted :param incident: if ``True`` incident field is plotted :param symmetric: if ``True`` the symmetry of the solution is used :param quiver_color: if not ``None``, quiver plot :param tripcolor: switches between tripcolor and tricontourf plot :param ax: if ``ax`` is passed, plot will be drawn on ``ax`` :param kwargs: passed through to tricontourf() """ if quiver_color: fig, ax = self.plot_velocity( inst=False, mode=mode, scattered=scattered, incident=incident, symmetric=symmetric, ) Q = self._overlay_quiver( ax, 0, scattered, incident, mode, symmetric, animation=True, quiver_color=quiver_color, ) annotation = self.plotter._annotate_phase(ax, 0) def animate_quiver(frame: int, frames: int, Q: Quiver, annotation): phase = frame / frames * 2 * pi _, _, u, w, _ = self.data.get_velocity_quiver( phase, mode, scattered, incident, symmetric, animation=True, ) self.plotter._update_phase_annotation(annotation, phase) Q.set_UVC(u, w) return (Q,) anim = FuncAnimation( fig, animate_quiver, frames=frames, interval=interval, blit=False, fargs=(frames, Q, annotation), ) return anim else: data_meth = self.data.get_velocity_magnitude return self._triangulation_animation( data_meth, tripcolor=tripcolor, frames=frames, interval=interval, mode=mode, scattered=scattered, incident=incident, symmetric=symmetric, ax=ax, cbar_label="Acoustic Velocity [m/s]", use_diverging_cmap=False, **kwargs, )
[docs] def plot_pressure_evolution( self, inst: bool = True, mode: None | int = None, scattered: bool = True, incident: bool = True, symmetric: bool = True, tripcolor: bool = False, layout: tuple[int, int] = (3, 3), **kwargs, ) -> tuple[plt.Figure, plt.Axes]: """Tricontourf for acoustic pressure evolution of the fluid Plots the pressure amplitude of the first-order acoustic pressure field of the fluid over one period at different phases using Matplotlib's `tricontourf <https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot .tricontour.html>`_ or `tripcolor <https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot .tripcolor.html>`_ if ``tripcolor = True``. The first phase value is always :math:`0\\pi` and the last one :math:`2\\pi`. The total number of plots and, hence, also the steps between the different phase values is the defined by the product of the ``layout`` tuple. :param inst: if ``True`` instantaneous amplitude is plotted :param mode: mode of oscillation :param scattered: if ``True`` scattering field is plotted :param incident: if ``True`` incident field is plotted :param symmetric: if ``True`` the symmetry of the solution is used :param tripcolor: switches between tripcolor and tricontourf plot :param layout: number of rows and columns for plotting :param kwargs: passed through to the parent subplots command """ n_row, n_col, phases = self._evo_compute_layout(layout) fig, axes = self._evo_create_subplots(n_row, n_col, **kwargs) get_data = partial( self.data.get_pressure, incident=incident, scattered=scattered, ) # Get velocity norm, needed to make colormap of the right range X, Z, C_norm = get_data(instantaneous=False, mode=mode, phase=0) # Only values inside the plotting range C_norm = np.where( np.hypot(X, Z) < self.data.r_max, C_norm, 0, ) vmax = 1.01 * np.abs(C_norm).max() vmin = -vmax # Color bar label cbar_label = "Acoustic Pressure [Pa]" for i, phase in enumerate(phases): row = i // n_col col = i % n_col ax = axes.flat[i] X, Z, C = get_data(instantaneous=True, mode=mode, phase=phase) self._evo_plot( X=Z, Y=X, C=C, symmetric=symmetric, tripcolor=tripcolor, cbar_label=cbar_label, use_diverging_cmap=True, ax=ax, vmin=vmin, vmax=vmax, ) self._evo_clean_axis(ax, phase, row, col, n_row) norm = colors.TwoSlopeNorm(vmin=vmin, vcenter=0, vmax=vmax) self._evo_create_cbar( fig, axes, cbar_label, self.plotter.div_cmap, norm, ) return fig, axes
[docs] def plot_velocity_potential_evolution( self, inst: bool = True, mode: None | int = None, scattered: bool = True, incident: bool = True, symmetric: bool = True, tripcolor: bool = False, layout: tuple[int, int] = (3, 3), **kwargs, ) -> tuple[plt.Figure, plt.Axes]: """Tricontourf for acoustic velocity potential evolution of the fluid Plots the velocity potential amplitude of the first-order acoustic velocity potential field of the fluid over one period at different phases using Matplotlib's `tricontourf <https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot .tricontour.html>`_ or `tripcolor <https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot .tripcolor.html>`_ if ``tripcolor = True``. The first phase value is always :math:`0\\pi` and the last one :math:`2\\pi`. The total number of plots and, hence, also the steps between the different phase values is the defined by the product of the ``layout`` tuple. :param inst: if ``True`` instantaneous amplitude is plotted :param mode: mode of oscillation :param scattered: if ``True`` scattering field is plotted :param incident: if ``True`` incident field is plotted :param symmetric: if ``True`` the symmetry of the solution is used :param tripcolor: switches between tripcolor and tricontourf plot :param layout: number of rows and columns for plotting :param kwargs: passed through to the parent subplots command """ n_row, n_col, phases = self._evo_compute_layout(layout) fig, axes = self._evo_create_subplots(n_row, n_col, **kwargs) get_data = partial( self.data.get_velocity_potential, incident=incident, scattered=scattered, ) X, Z, C_norm = get_data(instantaneous=False, mode=mode, phase=0) # Only values inside the plotting range C_norm = np.where( np.hypot(X, Z) < self.data.r_max, C_norm, 0, ) vmax = 1.01 * np.abs(C_norm).max() vmin = -vmax # Color bar label cbar_label = "Acoustic Velocity Potential [m^2/s]" for i, phase in enumerate(phases): row = i // n_col col = i % n_col ax = axes.flat[i] X, Z, C = get_data(instantaneous=True, mode=mode, phase=phase) self._evo_plot( X=Z, Y=X, C=C, symmetric=symmetric, tripcolor=tripcolor, cbar_label=cbar_label, use_diverging_cmap=True, ax=ax, vmin=vmin, vmax=vmax, ) self._evo_clean_axis(ax, phase, row, col, n_row) norm = colors.TwoSlopeNorm(vmin=vmin, vcenter=0, vmax=vmax) self._evo_create_cbar( fig, axes, cbar_label, self.plotter.div_cmap, norm, ) return fig, axes
[docs] def plot_velocity_evolution( self, mode: None | int = None, scattered: bool = True, incident: bool = True, symmetric: bool = True, quiver_color: None | str = None, tripcolor: bool = False, layout: tuple[int, int] = (3, 3), **kwargs, ) -> tuple[plt.Figure, plt.Axes]: """Tricontourf for acoustic velocity field evolution of the fluid Plots the velocity amplitude of the first-order acoustic velocity field of the fluid over one period at different phases using Matplotlib's `tricontourf <https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot .tricontour.html>`_ or `tripcolor <https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot .tripcolor.html>`_ if ``tripcolor = True``. The first phase value is always :math:`0\\pi` and the last one :math:`2\\pi`. The total number of plots and, hence, also the steps between the different phase values is the defined by the product of the ``layout`` tuple. :param mode: mode of oscillation :param scattered: if ``True`` scattering field is plotted :param incident: if ``True`` incident field is plotted :param symmetric: if ``True`` the symmetry of the solution is used :param quiver_color: color of the quiver arrows, if None: no arrows :param tripcolor: switches between tripcolor and tricontourf plot :param layout: number of rows and columns for plotting :param kwargs: passed through to the parent subplots command """ n_row, n_col, phases = self._evo_compute_layout(layout) fig, axes = self._evo_create_subplots(n_row, n_col, **kwargs) get_data = partial( self.data.get_velocity_magnitude, incident=incident, scattered=scattered, ) X, Z, C_norm = get_data(instantaneous=False, mode=mode, phase=0) # Only values inside the plotting range C_norm = np.where( np.hypot(X, Z) < self.data.r_max, C_norm, 0, ) vmin = 0 vmax = 1.01 * C_norm.max() # Color bar label cbar_label = "Acoustic Velocity [m/s]" for i, phase in enumerate(phases): row = i // n_col col = i % n_col ax = axes.flat[i] X, Z, C = get_data(instantaneous=True, mode=mode, phase=phase) self._evo_plot( X=Z, Y=X, C=C, symmetric=symmetric, tripcolor=tripcolor, cbar_label=cbar_label, use_diverging_cmap=False, ax=ax, vmin=vmin, vmax=vmax, ) if quiver_color: self._overlay_quiver( ax, phase, scattered, incident, mode, symmetric, animation=False, quiver_color=quiver_color, ) self._evo_clean_axis(ax, phase, row, col, n_row) norm = colors.Normalize(vmin=vmin, vmax=vmax) self._evo_create_cbar(fig, axes, cbar_label, self.plotter.cmap, norm) return fig, axes
# ------------------------------------------------------------------------- # Private Methods for evolution plots # ------------------------------------------------------------------------- def _evo_plot( self, X: NDArray, Y: NDArray, C: NDArray, symmetric: bool, tripcolor: bool, cbar_label: str, use_diverging_cmap: bool, ax: plt.Axes, vmin: float, vmax: float, ) -> None: # Plot _, _, _, cbar, _ = self.plotter.plot( X=X, Y=Y, C=C, radius=self.data.sol.R_0, symmetric=symmetric, tripcolor=tripcolor, cbar_label=cbar_label, use_diverging_cmap=use_diverging_cmap, ax=ax, vmin=vmin, vmax=vmax, ) cbar.remove() @staticmethod def _evo_create_cbar( fig: plt.Figure, axes: plt.Axes, cbar_label: str, cmap: str, norm: colors.Normalize, ) -> None: fig.tight_layout() cm = ScalarMappable(norm, cmap) cbar = fig.colorbar(cm, ax=axes.ravel().tolist()) cbar.ax.set_ylabel(cbar_label) @staticmethod def _evo_create_subplots( n_row: int, n_col: int, **kwargs, ) -> tuple[plt.Figure, plt.Axes]: fig, axes = plt.subplots( n_row, n_col, sharex=True, sharey=True, **kwargs, ) return fig, axes @staticmethod def _evo_compute_layout( layout: tuple[int, int], ) -> tuple[int, int, NDArray]: n_row, n_col = layout n = n_col * n_row phases = np.linspace(0, 2 * np.pi, num=n) return n_row, n_col, phases def _evo_clean_axis( self, ax: plt.Axes, phase: float, row: int, col: int, n_row: int, ) -> None: ticks = self.data.sol.R_0 * np.asarray([-1, 1]) labels = [-1, 1] ax.set_title(f"{phase / np.pi:.2f}" + r"$\pi$") if row != (n_row - 1): ax.set_xlabel("") if col > 0: ax.set_ylabel("") ax.set_xticks(ticks, labels=labels) ax.set_yticks(ticks, labels=labels) # set aspect ratio to 1:1 ax.set_aspect(1) # ------------------------------------------------------------------------- # Private Methods # ------------------------------------------------------------------------- def _triangulation_plot( self, data: tuple[NDArray, NDArray, NDArray], cbar_label: str, tripcolor: bool, symmetric: bool, use_diverging_cmap: bool, ax: None | plt.Axes, **kwargs, ) -> tuple[plt.Figure, plt.Axes]: """Helper function for tripcolor/tricontourf plot :param data: data to be plotted (X, Z, plot_data) :param cbar_label: label for the colorbar :param tripcolor: if ``True`` tripcolor, else tricontourf plot :param symmetric: if ``True`` the symmetry of the solution is used :param ax: if ``ax`` is passed, plot will be drawn on ``ax`` :param kwargs: passed through to plotting method """ kwargs.pop("mode", None) X, Z, C = data # Plot fig, ax, _, _, _ = self.plotter.plot( X=Z, Y=X, C=C, radius=self.data.sol.R_0, symmetric=symmetric, tripcolor=tripcolor, cbar_label=cbar_label, ax=ax, use_diverging_cmap=use_diverging_cmap, **kwargs, ) return fig, ax def _triangulation_animation( self, data_meth: Callable[ [bool, float, int, bool, bool], tuple[NDArray, NDArray, NDArray], ], tripcolor: bool, frames: int, interval: float, mode: None | int, scattered: bool, incident: bool, symmetric: bool, cbar_label: str, use_diverging_cmap: bool, ax: None | plt.Axes, **kwargs, ) -> FuncAnimation: """Helper function for tripcolor/tricontourf animation :param data_meth: method for getting the plotting data :param tripcolor: if ``True`` tripcolor, else tricontourf plot :param frames: number of frames for the animation :param interval: interval between frames in ms :param mode: mode of oscillation :param scattered: if ``True`` scattering field is plotted :param incident: if ``True`` incident field is plotted :param symmetric: if ``True`` the symmetry of the solution is used :param cbar_label: label of colorbar :param use_diverging_cmap: use :attr:`div_cmap` as colormap :param ax: if ``ax`` is passed, plot will be drawn on ``ax`` :param kwargs: passed through to tricontourf() """ # Data function for animation animate_meth = lambda phase: data_meth( phase=phase, instantaneous=True, mode=mode, scattered=scattered, incident=incident, ) # Get velocity norm, needed to make colormap of the right range X, Y, C_norm = data_meth( instantaneous=False, mode=mode, scattered=scattered, incident=incident, ) # Only values inside the plotting range C_norm = np.where( np.hypot(X, Y) < self.data.r_max, C_norm, 0, ) return self.plotter.animate( frames=frames, interval=interval, tripcolor=tripcolor, symmetric=symmetric, cbar_label=cbar_label, use_diverging_cmap=use_diverging_cmap, animate_meth=animate_meth, C_norm=C_norm, radius=self.data.sol.R_0, ax=ax, **kwargs, )
if __name__ == "__main__": pass