Files
Uni-Lab-OS/unilabos/devices/opsky_Raman/raman_module.py
2025-11-15 02:23:09 +08:00

181 lines
6.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# raman_module.py
import os
import time as time_mod
import numpy as np
import pandas as pd
# clr / ATRWrapper 依赖:在真实环境中使用 Windows + .NET wrapper
# 本模块对缺少 clr 或 Wrapper 的情况提供“仿真”回退,方便离线/调试运行。
try:
import clr
has_clr = True
except Exception:
clr = None
has_clr = False
# 本函数返回 (success: bool, file_prefix: str|None, df: pandas.DataFrame|None)
def run_raman_test(integration_time=5000, laser_power=200,
save_csv=True, save_plot=True,
normalize=False, norm_max=None,
max_wavenum=1300):
"""
拉曼测试流程(更稳健的实现):
- 若能加载 ATRWrapper 则使用之
- 否则生成模拟光谱(方便调试)
返回 (success, file_prefix, df)
"""
timestamp = time_mod.strftime("%Y%m%d_%H%M%S")
file_prefix = f"raman_{timestamp}"
wrapper = None
used_real_device = False
try:
if has_clr:
try:
# 请根据你的 DLL 路径调整
dll_path = r"D:\Raman\Raman_RS\ATRWrapper\ATRWrapper.dll"
if os.path.exists(dll_path):
clr.AddReference(dll_path)
else:
# 试图直接 AddReference 名称(若已在 PATH
try:
clr.AddReference("ATRWrapper")
except Exception:
pass
from Optosky.Wrapper import ATRWrapper # May raise
wrapper = ATRWrapper()
used_real_device = True
except Exception as e:
# 无法加载真实 wrapper -> fallback
print("⚠️ 未能加载 ATRWrapper使用模拟数据。详细:", e)
wrapper = None
if wrapper is None:
# 生成模拟光谱(方便调试)
# 模拟波数轴 50..1300
WaveNum = np.linspace(50, max_wavenum, 1024)
# 合成几条高斯峰 + 噪声
def gauss(x, mu, sig, A):
return A * np.exp(-0.5 * ((x - mu) / sig) ** 2)
Spect_data = (gauss(WaveNum, 200, 8, 1000) +
gauss(WaveNum, 520, 12, 600) +
gauss(WaveNum, 810, 20, 400) +
50 * np.random.normal(scale=1.0, size=WaveNum.shape))
Spect_bLC = Spect_data - np.min(Spect_data) * 0.05 # 简单 baseline
Spect_smooth = np.convolve(Spect_bLC, np.ones(3) / 3, mode="same")
df = pd.DataFrame({
"WaveNum": WaveNum,
"Raw_Spect": Spect_data,
"BaseLineCorrected": Spect_bLC,
"Smooth_Spect": Spect_smooth
})
success = True
file_prefix = f"raman_sim_{timestamp}"
# 保存 CSV / 绘图 等同真实设备
else:
# 使用真实设备 API根据你提供的 wrapper 调用)
On_flag = wrapper.OpenDevice()
print("通讯连接状态:", On_flag)
if not On_flag:
wrapper.CloseDevice()
return False, None, None
wrapper.SetIntegrationTime(int(integration_time))
wrapper.SetLdPower(int(laser_power), 1)
# 可能的冷却设置(如果 wrapper 支持)
try:
wrapper.SetCool(-5)
except Exception:
pass
Spect = wrapper.AcquireSpectrum()
Spect_data = np.array(Spect.get_Data())
if not Spect.get_Success():
print("光谱采集失败")
try:
wrapper.CloseDevice()
except Exception:
pass
return False, None, None
WaveNum = np.array(wrapper.GetWaveNum())
Spect_bLC = np.array(wrapper.BaseLineCorrect(Spect_data))
Spect_smooth = np.array(wrapper.SmoothBoxcar(Spect_bLC, 3))
df = pd.DataFrame({
"WaveNum": WaveNum,
"Raw_Spect": Spect_data,
"BaseLineCorrected": Spect_bLC,
"Smooth_Spect": Spect_smooth
})
wrapper.CloseDevice()
success = True
# 如果需要限定波数范围
mask = df["WaveNum"] <= max_wavenum
df = df[mask].reset_index(drop=True)
# 可选归一化
if normalize:
arr = df["Smooth_Spect"].values
mn, mx = arr.min(), arr.max()
if mx == mn:
df["Smooth_Spect"] = 0.0
else:
scale = 1.0 if norm_max is None else float(norm_max)
df["Smooth_Spect"] = (arr - mn) / (mx - mn) * scale
# 同时处理其它列(可选)
arr_raw = df["Raw_Spect"].values
mn_r, mx_r = arr_raw.min(), arr_raw.max()
if mx_r == mn_r:
df["Raw_Spect"] = 0.0
else:
scale = 1.0 if norm_max is None else float(norm_max)
df["Raw_Spect"] = (arr_raw - mn_r) / (mx_r - mn_r) * scale
# 保存 CSV
if save_csv:
csv_filename = f"{file_prefix}.csv"
df.to_csv(csv_filename, index=False)
print("✅ CSV 文件已生成:", csv_filename)
# 绘图(使用 matplotlib注意不要启用 GUI 后台
if save_plot:
try:
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
plt.figure(figsize=(8, 5))
plt.plot(df["WaveNum"], df["Raw_Spect"], linestyle='-', alpha=0.6, label="原始")
plt.plot(df["WaveNum"], df["BaseLineCorrected"], linestyle='--', alpha=0.8, label="基线校正")
plt.plot(df["WaveNum"], df["Smooth_Spect"], linewidth=1.2, label="平滑")
plt.xlabel("WaveNum (cm^-1)")
plt.ylabel("Intensity (a.u.)")
plt.title(f"Raman {file_prefix}")
plt.grid(True)
plt.legend()
plt.tight_layout()
plot_filename = f"{file_prefix}.png"
plt.savefig(plot_filename, dpi=300, bbox_inches="tight")
plt.close()
# 小短暂等待以确保文件系统刷新
time_mod.sleep(0.2)
print("✅ 图像已生成:", plot_filename)
except Exception as e:
print("⚠️ 绘图失败:", e)
return success, file_prefix, df
except Exception as e:
print("拉曼测试异常:", e)
try:
if wrapper is not None:
try:
wrapper.CloseDevice()
except Exception:
pass
except Exception:
pass
return False, None, None