-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathoptics_analyze.py
192 lines (148 loc) · 5.23 KB
/
optics_analyze.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
"""
Miscellaneous functions used to analyze
and modify optical results.
Grace E. Chesmore
May 2021
"""
import numpy as np
# Phase unwrapping
def twodunwrapx(array):
phase_offset = np.arange(-1000, 1000) * 2 * np.pi
end_i = np.shape(array)[0] - 1
end_j = np.shape(array)[1] - 1
i = int(end_i / 2)
while i < end_i:
j = int(end_j / 2)
while j < (np.shape(array))[1] - 1:
current_val = [array[i, j]]
next_val = array[i, j + 1] + phase_offset
diff = np.abs(next_val - current_val)
best = np.where(diff == np.min(diff))
array[i, j + 1] = next_val[best][0]
j += 1
i += 1
i = int(end_i / 2)
while i > 0:
j = int(end_j / 2)
while j > 0:
current_val = [array[i, j]]
next_val = array[i, j - 1] + phase_offset
diff = np.abs(next_val - current_val)
best = np.where(diff == np.min(diff))
array[i, j - 1] = next_val[best][0]
j -= 1
i -= 1
i = int(end_i / 2)
while i < end_i - 1:
j = int(end_j / 2)
while j > 0:
current_val = [array[i, j]]
next_val = array[i, j - 1] + phase_offset
diff = np.abs(next_val - current_val)
best = np.where(diff == np.min(diff))
array[i, j - 1] = next_val[best][0]
j -= 1
i += 1
i = int(end_i / 2)
while i > 0:
j = int(end_j / 2)
while j < end_j - 1:
current_val = [array[i, j]]
next_val = array[i, j + 1] + phase_offset
diff = np.abs(next_val - current_val)
best = np.where(diff == np.min(diff))
array[i, j + 1] = next_val[best][0]
j += 1
i -= 1
return array
# Unwraps the phase two times. The first time the phase is
# transposed and unwrapped, then it is transposed again
# (returned to normal state) and unwrapped.
def twodunwrap(array):
xunwraped = twodunwrapx(np.transpose(array))
unwrapped = twodunwrapx(np.transpose(xunwraped))
return unwrapped
# Unwraps the phase (calling on other unwrap functions) and
# normalizes to the center of the phase measurement.
def do_unwrap(phi):
unwraped_phi = twodunwrap(phi)
# print(unwraped_phi[int(len(unwraped_phi)/2),int(len(unwraped_phi)/2)])
# unwraped_phi = unwraped_phi - unwraped_phi[0,0]
unwraped_phi = (
unwraped_phi
- unwraped_phi[int(len(unwraped_phi) / 2), int(len(unwraped_phi) / 2)]
)
return unwraped_phi
# Rotate coordinates in azimuth and elevation.
def rotate_azel(xyz, az, el):
out = np.zeros(np.shape(xyz))
x = xyz[0]
y = xyz[1]
z = xyz[2]
# Rotate in elevation (note we assume z is along the elevation direction)
xt = np.cos(el) * x + np.sin(el) * z
yt = y
zt = (-1.0) * np.sin(el) * x + np.cos(el) * z
# Rotate in azimuth
out[0] = xt
out[1] = np.cos(az) * yt + np.sin(az) * zt
out[2] = (-1.0) * np.sin(az) * yt + np.cos(az) * zt
return out
# Given two arrays, calculate the 2D power spectrum
# for a given ell range, pixel size, and pixel number.
def calculate_2d_spectrum(Map1, Map2, delta_ell, ell_max, pix_size, N):
"calcualtes the power spectrum of a 2d map by FFTing, squaring, and azimuthally averaging"
N = int(N)
# Make a 2d ell coordinate system
ones = np.ones(N)
inds = (np.arange(N) + 0.5 - N / 2.0) / (N - 1.0)
kY = np.outer(ones, inds) / (pix_size / 60.0 * np.pi / 180.0)
kX = np.transpose(kY)
K = np.sqrt(kX ** 2.0 + kY ** 2.0)
ell_scale_factor = 2.0 * np.pi
ell2d = K * ell_scale_factor
# Make an array to hold the power spectrum results
N_bins = int(ell_max / delta_ell)
ell_array = np.arange(N_bins)
CL_array = np.zeros(N_bins)
input_maps = (np.conj(Map1) * Map1) / np.sum(abs(np.conj(Map1) * Map1))
# 2d fourier transform of the map
FMap1 = np.fft.fft2(np.fft.fftshift(input_maps))
FMap2 = np.fft.fft2(np.fft.fftshift(input_maps))
PSMap = np.fft.fftshift(np.real(np.conj(FMap1) * FMap2))
# Fill out the spectra
i = 0
while i < N_bins:
ell_array[i] = (i + 0.5) * delta_ell
inds_in_bin = (
(ell2d >= (i * delta_ell)) * (ell2d < ((i + 1) * delta_ell))
).nonzero()
CL_array[i] = np.mean(PSMap[inds_in_bin])
i = i + 1
# Return the power spectrum and ell bins
return (ell_array, CL_array)
# Elevation offset of holography measurements
def el_offset(x):
slope = (-0.0204345 - 0.00719988) / (400)
return x * slope
# Azimuth offset of holography measurements
def az_offset(x):
slope = (0.01367175) / (200)
return x * slope
# Shifts for holography measurements
def sh_z(z):
return z * ((0.33 + 0.33) / 1200)
def sh_x(z):
return z * ((0.36 + 0.36) / 1200)
# Ruze equation quantifying gain loss due
# to surface defects on antenna.
def ruze(eps, lam):
return np.exp(-2 * (4 * np.pi * eps / lam) ** 2)
# Computes the RMS of z for a given area(x,y)
def rms(x, y, z):
aperture_r = 2.75 # apodized beam radius [m]
rr = np.where(
((x - np.mean(x)) ** 2 + (y - np.mean(y)) ** 2) <= aperture_r ** 2
) # throw out outliers
z_rms = z[rr]
return np.sqrt(np.sum(z_rms ** 2) / len(z_rms))