Source code for avl_aero_tables.st_fileread

"""Parse AVL stability derivative output files (.st)."""

from __future__ import annotations

import re
from dataclasses import dataclass, field
from pathlib import Path


[docs] @dataclass class StResult: filename: str controls: dict[str, str] = field(default_factory=dict) # "d01" -> "flap" data: dict[str, float] = field(default_factory=dict) # "CLa" -> 5.631
def _sanitize(name: str) -> str: return name.replace("/", "_div_").replace("'", "_prime_") def _parse_st_file(path: Path) -> StResult: result = StResult(filename=path.name) lines = path.read_text().splitlines() tokens = " ".join(lines[1:]).split() # skip line 0 (the dashed separator) ctrl_re = re.compile(r"^d\d") for idx, tok in enumerate(tokens): if ctrl_re.match(tok) and idx > 0: result.controls[tok] = tokens[idx - 1] if tok == "=" and idx > 0 and idx + 1 < len(tokens): # "Clb Cnr / Clr Cnb = <value>" — 5-token compound name if ( idx >= 5 and tokens[idx - 5] == "Clb" and tokens[idx - 4] == "Cnr" and tokens[idx - 3] == "/" and tokens[idx - 2] == "Clr" ): var = "Clb_Cnr_div_Clr_Cnb" else: var = _sanitize(tokens[idx - 1]) try: result.data[var] = float(tokens[idx + 1]) except ValueError: pass return result
[docs] def st_fileread(path: str | Path) -> list[StResult]: """Parse .st files and return a list of StResult (one per file). Accepts either a directory (reads all ``*.st`` files) or a single ``.st`` file. Example ------- >>> from avl_aero_tables.st_fileread import st_fileread >>> results = st_fileread("tests/data/bd_alpha5_beta0.st") >>> len(results) 1 >>> results[0].filename 'bd_alpha5_beta0.st' >>> results[0].data["Alpha"] 5.0 >>> results[0].data["CLtot"] 0.58447 >>> results[0].controls {'d01': 'flap', 'd02': 'aileron', 'd03': 'elevator', 'd04': 'rudder'} """ path = Path(path) if path.is_dir(): files = sorted(path.glob("*.st")) else: files = [path] return [_parse_st_file(f) for f in files]