You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python交互式卢瑟福散射模拟中曲线拟合时灵时不灵的问题排查

Python交互式卢瑟福散射模拟中曲线拟合时灵时不灵的问题排查

嗨,我仔细看了你的代码和遇到的问题,曲线拟合时好时坏、大角度突然平线的情况确实挺闹心的,咱们从物理模型和代码细节两个维度来排查解决:

一、核心问题分析

你的拟合不稳定主要来自三个方面:

  1. 拟合模型冗余:你用了A / np.sin(theta/2)**4 + B的模型,但卢瑟福散射公式里根本没有常数偏移项B。大角度时sin(theta/2)趋近于1,B很容易被噪声点带偏,直接抵消掉信号导致平线。
  2. 噪声设计不合理:你当前的噪声计算total_noise_level = scaled_noise_level + noise_scaling + angle_factor,其中angle_factor是1/sin(theta/2)**4,大角度时这个值会爆炸式增长,导致模拟数据的噪声远大于真实信号,拟合器完全抓不住趋势。
  3. 初始猜测与边界缺失:虽然你试了多个初始猜测,但没给参数设置物理合理的边界,curve_fit很容易跑到负数或极端值,直接破坏拟合结果。

二、针对性修改方案

1. 修正拟合模型,去掉冗余的偏移项

把拟合函数改成严格匹配卢瑟福公式的形式,避免引入不必要的自由度:

def fit_curve_function(theta, A):
    """贴合物理模型的拟合函数,无多余偏移项"""
    return A / np.sin(theta / 2)**4

2. 优化噪声生成逻辑,贴近真实实验统计特性

把绝对噪声改成相对噪声+泊松统计噪声,大角度的噪声会和信号成正比,不会盖过真实趋势:

def monte_carlo_simulation(analytical, theta, EK_slider_value, Ni_slider_value, noise_level=0.1):
    """改进的噪声生成,更符合实验统计规律"""
    # 相对噪声:和信号幅度成正比
    relative_noise = np.random.normal(0, noise_level, size=theta.shape)
    # 泊松噪声:模拟粒子计数的统计涨落(真实实验的核心噪声来源)
    poisson_noise = np.random.poisson(analytical) - analytical
    
    # 组合噪声并确保数据非负
    simulated_data = analytical + analytical * relative_noise + poisson_noise
    simulated_data = np.maximum(simulated_data, 0)

    return simulated_data

3. 优化拟合逻辑,添加物理合理的参数边界

给拟合参数设置正数边界,同时用中等角度的模拟数据计算初始猜测,让拟合器从更合理的起点开始:

@debounce
# Fit the simulated data
def fit_simulation(change):
    global simulated_data, analytical_data
    if analytical_data is None or simulated_data is None:
        with output_error:
            output_error.clear_output()
            print("Run the simulation first to generate simulated data and analytical curve.")
        return

    try:
        # 使用贴合物理的拟合函数
        def fit_curve_function(theta, A):
            return A / np.sin(theta / 2)**4

        # 基于中等角度(比如30度)的模拟数据计算初始猜测,避免极端值干扰
        theta_30 = np.radians(30)
        idx_30 = np.argmin(np.abs(np.degrees(theta_values)-30))
        A_init = simulated_data[idx_30] * np.sin(theta_30/2)**4

        # 设置参数边界:A必须为正,符合物理意义
        popt, pcov = curve_fit(fit_curve_function, theta_values, simulated_data, 
                               p0=[A_init], bounds=(0, np.inf))
        
        # 计算拟合曲线
        fit_curve = fit_curve_function(theta_values, *popt)

        # 绘制结果
        with output_plot:
            output_plot.clear_output()
            plt.figure(figsize=(8, 6))
            plt.plot(np.degrees(theta_values), simulated_data, '.', color='green', label="Simulated Data")
            plt.plot(np.degrees(theta_values), analytical_data, '-', color='blue', label="Analytical Curve")
            plt.plot(np.degrees(theta_values), fit_curve, '--', color='red', label=f"Fit Curve (A={popt[0]:.2e})")
            plt.xlabel("Scattering Angle (degrees)")
            plt.ylabel(r"$N(\theta)$")
            plt.yscale('log')
            plt.title("Simulated Data with Analytical and Fit Curves")
            plt.grid()
            plt.tight_layout()
            plt.legend()
            plt.show()

    except Exception as e:
        with output_error:
            output_error.clear_output()
            print(f"Fitting failed: {str(e)}")

三、额外优化建议

  • 如果大角度的拟合还是不稳定,可以给拟合过程加权重,降低噪声大的点的影响:在curve_fit里添加sigma=1/np.sqrt(analytical),让信号强的点权重更高。
  • 可以在滑块调整时自动重新计算模拟数据(去掉按钮触发),配合防抖函数,提升交互体验。

备注:内容来源于stack exchange,提问作者Keanna

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 18:03:09