使用models.Gaussian1D拟合吸收谱线,结果呈线性而非高斯分布
问题分析与修正方案
你的拟合结果变成线性分布,核心原因是吸收谱线的特征与你设置的高斯模型初始参数不匹配,且未考虑连续谱背景的影响,具体问题和解决办法如下:
1. 吸收谱线的振幅初始值错误
吸收谱线是通量低于连续谱的“谷”,但你用np.max(fluxNE)作为高斯振幅的初始值,这会让模型一开始就朝着“峰”的方向拟合,和实际吸收特征完全相反。
修正:
- 先估算连续谱基线(比如取裁剪区间两端的通量平均值)
- 振幅初始值设为**(通量最小值 - 基线)**,也就是负数,对应吸收谷的深度
2. 缺少连续谱背景模型
真实光谱的吸收线是叠加在连续谱(可能是线性或常数)之上的,单纯用高斯模型拟合会让算法被迫用高斯参数去拟合背景,最终得到近似线性的结果。
修正:
- 用
Gaussian1D + Linear1D组合模型,同时拟合吸收线和背景
3. 初始参数优化
确保高斯的中心波长、宽度初始值贴近真实谱线:
- 中心波长可以用吸收谷对应的实际波长(而非直接用文件里的理论值,避免谱线偏移影响)
- 确认文件中
lineWidth的定义:如果是标准差(sigma),则直接使用;如果是半高全宽(FWHM),需要转换为sigma = lineWidth / 2.3548
修正后的代码
import os import numpy as np import matplotlib.pyplot as plt from astropy.modeling import models, fitting data_folder_path = '/home/marzie/Documents/new measurement section/measurement/test' #data address molecules_wave_list = '/home/marzie/Documents/new measurement section/measurement/Table of DIBS (copy).txt' #source molecules (Hobbs data) data_files = [file for file in os.listdir(data_folder_path) if file.endswith('.txt')] for file in data_files: #Reading data file_path = os.path.join(data_folder_path, file) wave, flux = np.loadtxt(file_path, unpack=True) file_name = os.path.splitext(file)[0] # Extract file name without extension #Cut the spectrum for desired molecule with open(molecules_wave_list, 'r') as molec: next(molec) # skip header for line in molec: molec_value = line.split() central_wave_file = float(molec_value[0]) sigma_file = float(molec_value[1]) # 假设文件里的是标准差(sigma) fwhm = 2.3548 * sigma_file # 裁剪范围:用FWHM的3倍左右,避免包含过多无关背景 cut_range = max(3*fwhm, 2.0) idx = (wave >= central_wave_file - cut_range) & (wave <= central_wave_file + cut_range) waveNE = wave[idx] fluxNE = flux[idx] # 1. 估计连续谱基线(取区间两端的平均值) baseline = np.mean([fluxNE[:10].mean(), fluxNE[-10:].mean()]) # 2. 找到吸收谷的位置和深度,作为高斯初始参数 min_flux_idx = np.argmin(fluxNE) peak_wave = waveNE[min_flux_idx] peak_amp = fluxNE[min_flux_idx] - baseline # 负数值,对应吸收谷 # 3. 组合模型:高斯(吸收)+ 线性背景 gauss = models.Gaussian1D(amplitude=peak_amp, mean=peak_wave, stddev=sigma_file) linear = models.Linear1D(slope=0, intercept=baseline) combined_model = gauss + linear # 4. 拟合模型 fit_g = fitting.LevMarLSQFitter() fitted_model = fit_g(combined_model, waveNE, fluxNE) # 绘图 plt.figure(figsize=(8,5)) plt.plot(waveNE, fluxNE, label='观测数据') plt.plot(waveNE, fitted_model(waveNE), label='拟合结果', linewidth=2) plt.title(f'{file_name} - 吸收线高斯拟合') plt.xlabel('波长') plt.ylabel('通量') plt.legend() plt.show()
额外注意事项
- 如果文件里的
lineWidth是半高全宽(FWHM),需将sigma_file改为float(molec_value[1]) / 2.3548 - 若裁剪后的连续谱是水平的,可替换
Linear1D为Constant1D作为背景模型 - 拟合前先检查裁剪后的
waveNE和fluxNE是否包含清晰的吸收谷,避免裁剪范围错误导致无有效谱线
内容的提问来源于stack exchange,提问作者marzieh Faraji
相关产品推荐
相关产品推荐

