Skip to content

Commit

Permalink
Refactor plotting code
Browse files Browse the repository at this point in the history
  • Loading branch information
sdahdah committed Dec 4, 2024
1 parent 84a998b commit b7c8a35
Show file tree
Hide file tree
Showing 6 changed files with 162 additions and 142 deletions.
4 changes: 2 additions & 2 deletions examples/1_example_dk_iter_fixed_order.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,11 +103,11 @@ def example_dk_iter_fixed_order():

fig, ax = plt.subplots()
for i, ds in enumerate(d_scale_fit_info):
ds.plot_mu(ax=ax, plot_kw=dict(label=f"iter{i}"))
dkpy.plot_mu(ds, ax=ax, plot_kw=dict(label=f"iter{i}"))

ax = None
for i, ds in enumerate(d_scale_fit_info):
_, ax = ds.plot_D(ax=ax, plot_kw=dict(label=f"iter{i}"))
_, ax = dkpy.plot_D(ds, ax=ax, plot_kw=dict(label=f"iter{i}"))

plt.show()

Expand Down
4 changes: 2 additions & 2 deletions examples/2_example_dk_iter_list_order.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,11 +107,11 @@ def example_dk_iter_fixed_order():

fig, ax = plt.subplots()
for i, ds in enumerate(d_scale_fit_info):
ds.plot_mu(ax=ax, plot_kw=dict(label=f"iter{i}"))
dkpy.plot_mu(ds, ax=ax, plot_kw=dict(label=f"iter{i}"))

ax = None
for i, ds in enumerate(d_scale_fit_info):
_, ax = ds.plot_D(ax=ax, plot_kw=dict(label=f"iter{i}"))
_, ax = dkpy.plot_D(ds, ax=ax, plot_kw=dict(label=f"iter{i}"))

plt.show()

Expand Down
8 changes: 4 additions & 4 deletions examples/3_example_dk_iter_order_callback.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,9 @@ def callback(
)
)
fig, ax = plt.subplots()
d_info[0].plot_mu(ax=ax, plot_kw=dict(label="true"), hide="mu_fit_omega")
dkpy.plot_mu(d_info[0], ax=ax, plot_kw=dict(label="true"), hide="mu_fit_omega")
for i, ds in enumerate(d_info):
ds.plot_mu(ax=ax, plot_kw=dict(label=f"order={i}"), hide="mu_omega")
dkpy.plot_mu(ds, ax=ax, plot_kw=dict(label=f"order={i}"), hide="mu_omega")
plt.show()
selected_order = int(input("Selected order: "))
done = input("Done? (y/N): ") == "y"
Expand Down Expand Up @@ -141,11 +141,11 @@ def callback(

fig, ax = plt.subplots()
for i, ds in enumerate(d_scale_fit_info):
ds.plot_mu(ax=ax, plot_kw=dict(label=f"iter{i}"))
dkpy.plot_mu(ds, ax=ax, plot_kw=dict(label=f"iter{i}"))

ax = None
for i, ds in enumerate(d_scale_fit_info):
_, ax = ds.plot_D(ax=ax, plot_kw=dict(label=f"iter{i}"))
_, ax = dkpy.plot_D(ds, ax=ax, plot_kw=dict(label=f"iter{i}"))

plt.show()

Expand Down
1 change: 1 addition & 0 deletions src/dkpy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@
from .controller_synthesis import *
from .dk_iteration import *
from .fit_transfer_functions import *
from .plotting import *
from .structured_singular_value import *
from .utilities import *
134 changes: 0 additions & 134 deletions src/dkpy/dk_iteration.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
import control
import numpy as np
import scipy.linalg
from matplotlib import pyplot as plt

from . import (
controller_synthesis,
Expand Down Expand Up @@ -66,139 +65,6 @@ def __init__(
self.D_fit = D_fit
self.block_structure = block_structure

def plot_mu(
self,
ax: Optional[plt.Axes] = None,
plot_kw: Optional[Dict[str, Any]] = None,
hide: Optional[str] = None,
) -> Tuple[plt.Figure, plt.Axes]:
"""Plot mu.
Parameters
----------
ax : Optional[plt.Axes]
Matplotlib axes to use.
plot_kw : Optional[Dict[str, Any]]
Keyword arguments for :func:`plt.Axes.semilogx`.
hide : Optional[str]
Set to ``'mu_omega'`` or ``'mu_fit_omega'`` to hide either one of
those lines.
Returns
-------
Tuple[plt.Figure, plt.Axes]
Matplotlib :class:`plt.Figure` and :class:`plt.Axes` objects.
"""
# Create figure if not provided
if ax is None:
fig, ax = plt.subplots()
else:
fig = ax.get_figure()
# Set label
label = plot_kw.pop("label", "mu")
label_mu_omega = label + ""
label_mu_fit_omega = label + "_fit"
# Clear line styles
_ = plot_kw.pop("ls", None)
_ = plot_kw.pop("linestyle", None)
# Plot mu
if hide != "mu_omega":
ax.semilogx(
self.omega,
self.mu_omega,
label=label_mu_omega,
ls="--",
**plot_kw,
)
if hide != "mu_fit_omega":
ax.semilogx(
self.omega,
self.mu_fit_omega,
label=label_mu_fit_omega,
**plot_kw,
)
# Set axis labels
ax.set_xlabel(r"$\omega$ (rad/s)")
ax.set_ylabel(r"$\mu(\omega)$")
ax.grid(linestyle="--")
ax.legend(loc="lower left")
# Return figure and axes
return fig, ax

def plot_D(
self,
ax: Optional[np.ndarray] = None,
plot_kw: Optional[Dict[str, Any]] = None,
hide: Optional[str] = None,
) -> Tuple[plt.Figure, np.ndarray]:
"""Plot D.
Parameters
----------
ax : Optional[np.ndarray]
Array of Matplotlib axes to use.
plot_kw : Optional[Dict[str, Any]]
Keyword arguments for :func:`plt.Axes.semilogx`.
hide : Optional[str]
Set to ``'D_omega'`` or ``'D_fit_omega'`` to hide either one of
those lines.
Returns
-------
Tuple[plt.Figure, np.ndarray]
Matplotlib :class:`plt.Figure` object and two-dimensional array of
:class:`plt.Axes` objects.
"""
mask = fit_transfer_functions._mask_from_block_structure(self.block_structure)
# Create figure if not provided
if ax is None:
fig, ax = plt.subplots(
mask.shape[0],
mask.shape[1],
constrained_layout=True,
)
else:
fig = ax[0, 0].get_figure()
# Set label
label = plot_kw.pop("label", "D")
label_D_omega = label + ""
label_D_fit_omega = label + "_fit"
# Clear line styles
_ = plot_kw.pop("ls", None)
_ = plot_kw.pop("linestyle", None)
# Plot D
mag_D_omega = np.abs(self.D_omega)
mag_D_fit_omega = np.abs(self.D_fit_omega)
for i in range(ax.shape[0]):
for j in range(ax.shape[1]):
if mask[i, j] != 0:
dB_omega = 20 * np.log10(mag_D_omega[i, j, :])
dB_fit_omega = 20 * np.log10(mag_D_fit_omega[i, j, :])
if hide != "D_omega":
ax[i, j].semilogx(
self.omega,
dB_omega,
label=label_D_omega,
ls="--",
**plot_kw,
)
if hide != "D_fit_omega":
ax[i, j].semilogx(
self.omega,
dB_fit_omega,
label=label_D_fit_omega,
**plot_kw,
)
# Set axis labels
ax[i, j].set_xlabel(r"$\omega$ (rad/s)")
ax[i, j].set_ylabel(rf"$D_{i}{j}(\omega) (dB)$")
ax[i, j].grid(linestyle="--")
else:
ax[i, j].axis("off")
fig.legend(handles=ax[0, 0].get_lines(), loc="lower left")
# Return figure and axes
return fig, ax

@classmethod
def create_from_fit(
cls,
Expand Down
153 changes: 153 additions & 0 deletions src/dkpy/plotting.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
"""Plotting utilities."""

__all__ = [
"plot_D",
"plot_mu",
]

from typing import Any, Dict, Tuple, Optional
import numpy as np
from matplotlib import pyplot as plt

from . import dk_iteration, fit_transfer_functions


def plot_mu(
d_scale_info: dk_iteration.DScaleFitInfo,
ax: Optional[plt.Axes] = None,
plot_kw: Optional[Dict[str, Any]] = None,
hide: Optional[str] = None,
) -> Tuple[plt.Figure, plt.Axes]:
"""Plot mu.
Parameters
----------
d_scale_fit_info : dkpy.DScaleFitInfo
Object containing information about the D-scale fit.
ax : Optional[plt.Axes]
Matplotlib axes to use.
plot_kw : Optional[Dict[str, Any]]
Keyword arguments for :func:`plt.Axes.semilogx`.
hide : Optional[str]
Set to ``'mu_omega'`` or ``'mu_fit_omega'`` to hide either one of
those lines.
Returns
-------
Tuple[plt.Figure, plt.Axes]
Matplotlib :class:`plt.Figure` and :class:`plt.Axes` objects.
"""
# Create figure if not provided
if ax is None:
fig, ax = plt.subplots()
else:
fig = ax.get_figure()
# Set label
label = plot_kw.pop("label", "mu")
label_mu_omega = label + ""
label_mu_fit_omega = label + "_fit"
# Clear line styles
_ = plot_kw.pop("ls", None)
_ = plot_kw.pop("linestyle", None)
# Plot mu
if hide != "mu_omega":
ax.semilogx(
d_scale_info.omega,
d_scale_info.mu_omega,
label=label_mu_omega,
ls="--",
**plot_kw,
)
if hide != "mu_fit_omega":
ax.semilogx(
d_scale_info.omega,
d_scale_info.mu_fit_omega,
label=label_mu_fit_omega,
**plot_kw,
)
# Set axis labels
ax.set_xlabel(r"$\omega$ (rad/s)")
ax.set_ylabel(r"$\mu(\omega)$")
ax.grid(linestyle="--")
ax.legend(loc="lower left")
# Return figure and axes
return fig, ax


def plot_D(
d_scale_info: dk_iteration.DScaleFitInfo,
ax: Optional[np.ndarray] = None,
plot_kw: Optional[Dict[str, Any]] = None,
hide: Optional[str] = None,
) -> Tuple[plt.Figure, np.ndarray]:
"""Plot D.
Parameters
----------
d_scale_fit_info : dkpy.DScaleFitInfo
Object containing information about the D-scale fit.
ax : Optional[np.ndarray]
Array of Matplotlib axes to use.
plot_kw : Optional[Dict[str, Any]]
Keyword arguments for :func:`plt.Axes.semilogx`.
hide : Optional[str]
Set to ``'D_omega'`` or ``'D_fit_omega'`` to hide either one of
those lines.
Returns
-------
Tuple[plt.Figure, np.ndarray]
Matplotlib :class:`plt.Figure` object and two-dimensional array of
:class:`plt.Axes` objects.
"""
mask = fit_transfer_functions._mask_from_block_structure(
d_scale_info.block_structure
)
# Create figure if not provided
if ax is None:
fig, ax = plt.subplots(
mask.shape[0],
mask.shape[1],
constrained_layout=True,
)
else:
fig = ax[0, 0].get_figure()
# Set label
label = plot_kw.pop("label", "D")
label_D_omega = label + ""
label_D_fit_omega = label + "_fit"
# Clear line styles
_ = plot_kw.pop("ls", None)
_ = plot_kw.pop("linestyle", None)
# Plot D
mag_D_omega = np.abs(d_scale_info.D_omega)
mag_D_fit_omega = np.abs(d_scale_info.D_fit_omega)
for i in range(ax.shape[0]):
for j in range(ax.shape[1]):
if mask[i, j] != 0:
dB_omega = 20 * np.log10(mag_D_omega[i, j, :])
dB_fit_omega = 20 * np.log10(mag_D_fit_omega[i, j, :])
if hide != "D_omega":
ax[i, j].semilogx(
d_scale_info.omega,
dB_omega,
label=label_D_omega,
ls="--",
**plot_kw,
)
if hide != "D_fit_omega":
ax[i, j].semilogx(
d_scale_info.omega,
dB_fit_omega,
label=label_D_fit_omega,
**plot_kw,
)
# Set axis labels
ax[i, j].set_xlabel(r"$\omega$ (rad/s)")
ax[i, j].set_ylabel(rf"$D_{{{i}{j}}}(\omega) (dB)$")
ax[i, j].grid(linestyle="--")
else:
ax[i, j].axis("off")
fig.legend(handles=ax[0, 0].get_lines(), loc="lower left")
# Return figure and axes
return fig, ax

0 comments on commit b7c8a35

Please sign in to comment.