Spaces:
Sleeping
Sleeping
| from __future__ import annotations | |
| from typing import Dict, Optional, Tuple | |
| import matplotlib | |
| matplotlib.use("Agg") | |
| import matplotlib.pyplot as plt | |
| import numpy as np | |
| from .cubic_curves import ( | |
| EPS33_ROW, | |
| LATERAL_ROW, | |
| MODE_TO_ROW, | |
| default_x_for_mode, | |
| evaluate_cubic_no_intercept, | |
| fit_cubic_no_intercept, | |
| ) | |
| def _set_axis_limits( | |
| ax: plt.Axes, | |
| y: np.ndarray, | |
| *, | |
| force_min: Optional[float] = None, | |
| force_max: Optional[float] = None, | |
| min_floor: Optional[float] = None, | |
| max_ceiling: Optional[float] = None, | |
| pad_frac: float = 0.2, | |
| ) -> None: | |
| y = np.asarray(y, dtype=np.float32).reshape(-1) | |
| if y.size == 0: | |
| return | |
| y_min = float(np.min(y)) | |
| y_max = float(np.max(y)) | |
| if force_min is not None: | |
| y_min = min(y_min, float(force_min)) | |
| if force_max is not None: | |
| y_max = max(y_max, float(force_max)) | |
| if min_floor is not None: | |
| y_min = min(y_min, float(min_floor)) | |
| if max_ceiling is not None: | |
| y_max = max(y_max, float(max_ceiling)) | |
| span = y_max - y_min | |
| pad = span * pad_frac if span > 0 else max(abs(y_max), abs(y_min), 1.0) * 0.1 | |
| bottom = y_min - pad | |
| top = y_max + pad | |
| if force_min is not None: | |
| bottom = float(force_min) | |
| if force_max is not None: | |
| top = float(force_max) | |
| ax.set_ylim(bottom, top) | |
| def plot_single_curve(coeffs: np.ndarray, mode: str, title: str, ylabel: str) -> plt.Figure: | |
| x = default_x_for_mode(mode) | |
| y = evaluate_cubic_no_intercept(coeffs, x) | |
| fig, ax = plt.subplots(figsize=(3.2, 2.5)) | |
| ax.plot(x, y, color="k", linewidth=2) | |
| ax.set_title(title) | |
| ax.set_xlabel("strain") | |
| ax.set_ylabel(ylabel) | |
| ax.grid(True, alpha=0.25) | |
| fig.tight_layout() | |
| return fig | |
| def plot_required_curves(cond_coeffs_7x3: np.ndarray) -> plt.Figure: | |
| cond = np.asarray(cond_coeffs_7x3, dtype=np.float32).reshape(7, 3) | |
| fig, axes = plt.subplots(3, 3, figsize=(14, 12)) | |
| modes = ["11", "22", "12"] | |
| for col, mode in enumerate(modes): | |
| x = default_x_for_mode(mode) | |
| stress_row = MODE_TO_ROW[mode] | |
| axes[0, col].plot(x, evaluate_cubic_no_intercept(cond[stress_row], x), color="k", linewidth=2) | |
| axes[0, col].set_title(f"Mode {mode} stress") | |
| axes[0, col].set_xlabel("strain") | |
| axes[0, col].set_ylabel("stress (MPa)") | |
| axes[0, col].grid(True, alpha=0.25) | |
| if mode in ("11", "22"): | |
| lat_row = int(LATERAL_ROW[mode]) | |
| e33_row = int(EPS33_ROW[mode]) | |
| axes[1, col].plot(x, evaluate_cubic_no_intercept(cond[lat_row], x), color="k", linewidth=2) | |
| axes[1, col].set_title(f"Mode {mode} lateral") | |
| axes[1, col].set_xlabel("strain") | |
| axes[1, col].set_ylabel("lateral strain") | |
| axes[1, col].grid(True, alpha=0.25) | |
| axes[2, col].plot(x, evaluate_cubic_no_intercept(cond[e33_row], x), color="k", linewidth=2) | |
| axes[2, col].set_title(f"Mode {mode} eps33") | |
| axes[2, col].set_xlabel("strain") | |
| axes[2, col].set_ylabel("eps33") | |
| axes[2, col].grid(True, alpha=0.25) | |
| else: | |
| axes[1, col].axis("off") | |
| axes[2, col].axis("off") | |
| fig.tight_layout() | |
| return fig | |
| def plot_required_curves_from_series(curves: Dict[str, np.ndarray]) -> plt.Figure: | |
| fig, axes = plt.subplots(3, 3, figsize=(14, 12)) | |
| axes[0, 0].plot(curves["eps11"], curves["sig11_mpa"], color="k", linewidth=2) | |
| axes[0, 0].set_title("Mode 11 stress") | |
| axes[0, 0].set_xlabel("strain") | |
| axes[0, 0].set_ylabel("stress (MPa)") | |
| axes[0, 0].grid(True, alpha=0.25) | |
| _set_axis_limits(axes[0, 0], curves["sig11_mpa"]) | |
| axes[1, 0].plot(curves["eps11"], curves["eps22_from_eps11"], color="k", linewidth=2) | |
| axes[1, 0].set_title("Mode 11 lateral") | |
| axes[1, 0].set_xlabel("strain") | |
| axes[1, 0].set_ylabel("lateral strain") | |
| axes[1, 0].grid(True, alpha=0.25) | |
| _set_axis_limits(axes[1, 0], curves["eps22_from_eps11"], min_floor=-0.01, max_ceiling=0.0, pad_frac=0.0) | |
| axes[2, 0].plot(curves["eps11"], curves["eps33_from_eps11"], color="k", linewidth=2) | |
| axes[2, 0].set_title("Mode 11 eps33") | |
| axes[2, 0].set_xlabel("strain") | |
| axes[2, 0].set_ylabel("eps33") | |
| axes[2, 0].grid(True, alpha=0.25) | |
| _set_axis_limits(axes[2, 0], curves["eps33_from_eps11"]) | |
| axes[0, 1].plot(curves["eps22"], curves["sig22_mpa"], color="k", linewidth=2) | |
| axes[0, 1].set_title("Mode 22 stress") | |
| axes[0, 1].set_xlabel("strain") | |
| axes[0, 1].set_ylabel("stress (MPa)") | |
| axes[0, 1].grid(True, alpha=0.25) | |
| _set_axis_limits(axes[0, 1], curves["sig22_mpa"]) | |
| axes[1, 1].plot(curves["eps22"], curves["eps11_from_eps22"], color="k", linewidth=2) | |
| axes[1, 1].set_title("Mode 22 lateral") | |
| axes[1, 1].set_xlabel("strain") | |
| axes[1, 1].set_ylabel("lateral strain") | |
| axes[1, 1].grid(True, alpha=0.25) | |
| _set_axis_limits(axes[1, 1], curves["eps11_from_eps22"], min_floor=-0.01, max_ceiling=0.0, pad_frac=0.0) | |
| axes[2, 1].plot(curves["eps22"], curves["eps33_from_eps22"], color="k", linewidth=2) | |
| axes[2, 1].set_title("Mode 22 eps33") | |
| axes[2, 1].set_xlabel("strain") | |
| axes[2, 1].set_ylabel("eps33") | |
| axes[2, 1].grid(True, alpha=0.25) | |
| _set_axis_limits(axes[2, 1], curves["eps33_from_eps22"]) | |
| axes[0, 2].plot(curves["eps12"], curves["sig12_mpa"], color="k", linewidth=2) | |
| axes[0, 2].set_title("Mode 12 stress") | |
| axes[0, 2].set_xlabel("strain") | |
| axes[0, 2].set_ylabel("stress (MPa)") | |
| axes[0, 2].grid(True, alpha=0.25) | |
| _set_axis_limits(axes[0, 2], curves["sig12_mpa"]) | |
| axes[1, 2].axis("off") | |
| axes[2, 2].axis("off") | |
| fig.tight_layout() | |
| return fig | |
| def plot_condition_and_simulations_v5( | |
| cond_coeffs_7x3: np.ndarray, | |
| simulations_by_design: Dict[int, Dict[str, Dict[str, np.ndarray]]], | |
| ) -> plt.Figure: | |
| cond = np.asarray(cond_coeffs_7x3, dtype=np.float32).reshape(7, 3) | |
| fig, axes = plt.subplots(3, 3, figsize=(14, 12)) | |
| modes = ["11", "22", "12"] | |
| colors = ["b", "c", "m", "g", "r"] | |
| for col, mode in enumerate(modes): | |
| x_cond = default_x_for_mode(mode) | |
| stress_ys = [evaluate_cubic_no_intercept(cond[MODE_TO_ROW[mode]], x_cond)] | |
| lateral_ys = [] | |
| eps33_ys = [] | |
| x_min, x_max = None, None | |
| for _, sim in sorted(simulations_by_design.items()): | |
| if mode in sim: | |
| x = sim[mode]["strain"] | |
| x_min = float(np.min(x)) | |
| x_max = float(np.max(x)) | |
| break | |
| stress_row = MODE_TO_ROW[mode] | |
| axes[0, col].plot( | |
| x_cond, | |
| evaluate_cubic_no_intercept(cond[stress_row], x_cond), | |
| color="k", | |
| linewidth=2, | |
| label="Condition", | |
| ) | |
| if mode in ("11", "22"): | |
| lat_row = int(LATERAL_ROW[mode]) | |
| e33_row = int(EPS33_ROW[mode]) | |
| lateral_ys.append(evaluate_cubic_no_intercept(cond[lat_row], x_cond)) | |
| eps33_ys.append(evaluate_cubic_no_intercept(cond[e33_row], x_cond)) | |
| axes[1, col].plot( | |
| x_cond, | |
| lateral_ys[-1], | |
| color="k", | |
| linewidth=2, | |
| label="Condition", | |
| ) | |
| axes[2, col].plot( | |
| x_cond, | |
| eps33_ys[-1], | |
| color="k", | |
| linewidth=2, | |
| label="Condition", | |
| ) | |
| else: | |
| axes[1, col].axis("off") | |
| axes[2, col].axis("off") | |
| for idx, (design_idx, sim) in enumerate(sorted(simulations_by_design.items(), key=lambda kv: kv[0])): | |
| if mode not in sim: | |
| continue | |
| color = colors[idx % len(colors)] | |
| data = sim[mode] | |
| strain = np.asarray(data["strain"], dtype=np.float32) | |
| stress = np.asarray(data["stress"], dtype=np.float32) | |
| stress_ys.append(stress) | |
| axes[0, col].plot([], [], color=color, linewidth=2, label=f"Gen {design_idx}") | |
| axes[0, col].scatter(strain, stress, color=color, s=22, alpha=0.85, label="_nolegend_") | |
| stress_coeffs = fit_cubic_no_intercept(strain, stress, degree=3) | |
| if stress_coeffs is not None: | |
| x_sim = np.linspace(float(np.min(strain)), float(np.max(strain)), 200, dtype=np.float32) | |
| axes[0, col].plot(x_sim, evaluate_cubic_no_intercept(stress_coeffs, x_sim), color=color, linewidth=2, alpha=0.9, label="_nolegend_") | |
| if mode in ("11", "22") and data.get("lateral") is not None: | |
| lateral = np.asarray(data["lateral"], dtype=np.float32) | |
| lateral_ys.append(lateral) | |
| axes[1, col].plot([], [], color=color, linewidth=2, label=f"Gen {design_idx}") | |
| axes[1, col].scatter(strain, lateral, color=color, s=22, alpha=0.85, label="_nolegend_") | |
| lat_coeffs = fit_cubic_no_intercept(strain, lateral, degree=3) | |
| if lat_coeffs is not None: | |
| axes[1, col].plot(x_sim, evaluate_cubic_no_intercept(lat_coeffs, x_sim), color=color, linewidth=2, alpha=0.9, label="_nolegend_") | |
| if mode in ("11", "22") and data.get("eps33") is not None: | |
| eps33 = np.asarray(data["eps33"], dtype=np.float32) | |
| eps33_ys.append(eps33) | |
| axes[2, col].plot([], [], color=color, linewidth=2, label=f"Gen {design_idx}") | |
| axes[2, col].scatter(strain, eps33, color=color, s=22, alpha=0.85, label="_nolegend_") | |
| e33_coeffs = fit_cubic_no_intercept(strain, eps33, degree=3) | |
| if e33_coeffs is not None: | |
| axes[2, col].plot(x_sim, evaluate_cubic_no_intercept(e33_coeffs, x_sim), color=color, linewidth=2, alpha=0.9, label="_nolegend_") | |
| if x_min is None or x_max is None or x_max <= x_min: | |
| x_min = float(np.min(x_cond)) | |
| x_max = float(np.max(x_cond)) | |
| else: | |
| x_min = min(float(np.min(x_cond)), x_min) | |
| x_max = max(float(np.max(x_cond)), x_max) | |
| axes[0, col].set_xlim(x_min, x_max) | |
| if mode in ("11", "22"): | |
| axes[1, col].set_xlim(x_min, x_max) | |
| axes[2, col].set_xlim(x_min, x_max) | |
| axes[0, col].set_title(f"Mode {mode} stress") | |
| axes[0, col].set_xlabel("strain") | |
| axes[0, col].set_ylabel("stress (MPa)") | |
| axes[0, col].grid(True, alpha=0.25) | |
| axes[0, col].legend(fontsize=8) | |
| _set_axis_limits(axes[0, col], np.concatenate(stress_ys)) | |
| if mode in ("11", "22"): | |
| axes[1, col].set_title(f"Mode {mode} lateral") | |
| axes[1, col].set_xlabel("strain") | |
| axes[1, col].set_ylabel("lateral strain") | |
| axes[1, col].grid(True, alpha=0.25) | |
| axes[1, col].legend(fontsize=8) | |
| _set_axis_limits(axes[1, col], np.concatenate(lateral_ys), min_floor=-0.01, max_ceiling=0.0, pad_frac=0.0) | |
| axes[2, col].set_title(f"Mode {mode} eps33") | |
| axes[2, col].set_xlabel("strain") | |
| axes[2, col].set_ylabel("eps33") | |
| axes[2, col].grid(True, alpha=0.25) | |
| axes[2, col].legend(fontsize=8) | |
| _set_axis_limits(axes[2, col], np.concatenate(eps33_ys)) | |
| fig.tight_layout() | |
| return fig | |