Skip to content

Commit d5aab36

Browse files
committed
feat: finding best parameters for SE Kernel
1 parent 535c63a commit d5aab36

File tree

3 files changed

+147
-3
lines changed

3 files changed

+147
-3
lines changed
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import frank
2+
import numpy as np
3+
import matplotlib.pyplot as plt
4+
5+
from frank.geometry import SourceGeometry
6+
from frank.radial_fitters import FrankFitter, FourierBesselFitter
7+
8+
# Huang 2018
9+
inc = 34.97
10+
pa = 85.76
11+
dra = 1.9e-3
12+
ddec = -2.5e-3
13+
r_out = 1.9
14+
15+
# Frank Parameters
16+
n_pts = 300
17+
alpha = 1.3
18+
w_smooth = 1e-1
19+
20+
# UVtable AS209 at 1mm with removed visibilities between .
21+
dir = "./"
22+
data_file = dir + 'AS209_continuum_prom_1chan_30s_keepflagsFalse_removed1.txt'
23+
24+
# Loading data
25+
u, v, Re, Im, Weights = np.loadtxt(data_file, unpack = True, skiprows = 1)
26+
vis = Re + Im*1j
27+
28+
geom = SourceGeometry(inc= inc, PA= pa, dRA= dra, dDec= ddec)
29+
30+
" Fitting with frank "
31+
#FF = FrankFitter(r_out, n_pts, geom, alpha = alpha, weights_smooth = w_smooth)
32+
FF = FourierBesselFitter(r_out, n_pts, geom)
33+
sol = FF.fit(u, v, vis, Weights)
34+
#setattr(sol, 'positive', sol.solve_non_negative())
35+
36+
fig = plt.figure(num = 1, figsize = (10, 5))
37+
plt.plot(sol.r, sol.mean / 1e10)
38+
plt.xlabel('Radius ["]', size = 15)
39+
plt.ylabel(r'Brightness profile [$10^{10}$ Jy sr$^{-1}$]', size = 15)
40+
plt.title('Frank Fit AS209 1mm', size = 15)
41+
plt.xlim(0, 1.3)
42+
#plt.savefig('FrankFit_AS209_1mm.jpg', bbox_inches='tight')
43+
plt.show()
44+
plt.close()

frank/radial_fitters.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,8 @@ def _build_matrices(self, mapping):
510510

511511
self._M = mapping['M']
512512
self._j = mapping['j']
513+
self._V = mapping['V']
514+
self._Wvalues = mapping['W']
513515

514516
self._H0 = mapping['null_likelihood']
515517

@@ -574,7 +576,8 @@ def fit(self, u, v, V, weights=1):
574576
def _fit(self):
575577
"""Fit step. Computes the best fit given the pre-processed data"""
576578
fit = GaussianModel(self._DHT, self._M, self._j,
577-
noise_likelihood=self._H0)
579+
noise_likelihood=self._H0,
580+
Wvalues= self._Wvalues, V = self._V)
578581

579582
self._sol = FrankGaussianFit(self._vis_map, fit, self._info,
580583
geometry=self._geometry.clone())

frank/statistical_models.py

Lines changed: 99 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -628,9 +628,12 @@ class GaussianModel:
628628
"""
629629

630630
def __init__(self, DHT, M, j, p=None, scale=None, guess=None,
631-
Nfields=None, noise_likelihood=0):
631+
Nfields=None, noise_likelihood=0,
632+
Wvalues = None, V = None):
632633

633634
self._DHT = DHT
635+
self._Wvalues = Wvalues
636+
self._V = V
634637

635638
# Correct shape of design matrix etc.
636639
if len(M.shape) == 2:
@@ -687,7 +690,19 @@ def __init__(self, DHT, M, j, p=None, scale=None, guess=None,
687690

688691
self._Sinv[sn:en, sn:en] += Sj[n]
689692
else:
690-
self._Sinv = None
693+
#self._Sinv = None
694+
q_array = self._DHT.q
695+
696+
def true_squared_exponential_kernel(q, p, l):
697+
698+
q1, q2 = np.meshgrid(q, q)
699+
p1, p2 = np.meshgrid(p, p)
700+
SE_Kernel = np.sqrt(p1 * p2) * np.exp(-0.5*(q1-q2)**2 / l**2)
701+
return SE_Kernel
702+
703+
Ykm = self._DHT.coefficients(direction="backward")
704+
# We continue after set M matrix because is needed to calculate
705+
# best parameters for S matrix.
691706

692707
# Compute the design matrix
693708
self._M = np.zeros([Nr*Nfields, Nr*Nfields], dtype='f8')
@@ -707,7 +722,89 @@ def __init__(self, DHT, M, j, p=None, scale=None, guess=None,
707722

708723
self._like_noise = noise_likelihood
709724

725+
# M is already defined, so we find best parameters for S matrix and use it.
726+
m, c , l = self.minimizeS()
727+
pI = np.exp(m*np.log(q_array) + c)
728+
S_fspace = true_squared_exponential_kernel(q_array, pI, l)
729+
S_real = np.dot(np.transpose(Ykm), np.dot(S_fspace, Ykm))
730+
S_real_inv = np.linalg.inv(S_real)
731+
self._Sinv = S_real_inv
732+
710733
self._fit()
734+
735+
def minimizeS(self):
736+
from scipy.optimize import minimize
737+
from scipy.special import gamma
738+
V = self._V
739+
740+
def calculate_S(m, c, l):
741+
q_array = self._DHT.q
742+
p_array = c*(q_array**m)
743+
def true_squared_exponential_kernel(q, p, l):
744+
q1, q2 = np.meshgrid(q, q)
745+
p1, p2 = np.meshgrid(p, p)
746+
SE_Kernel = np.sqrt(p1 * p2) * np.exp(-0.5*(q1-q2)**2 / l**2)
747+
return SE_Kernel
748+
749+
Ykm = self._DHT.coefficients(direction="backward")
750+
S_fspace = true_squared_exponential_kernel(q_array, p_array, l)
751+
S_real = np.dot(np.transpose(Ykm), np.dot(S_fspace, Ykm))
752+
return S_real
753+
754+
def calculate_D(S):
755+
S_real_inv = np.linalg.inv(S)
756+
Dinv = self._M + S_real_inv
757+
D = np.linalg.inv(Dinv)
758+
return [Dinv, D]
759+
760+
def calculate_mu(Dinv):
761+
try:
762+
Dchol = scipy.linalg.cho_factor(Dinv)
763+
mu = scipy.linalg.cho_solve(Dchol, self._j)
764+
765+
except np.linalg.LinAlgError:
766+
U, s, V = scipy.linalg.svd(Dinv, full_matrices=False)
767+
s1 = np.where(s > 0, 1. / s, 0)
768+
mu = np.dot(V.T, np.multiply(np.dot(U.T, self._j), s1))
769+
return mu
770+
771+
def likelihood(param, data):
772+
m, c, l = param
773+
Wvalues = self._Wvalues
774+
N = np.diag(1/Wvalues)
775+
776+
alpha = 1.3
777+
l0 = 1e7
778+
779+
# Create an Inverse Gamma distribution function
780+
def inv_gamma_function(l, alpha, beta):
781+
return ((gamma(alpha)*beta)**(-1))*((beta/l)**(alpha + 1))*np.exp(-beta/l)
782+
783+
S = calculate_S(m,c, l)
784+
[Dinv, D] = calculate_D(S)
785+
mu = calculate_mu(Dinv)
786+
logdetS = np.linalg.slogdet(S)[1]
787+
logdetD = np.linalg.slogdet(D)[1]
788+
logdetN = np.linalg.slogdet(N)[1]
789+
factor = np.log(2*np.pi)
790+
791+
log_likelihood = 2*np.log(np.abs((1/m)*(1/c))) \
792+
+ 2*np.log(inv_gamma_function(l, alpha, l0)) \
793+
- 0.5*(factor + logdetN) \
794+
- 0.5*(factor + logdetS) \
795+
+ 0.5*(factor + logdetD) \
796+
+ 0.5*np.dot(np.transpose(self._j), mu) \
797+
- 0.5*np.dot(np.transpose(data), np.dot(np.diag(Wvalues), data))
798+
return -log_likelihood
799+
800+
result = minimize(likelihood, x0=np.array([-5, 60, 5e4]), args=(V,),
801+
bounds=[(-6, 6), (1, 70), (1e3, 1e6)],
802+
method="Powell", tol=1e-6,
803+
)
804+
m, c, l = result.x
805+
print("Result: ", "m: ", m, "c: ", c, "l: ", "{:e}".format(l))
806+
return [m, c, l]
807+
711808

712809
def _fit(self):
713810
"""Compute the mean and variance"""

0 commit comments

Comments
 (0)