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,
**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
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)
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,
)
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", 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,
**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
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)
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,
**kwargs,
)
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,
**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
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)
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,
**kwargs,
)
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