Skip to content

Commit 902a85f

Browse files
committed
feat: adapted for testing estimated resolution
1 parent 47dac1d commit 902a85f

File tree

4 files changed

+899
-47
lines changed

4 files changed

+899
-47
lines changed

frank/Examples/13_July_ResolutionTest.ipynb

Lines changed: 821 additions & 0 deletions
Large diffs are not rendered by default.

frank/fourier2d.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ def __init__(self, Rmax, N, nu=0):
2121
self.dy = 2*self.Ymax/self.Ny
2222

2323
# Frequency space collocation points.
24-
# The [1:] is because to not consider the 0 baseline. But we're missing points.
2524
q1n = np.fft.fftfreq(self.Nx, d = self.dx)
2625
q2n = np.fft.fftfreq(self.Ny, d = self.dy)
2726
q1n, q2n = np.meshgrid(q1n, q2n, indexing='ij')
@@ -53,11 +52,10 @@ def coefficients(self, u = None, v = None, x = None, y = None, direction="forwar
5352
norm = 1 / (4*self.Xmax*self.Ymax)
5453
factor = 2j*np.pi
5554

56-
X, Y = u, v
55+
X, Y = self.Un, self.Vn
5756
if u is None:
58-
X, Y = self.Un, self.Vn
59-
u = self.Xn
60-
v = self.Yn
57+
u = self.Xn
58+
v = self.Yn
6159
else:
6260
raise AttributeError("direction must be one of {}"
6361
"".format(['forward', 'backward']))
@@ -94,4 +92,9 @@ def Rmax(self):
9492
@property
9593
def resolution(self):
9694
""" Resolution of the grid in the x coordinate in rad"""
97-
return self.dx
95+
return self.dx
96+
97+
@property
98+
def xy_points(self):
99+
""" Collocation points in the image plane"""
100+
return self.Xn, self.Yn

frank/radial_fitters.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ def interpolate_brightness(self, Rpts, I=None):
168168
-----
169169
The resulting brightness will be consistent with higher-resolution fits
170170
as long as the original fit has sufficient resolution. By sufficient
171-
resolution we simply mean that the missing terms in the Fourier-Bessel
171+
we simply mean that the missing terms in the Fourier-Bessel
172172
series are negligible, which will typically be the case if the
173173
brightness was obtained from a frank fit with 100 points or more.
174174
"""
@@ -437,7 +437,7 @@ class FourierBesselFitter(object):
437437

438438
def __init__(self, Rmax, N, geometry=None, nu=0, block_data=True,
439439
assume_optically_thick=True, scale_height=None,
440-
block_size=10 ** 5, verbose=True):
440+
block_size=10 ** 5, verbose=True, geometry_on = True):
441441

442442
Rmax /= rad_to_arcsec
443443

@@ -457,7 +457,7 @@ def __init__(self, Rmax, N, geometry=None, nu=0, block_data=True,
457457
model = 'opt_thin'
458458

459459
self._vis_map = VisibilityMapping(self._DHT, geometry,
460-
model, scale_height=scale_height,
460+
model, geometry_on = geometry_on ,scale_height=scale_height,
461461
block_data=block_data, block_size=block_size,
462462
check_qbounds=False, verbose=verbose,
463463
DFT = self._DFT)

frank/statistical_models.py

Lines changed: 66 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ class VisibilityMapping:
6666
Whether to print notification messages
6767
"""
6868
def __init__(self, DHT, geometry,
69-
vis_model='opt_thick', scale_height=None, block_data=True,
69+
vis_model='opt_thick', geometry_on = True, scale_height=None, block_data=True,
7070
block_size=10 ** 5, check_qbounds=True, verbose=True,
7171
DFT = None):
7272

@@ -78,6 +78,7 @@ def __init__(self, DHT, geometry,
7878
self._vis_model = vis_model
7979
self.check_qbounds = check_qbounds
8080
self._verbose = verbose
81+
self.geometry_on = geometry_on
8182

8283
self._chunking = block_data
8384
self._chunk_size = block_size
@@ -165,7 +166,8 @@ def map_visibilities(self, u, v, V, weights, frequencies=None, geometry=None):
165166
logging.info(' Building visibility matrices M and j')
166167

167168
# Deproject the visibilities
168-
#u, v, k, V = self._geometry.apply_correction(u, v, V, use3D=True)
169+
if self.geometry_on:
170+
u, v, k, V = self._geometry.apply_correction(u, v, V, use3D=True)
169171
q = np.hypot(u, v)
170172

171173
# Check consistency of the uv points with the model
@@ -179,7 +181,7 @@ def map_visibilities(self, u, v, V, weights, frequencies=None, geometry=None):
179181
if frequencies is None:
180182
multi_freq = False
181183
frequencies = np.ones_like(V)
182-
184+
start_time = time.time()
183185
channels = np.unique(frequencies)
184186
Ms = np.zeros([len(channels), self.size, self.size], dtype='c8')
185187
js = np.zeros([len(channels), self.size], dtype='c8')
@@ -209,15 +211,34 @@ def map_visibilities(self, u, v, V, weights, frequencies=None, geometry=None):
209211
Vs = Vi[start:end]
210212

211213
X = self._get_mapping_coefficients(qs, ks, us, vs)
212-
X_CT = self._get_mapping_coefficients(qs, ks, us, vs, inverse=True)
213-
wXT = np.matmul(X_CT, np.diag(ws)) # this line is the same as below.
214-
#wXT = np.matmul(np.transpose(np.conjugate(X)), np.diag(ws), dtype = "complex64")
215-
Ms[i] += np.matmul(wXT, X, dtype="complex128")
216-
js[i] += np.matmul(wXT, Vs, dtype="complex128")
214+
wXT = np.matmul(np.transpose(np.conjugate(X)), np.diag(ws), dtype = "complex128")
215+
Ms[i] += np.matmul(wXT, X, dtype="complex128").real
216+
js[i] += np.matmul(wXT, Vs, dtype="complex128").real
217217

218218
start = end
219219
end = min(Ndata, end + Nstep)
220-
220+
221+
import matplotlib.pyplot as plt
222+
223+
224+
N = int(np.sqrt(self._DFT.size))
225+
r"""FRANK 2D: TESTING M
226+
sparcity = ((np.sum(np.abs(Ms[0]) < 0.5e-17))/N**4)*100
227+
print("M is sparse? ", sparcity)
228+
print(Ms[0])
229+
230+
plt.imshow(Ms[0].real, cmap="magma", vmax = np.max(Ms[0].real), vmin = np.mean(Ms[0].real))
231+
plt.colorbar()
232+
plt.show()
233+
234+
M = np.diag(np.diag(Ms[0].real))
235+
num_zeros = ((np.sum(np.abs(M) == 0.0))/N**4)*100
236+
print("M is sparse? ", num_zeros)
237+
238+
IFT2 = np.linalg.solve(M, js[0]).real
239+
plt.imshow(IFT2.reshape(N,N).T, cmap="magma")
240+
plt.colorbar()
241+
221242
print("M type", Ms[0].dtype)
222243
print("j type", js[0].dtype)
223244
print("M imag-> ", " max: ", np.max(Ms[0].imag), ", min: ", np.min(Ms[0].imag) , ", mean: ", np.mean(Ms[0].imag) ,", median: ", np.median(Ms[0].imag), ", std: ", np.std(Ms[0].imag))
@@ -228,19 +249,22 @@ def map_visibilities(self, u, v, V, weights, frequencies=None, geometry=None):
228249
# from scipy.linalg import issymmetric
229250
# print(issymmetric(Ms[0]), "that M is a Symmetric Matrix")
230251
231-
232-
233252
import matplotlib.pyplot as plt
234253
plt.matshow(Ms[0].real, cmap="magma", vmax = np.max(Ms[0].real), vmin = np.mean(Ms[0].real))
235254
plt.colorbar()
236255
plt.title("M matrix, real part")
237256
plt.show()
238257
#import sys
239258
#sys.exit()
240-
259+
"""
241260

242261
#Ms[0] = np.loadtxt(r'.\..\Notebooks\M_N75.txt', dtype = 'c8')
243262
#js[0] = np.loadtxt(r'.\..\Notebooks\j_N75.txt', dtype = 'c8')
263+
print("--- %s minutes to calculate M and j ---" % (time.time()/60 - start_time/60))
264+
path = r'/Users/mariajmelladot/Desktop/Frank2D/1_Frank2D_DEV/data/TestingComplexity/'
265+
np.save(path + 'M_N' + str(N) , Ms[0].real)
266+
np.save(path + 'j_N' + str(N) , js[0].real)
267+
244268

245269
# Compute likelihood normalization H_0, i.e., the
246270
# log-likelihood of a source with I=0.
@@ -288,10 +312,10 @@ def check_hash(self, hash, multi_freq=False, geometry=None):
288312
self._DFT.Rmax == hash[1].Rmax and
289313
self._DFT.size == hash[1].size and
290314
self._DFT.order == hash[1].order and
291-
geometry.inc == hash[2].inc and
292-
geometry.PA == hash[2].PA and
293-
geometry.dRA == hash[2].dRA and
294-
geometry.dDec == hash[2].dDec and
315+
#geometry.inc == hash[2].inc and
316+
#geometry.PA == hash[2].PA and
317+
#geometry.dRA == hash[2].dRA and
318+
#geometry.dDec == hash[2].dDec and
295319
self._vis_model == hash[3]
296320
)
297321

@@ -496,8 +520,11 @@ def _get_mapping_coefficients(self, qs, ks, u, v, geometry=None, inverse=False):
496520
if self._vis_model == 'opt_thick':
497521
# Optically thick & geometrically thin
498522
if geometry is None:
499-
geometry = self._geometry
500-
scale = np.cos(geometry.inc * deg_to_rad)
523+
if not self.geometry_on:
524+
scale = 1
525+
else:
526+
geometry = self._geometry
527+
scale = np.cos(geometry.inc * deg_to_rad)
501528
elif self._vis_model == 'opt_thin':
502529
# Optically thin & geometrically thin
503530
scale = 1
@@ -746,7 +773,6 @@ def __init__(self, DHT, M, j, p=None, scale=None, guess=None,
746773
" New GP "
747774
self.u, self.v = self._DFT.uv_points
748775
self.Ykm = self._DFT.coefficients(direction="backward")
749-
self.Ykm_f = self._DFT.coefficients(direction="forward")
750776

751777
m, c , l = -5, 60, 1e4
752778
#m, c, l = 0.23651345032212925, 60.28747193555951, 1.000389e+05
@@ -758,10 +784,29 @@ def __init__(self, DHT, M, j, p=None, scale=None, guess=None,
758784
S_real_inv = np.linalg.inv(S_real)
759785
print("--- %s minutes to calculate S_real_inv---" % (time.time()/60 - start_time/60))
760786
self._Sinv = S_real_inv
761-
print(self._Sinv.dtype, " Sinv dtype")
762787
start_time = time.time()
763788
self._fit()
764789
print("--- %s minutes to fit---" % (time.time()/60 - start_time/60))
790+
791+
def calculate_S_real(self, u, v, l, m, c):
792+
start_time = time.time()
793+
S_fspace = self.true_squared_exponential_kernel(u, v, l, m, c)
794+
print("--- %s minutes to calculate S---" % (time.time()/60 - start_time/60))
795+
start_time = time.time()
796+
S_real = np.matmul(self.Ykm, np.matmul(S_fspace, self.Ykm.conj()), dtype = "complex128").real
797+
print("--- %s minutes to calculate S_real---" % (time.time()/60 - start_time/60))
798+
799+
"""
800+
#FRANK 2D: TESTING S_real
801+
print(" S_real")
802+
import matplotlib.pyplot as plt
803+
plt.matshow(S_real, cmap="magma")
804+
plt.colorbar()
805+
plt.title("S matrix, real part ")
806+
plt.show()
807+
"""
808+
809+
return S_real
765810

766811
def true_squared_exponential_kernel(self, u, v, l, m, c):
767812
u1, u2 = np.meshgrid(u, u)
@@ -784,23 +829,6 @@ def power_spectrum(q, m, c):
784829
SE_Kernel = np.sqrt(p1 * p2) * np.exp(-0.5*((u1-u2)**2 + (v1-v2)**2)/ l**2)
785830
return SE_Kernel
786831

787-
def calculate_S_real(self, u, v, l, m, c):
788-
start_time = time.time()
789-
S_fspace = self.true_squared_exponential_kernel(u, v, l, m, c)
790-
print("--- %s minutes to calculate S---" % (time.time()/60 - start_time/60))
791-
start_time = time.time()
792-
S_real = np.matmul(self.Ykm, np.matmul(S_fspace, self.Ykm_f), dtype = "complex64")
793-
print("--- %s minutes to calculate S_real---" % (time.time()/60 - start_time/60))
794-
795-
print(S_real.dtype, " S_real dtype")
796-
import matplotlib.pyplot as plt
797-
plt.matshow(S_fspace, cmap="magma", vmin = 0, vmax = 1e-3)
798-
plt.colorbar()
799-
plt.title("S real matrix, real part ")
800-
plt.show()
801-
802-
return S_real
803-
804832
def calculate_mu_cholesky(self, Dinv):
805833
print("calculate mu with cholesky")
806834
try:
@@ -889,7 +917,7 @@ def _fit(self):
889917

890918
Dinv = self._M + Sinv
891919

892-
"""
920+
r""" FRANK 2D: TESTING Dinv
893921
#import scipy.linalg as sc
894922
def is_pos_def(x):
895923
return np.all(np.linalg.eigvals(x) > 0)

0 commit comments

Comments
 (0)