Python 从数据集*编辑规范化普朗克定律曲线拟合中的值*

Python 从数据集*编辑规范化普朗克定律曲线拟合中的值*,python,numpy,scipy,curve-fitting,Python,Numpy,Scipy,Curve Fitting,我有一大组关于强度计数和波长的数据,我想用Planks定律来确定温度的猜测参数 数据集作为文本文件导入 import numpy as np import scipy as sp from scipy.optimize import curve_fit with open('Good_SolarRun2.txt') as g: data = g.read() data = data.split('\n') Wavle2 = [float(row.split()[0]) for row

我有一大组关于强度计数和波长的数据,我想用Planks定律来确定温度的猜测参数

数据集作为文本文件导入

import numpy as np
import scipy as sp
from scipy.optimize import curve_fit

with open('Good_SolarRun2.txt') as g:
    data = g.read()
data = data.split('\n')
Wavle2 = [float(row.split()[0]) for row in data]   # Wavelength (nm)
Int2 = [float(row.split()[1]) for row in data]  # Intensity (counts)
因此,我现在定义了Planks定律的拟合模型(根据波长)

---根据用户Evert的建议,我将常数设置为等于1,因为在计算机上优化小数字很困难

from scipy.constants import h,k,c

def Plancks_Law(lamb, T):
    return 1/np.power(lamb,5.0) * 1/( np.exp( 1/(lamb*T)) - 1 )
现在,我开始用我的数据集设置曲线拟合配置

x = Wavle2

# This has the same shape as Wavle2, but these values are scaled by me.
# Also the same shape as Int2
y = np.array(Intscale2P)

p0_R = (500.) 
optR, pcovR = curve_fit(Plancks_Law, x, y, p0_R)
T_R = optR
T_Rp = pcovR
yM = Plancks_Law(x, T_R)
print T T\u R
返回
542.04628177的值

这是一些未知的单位。我现在被难住了,怎么把所有的东西都转换成正确的单位。特别是指数中的值,以正确的单位表示


有什么方法可以纠正这个问题吗?

这里有一个稍微挑剔的问题:根据x值(波长),指数
1/(lamb*T)
通常太大而无法计算,并且会溢出。(或太小,它将始终导致零

最好尝试将普朗克函数分为三部分:

  • lamb*T
    较大的部分,例如>100。然后可以使用瑞利-琼斯近似
  • lamb*T
    较小的部分,例如<1e-4。然后可以使用维恩近似
  • 对于中间部分,使用函数本身
这将防止溢出


要获得良好的拟合结果,最好不要让参数和数据结果超出机器限制,无论是太大还是太小。由于拟合通常会导致中间结果远远超出输入(参数或数据)范围,因此最安全的做法是,一切都是有序统一的(这仅仅是人类的结果,计算机是由人类制造的,也是为人类制造的)

从原始普朗克函数开始:

alpha = 2*h*c*c
beta = h*c/k
return alpha/np.power(lamb,5.0) * 1/( np.exp( beta/(lamb*T)) - 1 )
请注意,alpha只是一个标准化。将其保留在此处,并在最后应用于拟合结果。在拟合过程中,不会有任何大或小的alpha值,只有
1
。这一点很简单

对于beta版,你不能真正做到这一点:你不能在指数之外对它进行建模,并在事实发生后应用它。这就是上面三部分函数的作用,以规避那里的问题

不过,您也可以(也可能应该)规范化x值。假设您的输入顺序为1e-9,因此纳米以米表示。以纳米为单位,将所有值乘以1e9。现在,x输入值的顺序是统一的

当然,这意味着你的alpha会改变;这里有一个
lambd**-5
因子,所以如果
lambd
增加1e9,那么这里的情况会改变
1/1e-(9*5)=1e45
。将1e45因子化为alpha

对于beta,也有类似的情况:你用1e9乘以
beta

最后,您还可以尝试“规范化”
T
。5000离顺序统一并不远,但您可以将其转换为int 5,并将因子1000转换为
beta

另外,将
alpha
beta
放在函数外部:它们本质上是常量,不需要在每次调用函数时进行求值。这使得拟合速度更快

注意:如果您从函数中删除alpha,并且仅在拟合后使用它,请不要忘记将其从Wien和Rayleigh Jeans近似中删除。如下所述:测试(例如,手动比较从一个配方到另一个配方的区域周围的结果,并查看其是否匹配。或者简单地在对数图上绘制宽范围的曲线)


免责声明:我没有测试过这个,可能得到了错误的信号。三次检查你需要的是1e45而不是1e-45,1e9或1e-9也是如此。简单检查:输入一些合适的数字,波长以米为单位,看看你得到了什么通量,然后输入波长以纳米为单位的附加因子,看看你是否得到了相同的通量


另外:抓起一张纸,一步一步地计算出变化。在这里这样做,你也可以将同样的方法应用于其他函数和拟合问题。

你在这里有一个稍微挑剔的问题:根据你的x值(波长),指数,
1/(lamb*T)
通常可能太大而无法计算,您将得到溢出。(或者太小,结果总是为零。)

最好尝试将普朗克函数分为三部分:

  • lamb*T
    较大的部分,例如>100。然后可以使用瑞利-琼斯近似
  • lamb*T
    较小的部分,例如<1e-4。然后可以使用维恩近似
  • 对于中间部分,使用函数本身
这将防止溢出


要获得良好的拟合结果,最好不要让参数和数据结果超出机器限制,无论是太大还是太小。由于拟合通常会导致中间结果远远超出输入(参数或数据)范围,因此最安全的做法是,一切都是有序统一的(这仅仅是人类的结果,计算机是由人类制造的,也是为人类制造的)

从原始普朗克函数开始:

alpha = 2*h*c*c
beta = h*c/k
return alpha/np.power(lamb,5.0) * 1/( np.exp( beta/(lamb*T)) - 1 )
请注意,alpha只是一个标准化。将其保留在此处,并在最后应用于拟合结果。在拟合过程中,不会有任何大或小的alpha值,只有
1
。这一点很简单

对于beta版,你不能真正做到这一点:你不能在指数之外对它进行建模,并在事实发生后应用它。这就是上面三部分函数的作用,以规避那里的问题

不过,您也可以(也可能应该)规范化x值。假设您的输入顺序为1e-9,因此纳米以米表示。以纳米为单位,将所有值乘以1e9。现在,x输入值的顺序是统一的

当然,,