Source code for avl_aero_tables.aero_fileplot

"""Plot AeroDatabase tables as 3-D surface plots (port of aero_fileplot.m)."""

from __future__ import annotations

from typing import TYPE_CHECKING

import numpy as np

from avl_aero_tables.aero_filewrite import COEF_NAMES, AeroDatabase

if TYPE_CHECKING:
    from matplotlib.figure import Figure


[docs] def aero_fileplot( aero: AeroDatabase, beta_ref: float = 0.0, ) -> "list[Figure]": """Plot stability and control coefficient tables from an AeroDatabase. Produces two sets of figures: 1. **Stability figure** — 2×3 grid of 3-D surface plots showing each of the six total-force coefficients vs. alpha and beta. 2. **Control figures** — one figure per coefficient, each containing one subplot per control surface, showing the coefficient vs. alpha and deflection at *beta_ref*. Parameters ---------- aero: AeroDatabase built by aero_filewrite(). beta_ref: Sideslip angle (deg) at which control-surface subplots are sliced. The nearest available beta breakpoint is used. Returns ------- list[plt.Figure] Stability figure first, then one control figure per coefficient. Returns an empty list for any set that cannot be plotted (e.g. no control surfaces). Example ------- >>> from avl_aero_tables import avl_sweep >>> from avl_aero_tables.aero_filewrite import aero_filewrite >>> from avl_aero_tables.aero_fileplot import aero_fileplot >>> results = avl_sweep( # doctest: +ELLIPSIS ... "examples/bd.avl", ... alpha=[-5, 0, 5, 10], ... beta=[-5, 0, 5], ... ctrl_sweeps={"elevator": [-10, 0, 10]}, ... ) AVL sweep complete → ... (36 cases) >>> db = aero_filewrite(results) >>> figs = aero_fileplot(db) >>> len(figs) # stability + one figure per coefficient 7 >>> figs[0].get_suptitle() 'Stability coefficients' >>> figs[1].get_suptitle() 'CLtot — beta = 0.0 deg' """ import matplotlib.pyplot as plt figs: list[Figure] = [] # ------------------------------------------------------------------ # 1. Stability figure (alpha × beta for each coefficient) # ------------------------------------------------------------------ stab_coefs = [c for c in COEF_NAMES if c in aero.stab] if stab_coefs: n_cols = 3 n_rows = (len(stab_coefs) + n_cols - 1) // n_cols fig_stab = plt.figure(figsize=(14, 4 * n_rows)) fig_stab.suptitle("Stability coefficients") for i, coef in enumerate(stab_coefs, start=1): stab_tbl = aero.stab[coef] ax = fig_stab.add_subplot(n_rows, n_cols, i, projection="3d") alpha_g, beta_g = np.meshgrid(stab_tbl.alpha, stab_tbl.beta, indexing="ij") ax.plot_surface(alpha_g, beta_g, stab_tbl.data, cmap="viridis", alpha=0.85) ax.set_xlabel("Alpha (deg)") ax.set_ylabel("Beta (deg)") ax.set_zlabel(coef) ax.set_title(coef) ax.view_init(elev=30, azim=-37.5) fig_stab.tight_layout() figs.append(fig_stab) # ------------------------------------------------------------------ # 2. Control figures (alpha × deflection at beta_ref) # ------------------------------------------------------------------ ctrl_surfaces = list(dict.fromkeys(t.surface for t in aero.ctrl.values())) if not ctrl_surfaces: return figs # Find the beta index nearest to beta_ref sample_tbl = next(iter(aero.ctrl.values())) beta_arr = sample_tbl.beta bi = int(np.argmin(np.abs(beta_arr - beta_ref))) beta_actual = float(beta_arr[bi]) n_surfs = len(ctrl_surfaces) n_cols = min(n_surfs, 2) n_rows = (n_surfs + n_cols - 1) // n_cols for coef in COEF_NAMES: ctrl_keys = [f"{coef}_{s}" for s in ctrl_surfaces if f"{coef}_{s}" in aero.ctrl] if not ctrl_keys: continue fig_ctrl = plt.figure(figsize=(6 * n_cols, 4 * n_rows)) fig_ctrl.suptitle(f"{coef} — beta = {beta_actual:.1f} deg") for j, key in enumerate(ctrl_keys, start=1): ctrl_tbl = aero.ctrl[key] ax = fig_ctrl.add_subplot(n_rows, n_cols, j, projection="3d") alpha_g, defl_g = np.meshgrid(ctrl_tbl.alpha, ctrl_tbl.defl, indexing="ij") z = ctrl_tbl.data[:, bi, :] ax.plot_surface(alpha_g, defl_g, z, cmap="plasma", alpha=0.85) ax.set_xlabel("Alpha (deg)") ax.set_ylabel(f"{ctrl_tbl.ctrl_name} (deg)") ax.set_zlabel(coef) ax.set_title(ctrl_tbl.surface) ax.view_init(elev=30, azim=-37.5) fig_ctrl.tight_layout() figs.append(fig_ctrl) return figs