q3
This commit is contained in:
329
org/chatgpt2/q1_anaylis.py
Normal file
329
org/chatgpt2/q1_anaylis.py
Normal file
@@ -0,0 +1,329 @@
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
from scipy.interpolate import CubicSpline
|
||||
from scipy.stats import pearsonr
|
||||
from sklearn.metrics import mean_squared_error
|
||||
import warnings
|
||||
|
||||
from sklearn.metrics.pairwise import cosine_similarity
|
||||
|
||||
from org.chatgpt2.q1_2 import wl_max, wl_min
|
||||
|
||||
warnings.filterwarnings('ignore')
|
||||
|
||||
|
||||
# -----------------------------
|
||||
# 1. 通用工具函数(保持不变)
|
||||
# -----------------------------
|
||||
def make_strictly_increasing(wl, n, k):
|
||||
unique_wl, indices = np.unique(wl, return_index=True)
|
||||
if len(unique_wl) != len(wl):
|
||||
print(f"Removed {len(wl) - len(unique_wl)} duplicate wavelength points")
|
||||
wl, n, k = wl[indices], n[indices], k[indices]
|
||||
is_increasing = np.diff(wl) > 0
|
||||
if not all(is_increasing):
|
||||
valid_indices = np.concatenate([[True], is_increasing])
|
||||
wl, n, k = wl[valid_indices], n[valid_indices], k[valid_indices]
|
||||
return wl, n, k
|
||||
|
||||
|
||||
def read_split_data(file_path):
|
||||
with open(file_path, 'r', encoding='utf-8') as f:
|
||||
lines = [line.strip() for line in f if line.strip() and not line.startswith('#')]
|
||||
split_idx = None
|
||||
for i, line in enumerate(lines):
|
||||
if line == 'wl k':
|
||||
split_idx = i
|
||||
break
|
||||
n_lines = lines[1:split_idx]
|
||||
wl_n, n_list = [], []
|
||||
for line in n_lines:
|
||||
wl, n_val = line.split()
|
||||
wl_n.append(float(wl)), n_list.append(float(n_val))
|
||||
k_lines = lines[split_idx + 1:]
|
||||
wl_k, k_list = [], []
|
||||
for line in k_lines:
|
||||
wl, k_val = line.split()
|
||||
wl_k.append(float(wl)), k_list.append(float(k_val))
|
||||
wl_n, n_list = np.array(wl_n), np.array(n_list)
|
||||
wl_k, k_list = np.array(wl_k), np.array(k_list)
|
||||
assert np.allclose(wl_n, wl_k), "n和k的波长列表不一致!"
|
||||
sorted_idx = np.argsort(wl_n)
|
||||
return wl_n[sorted_idx], n_list[sorted_idx], k_list[sorted_idx]
|
||||
|
||||
|
||||
def fresnel_reflectance(n1, k1, n2, k2):
|
||||
m1 = n1 + 1j * k1
|
||||
m2 = n2 + 1j * k2
|
||||
return np.abs((m1 - m2) / (m1 + m2)) ** 2
|
||||
|
||||
|
||||
def thin_film_emissivity(n_film, k_film, d, wl, n_air=1.0, k_air=0.0, n_sub=1.5, k_sub=0.0, r=0.0):
|
||||
m_air = n_air + 1j * k_air
|
||||
m_film = n_film + 1j * k_film
|
||||
m_sub = n_sub + 1j * k_sub
|
||||
R12 = np.abs((m_air - m_film) / (m_air + m_film)) ** 2
|
||||
R23 = np.abs((m_film - m_sub) / (m_film + m_sub)) ** 2
|
||||
beta = 2 * np.pi * m_film / wl
|
||||
delta_complex = beta * d
|
||||
alpha = 2 * np.imag(delta_complex)
|
||||
sqrt_term = np.sqrt(R12 * R23 * np.exp(-alpha))
|
||||
cos_term = np.cos(2 * np.real(delta_complex))
|
||||
R_specular = (R12 + R23 * np.exp(-alpha) + 2 * sqrt_term * cos_term) / (
|
||||
1 + R12 * R23 * np.exp(-alpha) + 2 * sqrt_term * cos_term)
|
||||
R_diffuse = 0.05 * r
|
||||
R_total = (1 - r) * R_specular + r * R_diffuse
|
||||
T_total = (1 - R12) * (1 - R23) * np.exp(-alpha) / (1 + R12 * R23 * np.exp(-alpha) + 2 * sqrt_term * cos_term)
|
||||
return np.clip(1 - R_total - T_total, 0, 1)
|
||||
|
||||
|
||||
# -----------------------------
|
||||
# 2. 新增:局部相似度计算函数(滑动窗口法)
|
||||
# -----------------------------
|
||||
def calculate_local_similarity(eps1, eps2, wl_common, window_size=0.5):
|
||||
"""
|
||||
计算逐波长的局部相似度(滑动窗口法)
|
||||
输入:
|
||||
eps1/eps2: 两个发射率数组
|
||||
wl_common: 统一波长数组
|
||||
window_size: 滑动窗口宽度(μm),默认0.5μm(覆盖5个采样点,保证平滑)
|
||||
输出:
|
||||
local_corr: 逐波长皮尔逊相关系数(局部相似度)
|
||||
local_cos_sim: 逐波长余弦相似度
|
||||
local_mae: 逐波长局部平均绝对误差(相似度的互补指标)
|
||||
"""
|
||||
n_points = len(wl_common)
|
||||
local_corr = np.zeros(n_points)
|
||||
local_cos_sim = np.zeros(n_points)
|
||||
local_mae = np.zeros(n_points)
|
||||
|
||||
# 滑动窗口计算局部相似度(窗口中心为每个波长点)
|
||||
for i in range(n_points):
|
||||
# 确定当前窗口的波长范围
|
||||
wl_center = wl_common[i]
|
||||
window_mask = (wl_common >= wl_center - window_size / 2) & (wl_common <= wl_center + window_size / 2)
|
||||
if np.sum(window_mask) < 3: # 窗口内至少3个点才计算(避免统计无意义)
|
||||
local_corr[i] = np.nan
|
||||
local_cos_sim[i] = np.nan
|
||||
local_mae[i] = np.nan
|
||||
continue
|
||||
|
||||
# 提取窗口内的发射率数据
|
||||
eps1_window = eps1[window_mask]
|
||||
eps2_window = eps2[window_mask]
|
||||
|
||||
# 计算窗口内的相似度指标
|
||||
corr, _ = pearsonr(eps1_window, eps2_window)
|
||||
cos_sim = cosine_similarity(eps1_window.reshape(1, -1), eps2_window.reshape(1, -1))[0][0]
|
||||
mae = np.mean(np.abs(eps1_window - eps2_window))
|
||||
|
||||
# 存储结果(相关系数和余弦相似度归一化到0-1范围)
|
||||
local_corr[i] = (corr + 1) / 2 # 原始相关系数-1~1 → 映射为0~1
|
||||
local_cos_sim[i] = cos_sim
|
||||
local_mae[i] = mae
|
||||
|
||||
return local_corr, local_cos_sim, local_mae
|
||||
|
||||
|
||||
# -----------------------------
|
||||
# 3. 核心相似性分析函数(新增局部相似度计算)
|
||||
# -----------------------------
|
||||
def analyze_spectral_similarity(file1, file2, thicknesses=[1.0], n_sub=1.5, k_sub=0.0, r=0.0, window_size=0.5):
|
||||
# Step 1: 数据读取与预处理
|
||||
wl1, n1, k1 = read_split_data(file1)
|
||||
wl2, n2, k2 = read_split_data(file2)
|
||||
wl1, n1, k1 = make_strictly_increasing(wl1, n1, k1)
|
||||
wl2, n2, k2 = make_strictly_increasing(wl2, n2, k2)
|
||||
|
||||
# Step 2: 统一波长范围
|
||||
wl_min = max(wl1.min(), wl2.min())
|
||||
wl_max = min(wl1.max(), wl2.max())
|
||||
if wl_min >= wl_max:
|
||||
raise ValueError("两个文件的波长范围无交集,无法进行相似性分析!")
|
||||
wl_common = np.linspace(wl_min, wl_max, 1000)
|
||||
|
||||
# Step 3: 插值得到统一波长下的n和k
|
||||
cs_n1 = CubicSpline(wl1, n1)
|
||||
cs_k1 = CubicSpline(wl1, k1)
|
||||
cs_n2 = CubicSpline(wl2, n2)
|
||||
cs_k2 = CubicSpline(wl2, k2)
|
||||
n1_common = cs_n1(wl_common)
|
||||
k1_common = cs_k1(wl_common)
|
||||
n2_common = cs_n2(wl_common)
|
||||
k2_common = cs_k2(wl_common)
|
||||
|
||||
# Step 4: 计算发射率和局部相似度
|
||||
emissivity_dict = {}
|
||||
local_similarity_dict = {}
|
||||
for d in thicknesses:
|
||||
eps1 = thin_film_emissivity(n1_common, k1_common, d, wl_common, n_sub=n_sub, k_sub=k_sub, r=r)
|
||||
eps2 = thin_film_emissivity(n2_common, k2_common, d, wl_common, n_sub=n_sub, k_sub=k_sub, r=r)
|
||||
emissivity_dict[d] = (eps1, eps2)
|
||||
|
||||
# 计算局部相似度
|
||||
local_corr, local_cos_sim, local_mae = calculate_local_similarity(eps1, eps2, wl_common, window_size)
|
||||
local_similarity_dict[d] = (local_corr, local_cos_sim, local_mae)
|
||||
|
||||
# Step 5: 全局相似性指标计算
|
||||
similarity_results = {}
|
||||
for d in thicknesses:
|
||||
eps1, eps2 = emissivity_dict[d]
|
||||
pearson_corr, _ = pearsonr(eps1, eps2)
|
||||
cos_sim = cosine_similarity(eps1.reshape(1, -1), eps2.reshape(1, -1))[0][0]
|
||||
mse = mean_squared_error(eps1, eps2)
|
||||
norm_mse = mse / (np.max([np.var(eps1), np.var(eps2)]) + 1e-8)
|
||||
mae = np.mean(np.abs(eps1 - eps2))
|
||||
|
||||
# 大气窗口指标
|
||||
window_corr, window_mae = None, None
|
||||
if wl_min <= 13 and wl_max >= 8:
|
||||
window_mask = (wl_common >= 8) & (wl_common <= 13)
|
||||
eps1_window = eps1[window_mask]
|
||||
eps2_window = eps2[window_mask]
|
||||
window_corr, _ = pearsonr(eps1_window, eps2_window)
|
||||
window_mae = np.mean(np.abs(eps1_window - eps2_window))
|
||||
|
||||
similarity_results[d] = {
|
||||
"pearson_correlation": pearson_corr,
|
||||
"cosine_similarity": cos_sim,
|
||||
"normalized_mse": norm_mse,
|
||||
"mae": mae,
|
||||
"window_pearson_correlation": window_corr,
|
||||
"window_mae": window_mae
|
||||
}
|
||||
|
||||
# Step 6: 可视化(新增相似度曲线)
|
||||
plot_spectral_comparison(wl_common, emissivity_dict, local_similarity_dict, thicknesses, wl_min, wl_max)
|
||||
|
||||
return similarity_results, wl_common, emissivity_dict, local_similarity_dict
|
||||
|
||||
|
||||
# -----------------------------
|
||||
# 4. 可视化函数(新增相似度曲线子图)
|
||||
# -----------------------------
|
||||
def plot_spectral_comparison(wl_common, emissivity_dict, local_similarity_dict, thicknesses, wl_min, wl_max):
|
||||
n_plots = len(thicknesses)
|
||||
fig, axes = plt.subplots(n_plots, 3, figsize=(18, 5 * n_plots)) # 新增1列用于相似度曲线
|
||||
plt.rcParams['font.sans-serif'] = ['Arial']
|
||||
|
||||
for idx, d in enumerate(thicknesses):
|
||||
eps1, eps2 = emissivity_dict[d]
|
||||
local_corr, local_cos_sim, local_mae = local_similarity_dict[d]
|
||||
diff = np.abs(eps1 - eps2)
|
||||
|
||||
# 子图1:发射率光谱对比
|
||||
ax1 = axes[idx, 0] if n_plots > 1 else axes[0]
|
||||
ax1.plot(wl_common, eps1, linewidth=2, label='data.txt', color='darkblue')
|
||||
ax1.plot(wl_common, eps2, linewidth=2, label='data2.txt', color='darkred', linestyle='--')
|
||||
if wl_min <= 13 and wl_max >= 8:
|
||||
ax1.axvspan(8, 13, alpha=0.15, color='orange', label='Atmospheric Window (8-13 μm)')
|
||||
ax1.set_xlabel('Wavelength (μm)', fontsize=12)
|
||||
ax1.set_ylabel('Emissivity ε(λ)', fontsize=12)
|
||||
ax1.set_title(f'Emissivity Spectrum Comparison (Thickness = {d} μm)', fontsize=14, fontweight='bold')
|
||||
ax1.grid(True, alpha=0.3)
|
||||
ax1.legend(fontsize=10)
|
||||
ax1.set_ylim(0, 1.05)
|
||||
|
||||
# 子图2:发射率差异
|
||||
ax2 = axes[idx, 1] if n_plots > 1 else axes[1]
|
||||
ax2.plot(wl_common, diff, linewidth=2, color='darkgreen', label='Absolute Difference |ε1 - ε2|')
|
||||
ax2.fill_between(wl_common, 0, diff, alpha=0.3, color='darkgreen')
|
||||
if wl_min <= 13 and wl_max >= 8:
|
||||
ax2.axvspan(8, 13, alpha=0.15, color='orange', label='Atmospheric Window (8-13 μm)')
|
||||
ax2.set_xlabel('Wavelength (μm)', fontsize=12)
|
||||
ax2.set_ylabel('Absolute Difference', fontsize=12)
|
||||
ax2.set_title(f'Emissivity Difference (Thickness = {d} μm)', fontsize=14, fontweight='bold')
|
||||
ax2.grid(True, alpha=0.3)
|
||||
ax2.legend(fontsize=10)
|
||||
ax2.set_ylim(0, np.nanmax(diff) * 1.2)
|
||||
|
||||
# 子图3:相似度曲线(核心新增)
|
||||
ax3 = axes[idx, 2] if n_plots > 1 else axes[2]
|
||||
# 绘制局部皮尔逊相关系数(归一化到0-1)
|
||||
ax3.plot(wl_common, local_corr, linewidth=2.5, color='#4B0082', label='Local Pearson Correlation (0-1)') # 绘制局部余弦相似度(0-1)
|
||||
ax3.plot(wl_common, local_cos_sim, linewidth=2.5, color='orange', label='Local Cosine Similarity (0-1)',
|
||||
linestyle='--')
|
||||
# 标注相似度阈值线(0.9为高相似,0.8为中等相似)
|
||||
ax3.axhline(y=0.9, color='red', linestyle=':', linewidth=1.5, label='High Similarity Threshold (0.9)')
|
||||
ax3.axhline(y=0.8, color='orange', linestyle=':', linewidth=1.5, label='Medium Similarity Threshold (0.8)')
|
||||
# 标注大气窗口
|
||||
if wl_min <= 13 and wl_max >= 8:
|
||||
ax3.axvspan(8, 13, alpha=0.15, color='orange', label='Atmospheric Window (8-13 μm)')
|
||||
ax3.set_xlabel('Wavelength (μm)', fontsize=12)
|
||||
ax3.set_ylabel('Local Similarity (0-1)', fontsize=12)
|
||||
ax3.set_title(f'Wavelength-Dependent Similarity Curve (Thickness = {d} μm)', fontsize=14, fontweight='bold')
|
||||
ax3.grid(True, alpha=0.3)
|
||||
ax3.legend(fontsize=10)
|
||||
ax3.set_ylim(0, 1.05) # 相似度范围0-1
|
||||
ax3.set_xlim(wl_min, wl_max)
|
||||
|
||||
plt.tight_layout()
|
||||
plt.savefig('spectral_similarity_complete.png', dpi=300, bbox_inches='tight')
|
||||
plt.show()
|
||||
|
||||
|
||||
# -----------------------------
|
||||
# 5. 主程序执行
|
||||
# -----------------------------
|
||||
if __name__ == "__main__":
|
||||
file1 = '/Users/spasolreisa/IdeaProjects/asiaMath/data.txt'
|
||||
file2 = '/Users/spasolreisa/IdeaProjects/asiaMath/data2.txt'
|
||||
target_thicknesses = [0.5, 1.0, 1.5, 2.0]
|
||||
base_params = {
|
||||
'n_sub': 1.5,
|
||||
'k_sub': 0.0,
|
||||
'r': 0.05
|
||||
}
|
||||
window_size = 0.5 # 滑动窗口宽度(可调整,建议0.3-0.8μm)
|
||||
|
||||
print("=== 开始光谱相似性分析(含相似度曲线) ===")
|
||||
print(f"文件1: {file1}")
|
||||
print(f"文件2: {file2}")
|
||||
print(f"分析厚度: {target_thicknesses} μm")
|
||||
print(f"滑动窗口宽度: {window_size} μm")
|
||||
print("-" * 50)
|
||||
|
||||
results, wl_common, emissivity_dict, local_similarity_dict = analyze_spectral_similarity(
|
||||
file1, file2,
|
||||
thicknesses=target_thicknesses,
|
||||
n_sub=base_params['n_sub'],
|
||||
k_sub=base_params['k_sub'],
|
||||
r=base_params['r'],
|
||||
window_size=window_size
|
||||
)
|
||||
|
||||
# 输出全局指标
|
||||
print("\n=== 全局相似性指标 ===")
|
||||
for d in target_thicknesses:
|
||||
res = results[d]
|
||||
print(f"\n【厚度 {d} μm】")
|
||||
print(f"全局皮尔逊相关系数: {res['pearson_correlation']:.4f}")
|
||||
print(f"全局余弦相似度: {res['cosine_similarity']:.4f}")
|
||||
print(f"归一化均方误差: {res['normalized_mse']:.4f}")
|
||||
print(f"平均绝对误差: {res['mae']:.4f}")
|
||||
if res['window_pearson_correlation'] is not None:
|
||||
print(f"大气窗口全局相关系数: {res['window_pearson_correlation']:.4f}")
|
||||
|
||||
# 输出局部相似度统计(大气窗口内)
|
||||
print("\n=== 大气窗口(8-13μm)局部相似度统计 ===")
|
||||
for d in target_thicknesses:
|
||||
local_corr, local_cos_sim, _ = local_similarity_dict[d]
|
||||
if wl_min <= 13 and wl_max >= 8:
|
||||
window_mask = (wl_common >= 8) & (wl_common <= 13)
|
||||
window_local_corr = local_corr[window_mask]
|
||||
window_local_cos = local_cos_sim[window_mask]
|
||||
# 过滤NaN值
|
||||
window_local_corr = window_local_corr[~np.isnan(window_local_corr)]
|
||||
window_local_cos = window_local_cos[~np.isnan(window_local_cos)]
|
||||
if len(window_local_corr) > 0:
|
||||
print(f"\n【厚度 {d} μm】")
|
||||
print(f"大气窗口局部相关系数均值: {np.mean(window_local_corr):.4f}")
|
||||
print(f"大气窗口局部相关系数最小值: {np.min(window_local_corr):.4f}")
|
||||
print(f"大气窗口局部余弦相似度均值: {np.mean(window_local_cos):.4f}")
|
||||
|
||||
# 结果解读
|
||||
print("\n=== 结果解读 ===")
|
||||
print("1. 相似度曲线(子图3):值越接近1,对应波长下的发射率越相似;")
|
||||
print("2. 高相似区域(≥0.9):两文件在该波段的辐射冷却性能几乎一致;")
|
||||
print("3. 低相似区域(<0.8):需关注该波段的材料差异对冷却效果的影响;")
|
||||
print("4. 大气窗口内相似度:优先关注该区域,直接决定辐射冷却核心性能是否一致。")
|
||||
Reference in New Issue
Block a user