Source code for at_py.readwrite.rc

"""Reflection coefficient ``.trc`` / ``.brc`` readers (port of Matlab ``readrc.m`` core I/O)."""

from __future__ import annotations

from dataclasses import dataclass

import numpy as np


[docs] @dataclass(frozen=True) class ReflectionCoeffRead: """Angles in radians (``phi`` converted from degrees as in Matlab).""" n_points: int theta: np.ndarray r: np.ndarray phi_rad: np.ndarray
[docs] def read_rc_bytes(data: bytes) -> ReflectionCoeffRead: """Parse one **top** (``.trc``) or **bottom** (``.brc``) reflection coefficient file. Format: integer ``N``, then ``N`` lines of ``theta``, ``R``, ``phi`` with ``phi`` in **degrees** (converted to radians like Matlab ``readrc``). """ text = data.decode("utf-8", errors="replace") lines = [ln.strip() for ln in text.splitlines() if ln.strip()] if not lines: raise ValueError("empty RC file") n = int(lines[0].split()[0]) if len(lines) < 1 + n: raise ValueError(f"RC file: expected {n} data rows after count, got {len(lines) - 1}") theta = np.empty(n, dtype=np.float64) r = np.empty(n, dtype=np.float64) phi_deg = np.empty(n, dtype=np.float64) for i in range(n): parts = lines[1 + i].replace(",", " ").split() if len(parts) < 3: raise ValueError(f"RC row {i + 1}: expected 3 floats, got {parts!r}") theta[i] = float(parts[0]) r[i] = float(parts[1]) phi_deg[i] = float(parts[2]) phi_rad = (np.pi / 180.0) * phi_deg if n > 1: if np.any(np.diff(theta) < -1e-12): raise ValueError("RC file: theta must be non-decreasing (Matlab validateattributes)") return ReflectionCoeffRead(n_points=n, theta=theta, r=r, phi_rad=phi_rad)
[docs] def read_rc_trc_bytes(data: bytes) -> ReflectionCoeffRead: """Alias for a **top** ``.trc`` file (same parser as :func:`read_rc_bytes`).""" return read_rc_bytes(data)
[docs] def read_rc_brc_bytes(data: bytes) -> ReflectionCoeffRead: """Alias for a **bottom** ``.brc`` file (same parser as :func:`read_rc_bytes`).""" return read_rc_bytes(data)