|
|
import numpy
|
|
|
|
|
|
def setConstants(dataOut):
|
|
|
dictionary = {}
|
|
|
dictionary["M"] = dataOut.normFactor
|
|
|
dictionary["N"] = dataOut.nFFTPoints
|
|
|
dictionary["ippSeconds"] = dataOut.ippSeconds
|
|
|
dictionary["K"] = dataOut.nIncohInt
|
|
|
|
|
|
return dictionary
|
|
|
|
|
|
def initialValuesFunction(data_spc, constants):
|
|
|
#Constants
|
|
|
M = constants["M"]
|
|
|
N = constants["N"]
|
|
|
ippSeconds = constants["ippSeconds"]
|
|
|
|
|
|
S1 = data_spc[0,:]/(N*M)
|
|
|
S2 = data_spc[1,:]/(N*M)
|
|
|
|
|
|
Nl=min(S1)
|
|
|
A=sum(S1-Nl)/N
|
|
|
#x = dataOut.getVelRange() #below matches Madrigal data better
|
|
|
x=numpy.linspace(-(N/2)/(N*ippSeconds),(N/2-1)/(N*ippSeconds),N)*-(6.0/2)
|
|
|
v=sum(x*(S1-Nl))/sum(S1-Nl)
|
|
|
al1=numpy.sqrt(sum(x**2*(S1-Nl))/sum(S2-Nl)-v**2)
|
|
|
p0=[al1,A,A,v,min(S1),min(S2)]#first guess(width,amplitude,velocity,noise)
|
|
|
return p0
|
|
|
|
|
|
def modelFunction(p, constants):
|
|
|
ippSeconds = constants["ippSeconds"]
|
|
|
N = constants["N"]
|
|
|
|
|
|
fm_c = ACFtoSPC(p, constants)
|
|
|
fm = numpy.hstack((fm_c[0],fm_c[1]))
|
|
|
return fm
|
|
|
|
|
|
def errorFunction(p, constants, LT):
|
|
|
|
|
|
J=makeJacobian(p, constants)
|
|
|
J =numpy.dot(LT,J)
|
|
|
covm =numpy.linalg.inv(numpy.dot(J.T ,J))
|
|
|
#calculate error as the square root of the covariance matrix diagonal
|
|
|
#multiplying by 1.96 would give 95% confidence interval
|
|
|
err =numpy.sqrt(numpy.diag(covm))
|
|
|
return err
|
|
|
|
|
|
#-----------------------------------------------------------------------------------
|
|
|
|
|
|
def ACFw(alpha,A1,A2,vd,x,N,ippSeconds):
|
|
|
#creates weighted autocorrelation function based on the operational model
|
|
|
#x is n or N-n
|
|
|
k=2*numpy.pi/3.0
|
|
|
pdt=x*ippSeconds
|
|
|
#both correlated channels ACFs are created at the sametime
|
|
|
R1=A1*numpy.exp(-1j*k*vd*pdt)/numpy.sqrt(1+(alpha*k*pdt)**2)
|
|
|
R2=A2*numpy.exp(-1j*k*vd*pdt)/numpy.sqrt(1+(alpha*k*pdt)**2)
|
|
|
# T is the triangle weigthing function
|
|
|
T=1-abs(x)/N
|
|
|
Rp1=T*R1
|
|
|
Rp2=T*R2
|
|
|
return [Rp1,Rp2]
|
|
|
|
|
|
def ACFtoSPC(p, constants):
|
|
|
#calls the create ACF function and transforms the ACF to spectra
|
|
|
N = constants["N"]
|
|
|
ippSeconds = constants["ippSeconds"]
|
|
|
|
|
|
n=numpy.linspace(0,(N-1),N)
|
|
|
Nn=N-n
|
|
|
R = ACFw(p[0],p[1],p[2],p[3],n,N,ippSeconds)
|
|
|
RN = ACFw(p[0],p[1],p[2],p[3],Nn,N,ippSeconds)
|
|
|
Rf1=R[0]+numpy.conjugate(RN[0])
|
|
|
Rf2=R[1]+numpy.conjugate(RN[1])
|
|
|
sw1=numpy.fft.fft(Rf1,n=N)
|
|
|
sw2=numpy.fft.fft(Rf2,n=N)
|
|
|
#the fft needs to be shifted, noise added, and takes only the real part
|
|
|
sw0=numpy.real(numpy.fft.fftshift(sw1))+abs(p[4])
|
|
|
sw1=numpy.real(numpy.fft.fftshift(sw2))+abs(p[5])
|
|
|
return [sw0,sw1]
|
|
|
|
|
|
def makeJacobian(p, constants):
|
|
|
#create Jacobian matrix
|
|
|
N = constants["N"]
|
|
|
IPPt = constants["ippSeconds"]
|
|
|
|
|
|
n=numpy.linspace(0,(N-1),N)
|
|
|
Nn=N-n
|
|
|
k=2*numpy.pi/3.0
|
|
|
#created weighted ACF
|
|
|
R=ACFw(p[0],p[1],p[2],p[3],n,N,IPPt)
|
|
|
RN=ACFw(p[0],p[1],p[2],p[3],Nn,N,IPPt)
|
|
|
#take derivatives with respect to the fit parameters
|
|
|
Jalpha1=R[0]*-1*(k*n*IPPt)**2*p[0]/(1+(p[0]*k*n*IPPt)**2)+numpy.conjugate(RN[0]*-1*(k*Nn*IPPt)**2*p[0]/(1+(p[0]*k*Nn*IPPt)**2))
|
|
|
Jalpha2=R[1]*-1*(k*n*IPPt)**2*p[0]/(1+(p[0]*k*n*IPPt)**2)+numpy.conjugate(RN[1]*-1*(k*Nn*IPPt)**2*p[0]/(1+(p[0]*k*Nn*IPPt)**2))
|
|
|
JA1=R[0]/p[1]+numpy.conjugate(RN[0]/p[1])
|
|
|
JA2=R[1]/p[2]+numpy.conjugate(RN[1]/p[2])
|
|
|
Jvd1=R[0]*-1j*k*n*IPPt+numpy.conjugate(RN[0]*-1j*k*Nn*IPPt)
|
|
|
Jvd2=R[1]*-1j*k*n*IPPt+numpy.conjugate(RN[1]*-1j*k*Nn*IPPt)
|
|
|
#fft
|
|
|
sJalp1=numpy.fft.fft(Jalpha1,n=N)
|
|
|
sJalp2=numpy.fft.fft(Jalpha2,n=N)
|
|
|
sJA1=numpy.fft.fft(JA1,n=N)
|
|
|
sJA2=numpy.fft.fft(JA2,n=N)
|
|
|
sJvd1=numpy.fft.fft(Jvd1,n=N)
|
|
|
sJvd2=numpy.fft.fft(Jvd2,n=N)
|
|
|
sJalp1=numpy.real(numpy.fft.fftshift(sJalp1))
|
|
|
sJalp2=numpy.real(numpy.fft.fftshift(sJalp2))
|
|
|
sJA1=numpy.real(numpy.fft.fftshift(sJA1))
|
|
|
sJA2=numpy.real(numpy.fft.fftshift(sJA2))
|
|
|
sJvd1=numpy.real(numpy.fft.fftshift(sJvd1))
|
|
|
sJvd2=numpy.real(numpy.fft.fftshift(sJvd2))
|
|
|
sJnoise=numpy.ones(numpy.shape(sJvd1))
|
|
|
#combine arrays
|
|
|
za=numpy.zeros([N])
|
|
|
sJalp=zip(sJalp1,sJalp2)
|
|
|
sJA1=zip(sJA1,za)
|
|
|
sJA2=zip(za,sJA2)
|
|
|
sJvd=zip(sJvd1,sJvd2)
|
|
|
sJn1=zip(sJnoise, za)
|
|
|
sJn2=zip(za, sJnoise)
|
|
|
#reshape from 2D to 1D
|
|
|
sJalp=numpy.reshape(list(sJalp), [2*N])
|
|
|
sJA1=numpy.reshape(list(sJA1), [2*N])
|
|
|
sJA2=numpy.reshape(list(sJA2), [2*N])
|
|
|
sJvd=numpy.reshape(list(sJvd), [2*N])
|
|
|
sJn1=numpy.reshape(list(sJn1), [2*N])
|
|
|
sJn2=numpy.reshape(list(sJn2), [2*N])
|
|
|
#combine into matrix and transpose
|
|
|
J=numpy.array([sJalp,sJA1,sJA2,sJvd,sJn1,sJn2])
|
|
|
J=J.T
|
|
|
return J
|
|
|
|