"""Gamma 曲线绘制。 Step 2 重构:从 pqAutomationApp.PQAutomationApp.plot_gamma 原样搬迁。 """ import numpy as np from app.views.modern_styles import get_theme_palette from typing import TYPE_CHECKING if TYPE_CHECKING: from pqAutomationApp import PQAutomationApp def _is_dark_palette(palette: dict[str, str]) -> bool: """根据主题背景色亮度判断是否深色主题。""" bg = palette.get("bg", "#FFFFFF").lstrip("#") try: r = int(bg[0:2], 16) g = int(bg[2:4], 16) b = int(bg[4:6], 16) except Exception: return False return (r * 299 + g * 587 + b * 114) / 1000 < 128 def plot_gamma(self: "PQAutomationApp", L_bar, results_with_gamma_list, target_gamma, test_type): """绘制Gamma曲线 + 数据表格(包含实测亮度)""" palette = get_theme_palette() dark_mode = _is_dark_palette(palette) line_actual = "#3FA7FF" if dark_mode else "#0A4BFF" line_ideal = "#FF6B6B" if dark_mode else "#D62828" grid_color = "#566070" if dark_mode else "#B8BDC3" legend_bg = "#131821" if dark_mode else "#FFFFFF" legend_edge = "#A4B2C6" if dark_mode else palette["border"] table_edge = "#738196" if dark_mode else palette["border"] table_body_fg = "#EEF3FA" if dark_mode else palette["fg"] # ========== 1. 清空并重置左侧曲线 ========== self.gamma_ax.clear() self.gamma_fig.patch.set_facecolor(palette["bg"]) self.gamma_ax.set_facecolor(palette["card_bg"]) self.gamma_ax.set_xlim(0, 105) self.gamma_ax.set_ylim(0, 1.1) self.gamma_ax.set_xlabel("灰阶 (%)", fontsize=10, color=palette["fg"]) self.gamma_ax.set_ylabel("L_bar", fontsize=10, color=palette["fg"]) self.gamma_ax.grid(True, linestyle="--", alpha=0.45 if dark_mode else 0.3, color=grid_color) self.gamma_ax.tick_params(labelsize=9) self.gamma_ax.tick_params(colors=palette["fg"]) for spine in self.gamma_ax.spines.values(): spine.set_color(palette["border"]) # 生成横坐标(灰阶百分比) x_values = np.linspace(0, 100, len(L_bar)) # 反转 L_bar(确保从左到右是 0% → 100%) if len(L_bar) > 1 and L_bar[0] > L_bar[-1]: L_bar = L_bar[::-1] results_with_gamma_list = results_with_gamma_list[::-1] # 计算平均Gamma gamma_values = [] for item in results_with_gamma_list: if isinstance(item, (list, tuple)) and len(item) >= 4: gamma = item[3] if 0.5 < gamma < 5.0: gamma_values.append(gamma) avg_gamma = np.mean(gamma_values) if gamma_values else target_gamma # 绘制实测曲线 self.gamma_ax.plot( x_values, L_bar, color=line_actual, marker="o", label=f"实测 (平均γ={avg_gamma:.2f})", linewidth=2, markersize=4, zorder=5, ) # 绘制理想曲线(使用 target_gamma) ideal_L_bar = [(x / 100) ** target_gamma for x in x_values] self.gamma_ax.plot( x_values, ideal_L_bar, color=line_ideal, linestyle="--", label=f"理想 (γ={target_gamma})", linewidth=2, alpha=0.9 if dark_mode else 0.7, zorder=3, ) # 图例 legend = self.gamma_ax.legend( fontsize=9, loc="upper left", framealpha=0.9 if dark_mode else 0.95, facecolor=legend_bg, edgecolor=legend_edge, ) for text in legend.get_texts(): text.set_color(palette["fg"]) # ========== 2. 清空并绘制右侧表格 ========== self.gamma_table_ax.clear() self.gamma_table_ax.axis("off") # 构建表格数据(4列) table_data = [["灰阶", "实测亮度\n(cd/m²)", "L_bar", "Gamma"]] for i, (x_val, L_val, result) in enumerate( zip(x_values, L_bar, results_with_gamma_list) ): # 提取实测亮度 if isinstance(result, (list, tuple)) and len(result) >= 3: measured_lv = result[2] measured_lv_str = f"{measured_lv:.2f}" else: measured_lv_str = "--" # 提取 Gamma if isinstance(result, (list, tuple)) and len(result) >= 4: gamma = result[3] if gamma < 0.5 or gamma > 5.0: gamma_str = "--" else: gamma_str = f"{gamma:.2f}" else: gamma_str = "--" table_data.append( [ f"{x_val:.0f}%", measured_lv_str, f"{L_val:.3f}", gamma_str, ] ) # 绘制表格(4列) table = self.gamma_table_ax.table( cellText=table_data, cellLoc="center", loc="center", colWidths=[0.18, 0.28, 0.27, 0.27], ) # 美化表格 table.auto_set_font_size(False) table.set_fontsize(7.5) table.scale(1, 1.5) # 表头样式 for i in range(4): cell = table[(0, i)] cell.set_facecolor(palette["primary"]) cell.set_text_props(weight="bold", color=palette["select_fg"]) cell.set_edgecolor(table_edge) cell.set_linewidth(0.8) # 数据行交替颜色 for i in range(1, len(table_data)): for j in range(4): cell = table[(i, j)] if i % 2 == 0: cell.set_facecolor(palette["surface_alt_bg"]) else: cell.set_facecolor(palette["card_bg"]) cell.set_text_props(color=table_body_fg) cell.set_edgecolor(table_edge) cell.set_linewidth(0.6) # ========== 3. 总标题 ========== test_type_name = self.get_test_type_name(test_type) self.gamma_fig.suptitle( f"{test_type_name} - Gamma曲线", fontsize=12, y=0.98, fontweight="bold", color=palette["fg"], ) # ========== 4. 绘制到画布 ========== self.gamma_canvas.draw() self.chart_notebook.select(self.gamma_chart_frame) self.log_gui.log("Gamma曲线 + 数据表格绘制完成", level="success") class PlotGammaMixin: """由 tools/refactor_to_mixins.py 自动生成。 把本模块的自由函数挂到 PQAutomationApp 上,便于 F12 跳转与类型推断。 """ plot_gamma = plot_gamma