Python 从数据集*编辑规范化普朗克定律曲线拟合中的值*
我有一大组关于强度计数和波长的数据,我想用Planks定律来确定温度的猜测参数 数据集作为文本文件导入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
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输入值的顺序是统一的
当然,,