import numpy as np
import matplotlib.pyplot as plt
from lmfit import Model,Parameters
f2= "KELT_N16_lc_006261_V01_west_tfa.dat"
t2="TIMES" # file name
NewData2 = np.loadtxt(t2, dtype=float, unpack=True)
NewData = np.loadtxt(f2,dtype=float, unpack=True, usecols=(1,))
flux = NewData
time= NewData2
new_flux=np.hstack([flux,flux])
# fold
period = 2.0232 # period (must be known already!)
foldTimes = ((time)/ period) # divide by period to convert to phase
foldTimes = foldTimes % 1 # take fractional part of phase only (i.e. discard whole number part)
new_phase=np.hstack([foldTimes+1,foldTimes])
print len(new_flux)
print len(new_phase)
def Wave(x, new_flux,new_phase):
wave = new_flux*np.sin(new_phase+x)
return wave
model = Model(Wave)
print "Independent Vars:", model.independent_vars
print "Parameters:",model.param_names
p = Parameters()
p.add_many(('new_flux',13.42, True, None, None, None) )
p.add_many(('new_phase',0,True, None, None, None) )
result=model.fit(new_flux,x=new_phase,params=p,weights= None)
plt.scatter(new_phase,new_flux,marker='o',edgecolors='none',color='blue',s=5.0, label="Period: 2.0232 days")
plt.ylim([13.42,13.54])
plt.xlim(0,2)
plt.gca().invert_yaxis()
plt.title('HD 240121 Light Curve with BJD Correction')
plt.ylabel('KELT Instrumental Magnitude')
plt.xlabel('Phase')
legend = plt.legend(loc='lower right', shadow=True)
plt.scatter(new_phase,result.best_fit,label="One Oscillation Fit", color='red',s=60.0)
plt.savefig('NewEpoch.png')
print result.fit_report()
我正在尝试将正弦函数拟合到研究项目的阶段光曲线数据。但是,我不确定我哪里出错了,我相信它存在于我的参数中。看起来拟合的幅度太高,而且周期太长。任何帮助,将不胜感激。谢谢!
这就是图形现在的样子(尝试将正弦函数拟合到我的数据集中):
答案 0 :(得分:1)
一些意见/建议:
首先,替换
几乎肯定更好p = Parameters()
p.add_many(('new_flux',13.42, True, None, None, None) )
p.add_many(('new_phase',0,True, None, None, None) )
与
p = Parameters()
p.add('new_flux', value=13.42, vary=True)
p.add('new_phase', value=0, vary=True)
其次,您的模型不包括DC偏移,但您的数据显然有一个。偏移约为13.4,正弦波的幅度约为0.05。当你在它的时候,你可能想要包括一个比例相位和一个偏移量,以便模型
offset + amplitude * sin(scale*x + phase_shift)
您不一定要改变所有这些,但是让模型更加通用将允许查看相移和比例是如何相关的 - 给定数据中的噪声级别,这可能很重要。
使用更通用的模型,您可以尝试使用model.eval()
来评估具有一组参数的模型的几组参数值。一旦你有一个更好的模型和合理的起点,你应该得到一个合理的契合。
答案 1 :(得分:0)
我们如何帮助您使用未注释的代码?
我将从计算近似正弦波参数开始。假设您以data
点的形式获得了n
个x,y
坐标y(t) = y0+A*sin(x0+x(t)*f)
。并希望适应一股罪恶的浪潮:
y0
x0
是y偏移,A
是相位偏移,f
是幅度,y0 = sum(data[i].y)/n where i={0,1,2,...n-1}
是角频率。
我会:
计算平均值
y0
这是表示你的正弦波可能y偏移y0
的平均值。
计算到d = sum (|data[i].y-y0|)/n where i={0,1,2,...n-1}
的平均距离
A = sqrt(2)*d
如果我的记忆很好,那么这应该是幅度的有效值,所以:
x
在数据集中找到零交叉
为此,数据集应按i
排序,如果不是,则对其进行排序。请记住索引i0
:第一次越过i1
,最后一次越过j
和找到的过境点数f=M_PI*double(j-1)/(datax[i1]-datax[i0]);
x0=-datax[i0]*f;
,我们可以估算出频率和相位偏差:
i1=i0+((i1-i0)/(j-1));
if (datay[(i0+i1)>>1]<=y0) x0+=M_PI;
确定我们对齐的半个正弦波只检查前两个零交叉点之间的中点符号
x0,y0,f,A
或者检查特定的过零模式。
现在我们只有大约//---------------------------------------------------------------------------
#include <math.h>
// input data
const int n=5000;
double datax[n];
double datay[n];
// fitted sin wave
double A,x0,y0,f;
//---------------------------------------------------------------------------
void data_generate() // genere random noisy sinvawe
{
int i;
double A=150.0,x0=250.0,y0=200.0,f=0.03,r=20.0;
double x,y;
Randomize();
for (i=0;i<n;i++)
{
x=800.0*double(i)/double(n);
y=y0+A*sin(x0+x*f);
datax[i]=x+r*Random();
datay[i]=y+r*Random();
}
}
//---------------------------------------------------------------------------
void data_fit() // find raw approximate of x0,y0,f,A
{
int i,j,e,i0,i1;
double x,y,q0,q1;
// y0 = avg(y)
for (y0=0.0,i=0;i<n;i++) y0+=datay[i]; y0/=double(n);
// A = avg(|y-y0|)
for (A=0.0,i=0;i<n;i++) A+=fabs(datay[i]-y0); A/=double(n); A*=sqrt(2.0);
// bubble sort data by x asc
for (e=1,j=n;e;j--)
for (e=0,i=1;i<j;i++)
if (datax[i-1]>datax[i])
{
x=datax[i-1]; datax[i-1]=datax[i]; datax[i]=x;
y=datay[i-1]; datay[i-1]=datay[i]; datay[i]=y;
e=1;
}
// find zero crossings
for (i=0,j=0;i<n;)
{
// find value below zero
for (;i<n;i++) if (datay[i]-y0<=-0.75*A) break; e=i;
// find value above zero
for (;i<n;i++) if (datay[i]-y0>=+0.75*A) break;
if (i>=n) break;
// find point closest to zero
for (i1=e;e<i;e++)
if (fabs(datay[i1]-y0)>fabs(datay[e]-y0)) i1=e;
if (!j) i0=i1; j++;
}
f=2.0*M_PI*double(j-1)/(datax[i1]-datax[i0]);
x0=-datax[i0]*f;
}
//---------------------------------------------------------------------------
sinwave的参数。
这里我测试了一些 C ++ 代码(抱歉我不使用Python):
$autoload['libraries'] = array('database','ci_session');
预览:
点生成噪声数据,蓝色曲线适合sin波。
除此之外,您还可以构建您的配件以提高精度。无论您将使用哪种方法搜索找到的参数。例如,我会去: