| from __future__ import annotations |
|
|
| from typing import Optional |
|
|
| import numpy as np |
|
|
|
|
| MODE_TO_ROW = {"11": 0, "22": 3, "12": 6} |
| LATERAL_ROW = {"11": 1, "22": 4, "12": None} |
| EPS33_ROW = {"11": 2, "22": 5, "12": None} |
|
|
|
|
| def evaluate_cubic_no_intercept(coeffs: np.ndarray, x: np.ndarray) -> np.ndarray: |
| coeffs = np.asarray(coeffs, dtype=np.float32).reshape(-1) |
| x = np.asarray(x, dtype=np.float32) |
| coeffs_with_zero = np.append(coeffs, 0.0) |
| return np.polyval(coeffs_with_zero, x).astype(np.float32) |
|
|
|
|
| def fit_cubic_no_intercept(x: np.ndarray, y: np.ndarray, degree: int = 3) -> Optional[np.ndarray]: |
| x = np.asarray(x, dtype=np.float32).reshape(-1) |
| y = np.asarray(y, dtype=np.float32).reshape(-1) |
| if x.size < 2 or y.size < 2 or x.size != y.size: |
| return None |
| degree = int(max(1, min(int(degree), max(1, x.size - 1)))) |
| A = np.vstack([x**p for p in range(degree, 0, -1)]).T |
| try: |
| coeffs, *_ = np.linalg.lstsq(A, y, rcond=None) |
| return coeffs.astype(np.float32) |
| except Exception: |
| return None |
|
|
|
|
| def default_x_for_mode(mode: str) -> np.ndarray: |
| x_max = 0.1 |
| return np.linspace(0.0, x_max, 250, dtype=np.float32) |
|
|