Source code for foxes.output.flow_plots_2d.flow_plots

import numpy as np

from foxes.output import SliceData
import foxes.variables as FV

from .get_fig import get_fig


[docs] class FlowPlots2D(SliceData): """ Class for horizontal or vertical 2D flow plots :group: output.flow_plots_2d """
[docs] def get_mean_fig_xy( self, var, xlabel="x [m]", ylabel="y [m]", levels=None, figsize=None, title=None, vlabel=None, fig=None, ax=None, add_bar=True, cmap=None, vmin=None, vmax=None, quiver_n=None, quiver_pars={}, ret_state=False, ret_im=False, ret_data=False, animated=False, **kwargs, ): """ Generates 2D farm flow figure in a horizontal xy-plane. Parameters ---------- var: str The variable name xlabel: str, optional The x axis label ylabel: str, optional The y axis label levels: int, optional The number of levels for the contourf plot, or None for pure image figsize: tuple, optional The figsize for plt.Figure title: str, optional The title vlabel: str, optional The variable label fig: plt.Figure, optional The figure object ax: plt.Axes, optional The figure axes add_bar: bool Add a color bar cmap: str, optional The colormap vmin: float, optional The minimal variable value vmax: float, optional The maximal variable value quiver_n: int, optional Place a vector at each `n`th point quiver_pars: dict, optional Parameters for plt.quiver ret_state: bool Flag for state index return ret_im: bool Flag for image return ret_data: bool Flag for returning image data animated: bool Switch for usage for an animation kwargs: dict, optional Additional parameters for SliceData.get_mean_data_xy Returns ------- fig: matplotlib.Figure The figure object si: int, optional The state index im: tuple, optional The image objects, matplotlib.collections.QuadMesh or matplotlib.QuadContourSet data: numpy.ndarray, optional The image data, shape: (n_x, n_y) """ variables = list(set([var] + [FV.WD, FV.WS])) vi = variables.index(var) wdi = variables.index(FV.WD) wsi = variables.index(FV.WS) data, gdata = self.get_mean_data_xy( variables=variables, vmin={var: vmin} if vmin is not None else {}, vmax={var: vmax} if vmax is not None else {}, data_format="numpy", ret_grid=True, **kwargs, ) x_pos, y_pos, z_pos, __ = gdata if title is None: title = f"States mean, z = {int(np.round(z_pos))} m" # define wind vector arrows: qpars = dict(angles="xy", scale_units="xy", scale=0.05) qpars.update(quiver_pars) quiv = ( None if quiver_n is None else ( quiver_n, qpars, data[None, :, :, wdi], data[None, :, :, wsi], ) ) # create plot: out = get_fig( var=var, fig=fig, figsize=figsize, ax=ax, data=data[None, :, :, vi], si=0, s=None, levels=levels, x_pos=x_pos, y_pos=y_pos, cmap=cmap, xlabel=xlabel, ylabel=ylabel, title=title, add_bar=add_bar, vlabel=vlabel, quiv=quiv, vmin=vmin, vmax=vmax, ret_state=ret_state, ret_im=ret_im, animated=animated, ) if ret_data: out = list(out) if isinstance(out, tuple) else [out] return tuple(out + [data[:, :, 0]]) return out
[docs] def get_mean_fig_xz( self, var, x_direction=270, xlabel="x [m]", zlabel="z [m]", levels=None, figsize=None, title=None, vlabel=None, fig=None, ax=None, add_bar=True, cmap=None, vmin=None, vmax=None, quiver_n=None, quiver_pars={}, ret_state=False, ret_im=False, ret_data=False, animated=False, **kwargs, ): """ Generates 2D farm flow figure in a horizontal xz-plane. Parameters ---------- var: str The variable name x_direction: float, optional The direction of the x axis, 0 = north xlabel: str, optional The x axis label zlabel: str, optional The z axis label levels: int, optional The number of levels for the contourf plot, or None for pure image figsize: tuple, optional The figsize for plt.Figure title: str, optional The title vlabel: str, optional The variable label fig: plt.Figure, optional The figure object ax: plt.Axes, optional The figure axes add_bar: bool Add a color bar cmap: str, optional The colormap vmin: float, optional The minimal variable value vmax: float, optional The maximal variable value quiver_n: int, optional Place a vector at each `n`th point quiver_pars: dict, optional Parameters for plt.quiver ret_state: bool Flag for state index return ret_im: bool Flag for image return ret_data: bool Flag for returning image data animated: bool Switch for usage for an animation kwargs: dict, optional Additional parameters for SliceData.get_mean_data_xz Returns ------- fig: matplotlib.Figure The figure object si: int, optional The state index im: tuple, optional The image objects, matplotlib.collections.QuadMesh or matplotlib.QuadContourSet data: numpy.ndarray, optional The image data, shape: (n_x, n_y) """ variables = list(set([var] + [FV.WD, FV.WS])) vi = variables.index(var) wdi = variables.index(FV.WD) wsi = variables.index(FV.WS) data, gdata = self.get_mean_data_xz( variables=variables, vmin={var: vmin} if vmin is not None else {}, vmax={var: vmax} if vmax is not None else {}, x_direction=x_direction, data_format="numpy", ret_grid=True, **kwargs, ) x_pos, y_pos, z_pos, __ = gdata if title is None: title = f"States mean, x direction {x_direction}°, y = {int(np.round(y_pos))} m" # define wind vector arrows: qpars = dict(angles="xy", scale_units="xy", scale=0.05) qpars.update(quiver_pars) quiv = ( None if quiver_n is None else ( quiver_n, qpars, data[None, :, :, wdi], data[None, :, :, wsi], ) ) # create plot: out = get_fig( var=var, fig=fig, figsize=figsize, ax=ax, data=data[None, :, :, vi], si=0, s=None, levels=levels, x_pos=x_pos, y_pos=z_pos, cmap=cmap, xlabel=xlabel, ylabel=zlabel, title=title, add_bar=add_bar, vlabel=vlabel, vmin=vmin, vmax=vmax, ret_state=ret_state, ret_im=ret_im, quiv=quiv, animated=animated, ) if ret_data: out = list(out) if isinstance(out, tuple) else [out] return tuple(out + [data[:, :, 0]]) return out
[docs] def get_mean_fig_yz( self, var, x_direction=270, ylabel="x [m]", zlabel="z [m]", levels=None, figsize=None, title=None, vlabel=None, fig=None, ax=None, add_bar=True, cmap=None, vmin=None, vmax=None, quiver_n=None, quiver_pars={}, ret_state=False, ret_im=False, ret_data=False, animated=False, **kwargs, ): """ Generates 2D farm flow figure in a horizontal yz-plane. Parameters ---------- var: str The variable name x_direction: float, optional The direction of the x axis, 0 = north ylabel: str, optional The y axis label zlabel: str, optional The z axis label levels: int, optional The number of levels for the contourf plot, or None for pure image figsize: tuple, optional The figsize for plt.Figure title: str, optional The title vlabel: str, optional The variable label fig: plt.Figure, optional The figure object ax: plt.Axes, optional The figure axes add_bar: bool Add a color bar cmap: str, optional The colormap vmin: float, optional The minimal variable value vmax: float, optional The maximal variable value quiver_n: int, optional Place a vector at each `n`th point quiver_pars: dict, optional Parameters for plt.quiver ret_state: bool Flag for state index return ret_im: bool Flag for image return ret_data: bool Flag for returning image data animated: bool Switch for usage for an animation kwargs: dict, optional Additional parameters for SliceData.get_mean_data_yz Returns ------- fig: matplotlib.Figure The figure object si: int, optional The state index im: tuple, optional The image objects, matplotlib.collections.QuadMesh or matplotlib.QuadContourSet data: numpy.ndarray, optional The image data, shape: (n_x, n_y) """ variables = list(set([var] + [FV.WD, FV.WS])) vi = variables.index(var) wdi = variables.index(FV.WD) wsi = variables.index(FV.WS) data, gdata = self.get_mean_data_yz( variables=variables, vmin={var: vmin} if vmin is not None else {}, vmax={var: vmax} if vmax is not None else {}, x_direction=x_direction, data_format="numpy", ret_grid=True, **kwargs, ) x_pos, y_pos, z_pos, __ = gdata if title is None: title = f"States mean, x direction {x_direction}°, x = {int(np.round(x_pos))} m" # define wind vector arrows: qpars = dict(angles="xy", scale_units="xy", scale=0.05) qpars.update(quiver_pars) quiv = ( None if quiver_n is None else ( quiver_n, qpars, data[None, :, :, wdi], data[None, :, :, wsi], ) ) # create plot: out = get_fig( var=var, fig=fig, figsize=figsize, ax=ax, data=data[None, :, :, vi], si=0, s=None, levels=levels, x_pos=y_pos, y_pos=z_pos, cmap=cmap, xlabel=ylabel, ylabel=zlabel, title=title, add_bar=add_bar, vlabel=vlabel, vmin=vmin, vmax=vmax, ret_state=ret_state, ret_im=ret_im, quiv=quiv, invert_axis="x", animated=animated, ) if ret_data: out = list(out) if isinstance(out, tuple) else [out] return tuple(out + [data[:, :, 0]]) return out
[docs] def gen_states_fig_xy( self, var, xlabel="x [m]", ylabel="y [m]", levels=None, figsize=None, title=None, vlabel=None, fig=None, ax=None, add_bar=True, cmap=None, vmin=None, vmax=None, quiver_n=None, quiver_pars={}, ret_state=False, ret_im=False, animated=False, rotor_color=None, precalc=False, **kwargs, ): """ Generates 2D farm flow figure in a horizontal xy-plane. Parameters ---------- var: str The variable name xlabel: str, optional The x axis label ylabel: str, optional The y axis label levels: int, optional The number of levels for the contourf plot, or None for pure image figsize: tuple, optional The figsize for plt.Figure title: str, optional The title vlabel: str, optional The variable label fig: plt.Figure, optional The figure object ax: plt.Axes, optional The figure axes add_bar: bool Add a color bar cmap: str, optional The colormap vmin: float, optional The minimal variable value vmax: float, optional The maximal variable value quiver_n: int, optional Place a vector at each `n`th point quiver_pars: dict, optional Parameters for plt.quiver ret_state: bool Flag for state index return ret_im: bool Flag for image return animated: bool Switch for usage for an animation rotor_color: str, optional Indicate the rotor orientation by a colored line precalc: bool or tuple Flag for pre-calculation run, adding an additional generator call before the actual plot generations, yields data, states, gdata. The same tuple can be given for avoiding its calculation and picking up from there. kwargs: dict, optional Additional parameters for SliceData.get_states_data_xy Yields ------ fig: matplotlib.Figure The figure object si: int, optional The state index im: tuple, optional The image objects, matplotlib.collections.QuadMesh or matplotlib.QuadContourSet """ variables = list(set([var] + [FV.WD, FV.WS])) vi = variables.index(var) wdi = variables.index(FV.WD) wsi = variables.index(FV.WS) if isinstance(precalc, (tuple, list)): data, states, gdata = precalc else: data, states, gdata = self.get_states_data_xy( variables=variables, vmin={var: vmin} if vmin is not None else {}, vmax={var: vmax} if vmax is not None else {}, data_format="numpy", ret_states=True, ret_grid=True, **kwargs, ) if precalc: yield data, states, gdata x_pos, y_pos, z_pos, __ = gdata # define wind vector arrows: qpars = dict(angles="xy", scale_units="xy", scale=0.05) qpars.update(quiver_pars) quiv = ( None if quiver_n is None else ( quiver_n, qpars, data[..., wdi], data[..., wsi], ) ) # loop over states: for si, s in enumerate(states): if animated and si == 0: vmin = vmin if vmin is not None else np.min(data[..., vi]) vmax = vmax if vmax is not None else np.max(data[..., vi]) elif animated and si > 0: add_bar = False if not animated and title is None: ttl = f"State {s}" ttl += f", z = {int(np.round(z_pos))} m" elif callable(title): ttl = title(si, s) else: ttl = title # get data for show_turbines if rotor_color is not None: try: turb_angle = self.fres[FV.AMB_WD][si] + self.fres[FV.YAWM][si] except KeyError: turb_angle = self.fres[FV.AMB_WD][si] show_rotor_dict = { "color": rotor_color, "D": self.fres[FV.D][si], "H": self.fres[FV.H][si], "X": self.fres[FV.X][si], "Y": self.fres[FV.Y][si], "AMB_WD": self.fres[FV.AMB_WD][si], "turb_angle": turb_angle, } else: show_rotor_dict = None out = get_fig( var=var, fig=fig, figsize=figsize, ax=ax, data=data[..., vi], si=si, s=s, levels=levels, x_pos=x_pos, y_pos=y_pos, cmap=cmap, xlabel=xlabel, ylabel=ylabel, title=ttl, add_bar=add_bar, vlabel=vlabel, vmin=vmin, vmax=vmax, quiv=quiv, ret_state=ret_state, ret_im=ret_im, animated=animated, show_rotor_dict=show_rotor_dict, ) yield out
[docs] def gen_states_fig_xz( self, var, x_direction=270.0, xlabel="x [m]", zlabel="z [m]", levels=None, figsize=None, title=None, vlabel=None, fig=None, ax=None, add_bar=True, cmap=None, vmin=None, vmax=None, quiver_n=None, quiver_pars={}, ret_state=False, ret_im=False, animated=False, rotor_color=None, precalc=False, **kwargs, ): """ Generates 2D farm flow figure in a vertical xz-plane. Parameters ---------- var: str The variable name x_direction: float, optional The direction of the x axis, 0 = north xlabel: str, optional The x axis label zlabel: str, optional The z axis label levels: int, optional The number of levels for the contourf plot, or None for pure image figsize: tuple, optional The figsize for plt.Figure title: str, optional The title vlabel: str, optional The variable label fig: plt.Figure, optional The figure object ax: plt.Axes, optional The figure axes add_bar: bool Add a color bar cmap: str, optional The colormap vmin: float, optional The minimal variable value vmax: float, optional The maximal variable value quiver_n: int, optional Place a vector at ech `n`th point quiver_pars: dict, optional Parameters for plt.quiver ret_state: bool Flag for state index return ret_im: bool Flag for image return animated: bool Switch for usage for an animation rotor_color: str, optional Indicate the rotor orientation by a colored line precalc: bool or tuple Flag for pre-calculation run, adding an additional generator call before the actual plot generations, yields data, states, gdata. The same tuple can be given for avoiding its calculation and picking up from there. kwargs: dict, optional Additional parameters for SliceData.get_states_data_xz Yields ------ fig: matplotlib.Figure The figure object si: int, optional The state index im: tuple, optional The image objects, matplotlib.collections.QuadMesh or matplotlib.QuadContourSet """ variables = list(set([var] + [FV.WD, FV.WS])) vi = variables.index(var) wdi = variables.index(FV.WD) wsi = variables.index(FV.WS) if isinstance(precalc, (tuple, list)): data, states, gdata = precalc else: data, states, gdata = self.get_states_data_xz( variables=variables, vmin={var: vmin} if vmin is not None else {}, vmax={var: vmax} if vmax is not None else {}, data_format="numpy", ret_states=True, ret_grid=True, x_direction=x_direction, **kwargs, ) if precalc: yield data, states, gdata x_pos, y_pos, z_pos, __ = gdata # define wind vector arrows: qpars = dict(angles="xy", scale_units="xy", scale=0.05) qpars.update(quiver_pars) quiv = ( None if quiver_n is None else ( quiver_n, qpars, data[..., wdi], data[..., wsi], ) ) # loop over states: for si, s in enumerate(states): if animated and si > 0 and vmin is not None and vmax is not None: add_bar = False if not animated and title is None: ttl = f"State {s}" ttl += f", x direction = {x_direction}°" ttl += f", y = {int(np.round(y_pos))} m" elif callable(title): ttl = title(si, s) else: ttl = title # get data for show_turbines if rotor_color is not None: try: turb_angle = self.fres[FV.AMB_WD][si] + self.fres[FV.YAWM][si] except KeyError: turb_angle = self.fres[FV.AMB_WD][si] show_rotor_dict = { "color": rotor_color, "D": self.fres[FV.D][si], "H": self.fres[FV.H][si], "X": self.fres[FV.X][si], "Y": self.fres[FV.Y][si], "AMB_WD": self.fres[FV.AMB_WD][si], "turb_angle": turb_angle, } else: show_rotor_dict = None out = get_fig( var=var, fig=fig, figsize=figsize, ax=ax, data=data[..., vi], si=si, s=s, levels=levels, x_pos=x_pos, y_pos=z_pos, cmap=cmap, xlabel=xlabel, ylabel=zlabel, title=ttl, add_bar=add_bar, vlabel=vlabel, quiv=quiv, vmin=vmin, vmax=vmax, ret_state=ret_state, ret_im=ret_im, animated=animated, show_rotor_dict=show_rotor_dict, ) yield out
[docs] def gen_states_fig_yz( self, var, x_direction=270.0, ylabel="y [m]", zlabel="z [m]", levels=None, figsize=None, title=None, vlabel=None, fig=None, ax=None, add_bar=True, cmap=None, vmin=None, vmax=None, quiver_n=None, quiver_pars={}, ret_state=False, ret_im=False, animated=False, rotor_color=None, precalc=False, **kwargs, ): """ Generates 2D farm flow figure in a vertical yz-plane. Parameters ---------- var: str The variable name x_direction: float, optional The direction of the x axis, 0 = north ylabel: str, optional The y axis label zlabel: str, optional The z axis label levels: int, optional The number of levels for the contourf plot, or None for pure image figsize: tuple, optional The figsize for plt.Figure title: str, optional The title vlabel: str, optional The variable label fig: plt.Figure, optional The figure object ax: plt.Axes, optional The figure axes add_bar: bool Add a color bar cmap: str, optional The colormap vmin: float, optional The minimal variable value vmax: float, optional The maximal variable value quiver_n: int, optional Place a vector at ech `n`th point quiver_pars: dict, optional Parameters for plt.quiver ret_state: bool Flag for state index return ret_im: bool Flag for image return animated: bool Switch for usage for an animation rotor_color: str, optional Indicate the rotor orientation by a colored line precalc: bool or tuple Flag for pre-calculation run, adding an additional generator call before the actual plot generations, yields data, states, gdata. The same tuple can be given for avoiding its calculation and picking up from there. kwargs: dict, optional Additional parameters for SliceData.get_states_data_yz Yields ------ fig: matplotlib.Figure The figure object si: int, optional The state index im: tuple, optional The image objects, matplotlib.collections.QuadMesh or matplotlib.QuadContourSet """ variables = list(set([var] + [FV.WD, FV.WS])) vi = variables.index(var) wdi = variables.index(FV.WD) wsi = variables.index(FV.WS) if isinstance(precalc, (tuple, list)): data, states, gdata = precalc else: data, states, gdata = self.get_states_data_yz( variables=variables, vmin={var: vmin} if vmin is not None else {}, vmax={var: vmax} if vmax is not None else {}, data_format="numpy", ret_states=True, ret_grid=True, x_direction=x_direction, **kwargs, ) if precalc: yield data, states, gdata x_pos, y_pos, z_pos, __ = gdata # define wind vector arrows: qpars = dict(angles="xy", scale_units="xy", scale=0.05) qpars.update(quiver_pars) quiv = ( None if quiver_n is None else ( quiver_n, qpars, data[..., wdi], data[..., wsi], ) ) # loop over states: for si, s in enumerate(states): if animated and si > 0 and vmin is not None and vmax is not None: add_bar = False if not animated and title is None: ttl = f"State {s}" if title is None else title ttl += f", x direction = {x_direction}°" ttl += f", x = {int(np.round(x_pos))} m" elif callable(title): ttl = title(si, s) else: ttl = title # get data for show_turbines if rotor_color is not None: try: turb_angle = self.fres[FV.AMB_WD][si] + self.fres[FV.YAWM][si] except KeyError: turb_angle = self.fres[FV.AMB_WD][si] show_rotor_dict = { "color": rotor_color, "D": self.fres[FV.D][si], "H": self.fres[FV.H][si], "X": self.fres[FV.X][si], "Y": self.fres[FV.Y][si], "AMB_WD": self.fres[FV.AMB_WD][si], "turb_angle": turb_angle, } else: show_rotor_dict = None out = get_fig( var=var, fig=fig, figsize=figsize, ax=ax, data=data[..., vi], si=si, s=s, levels=levels, x_pos=y_pos, y_pos=z_pos, cmap=cmap, xlabel=ylabel, ylabel=zlabel, title=ttl, add_bar=add_bar, vlabel=vlabel, vmin=vmin, vmax=vmax, quiv=quiv, ret_state=ret_state, ret_im=ret_im, invert_axis="x", animated=animated, show_rotor_dict=show_rotor_dict, ) yield out