-
Notifications
You must be signed in to change notification settings - Fork 2
/
cv_fisher.py
executable file
·351 lines (278 loc) · 11.6 KB
/
cv_fisher.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
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
#!/usr/bin/python
"""
Calculate Fisher matrix and P(k) constraints for all redshift bins for a given
experiment.
"""
import numpy as np
import pylab as P
import scipy.spatial, scipy.integrate, scipy.interpolate
from scipy.integrate import simps
import radiofisher as rf
from radiofisher.units import *
from radiofisher.experiments import USE, foregrounds
from mpi4py import MPI
comm = MPI.COMM_WORLD
myid = comm.Get_rank()
size = comm.Get_size()
################################################################################
# Set-up experiment parameters
################################################################################
# Define cosmology and experiment settings
survey_name = "ExptA"
root = "output/" + survey_name
# Planck 2015 base_plikHM_TTTEEE_lowTEB_post_BAO
cosmo = {
'omega_M_0': 0.3108,
'omega_lambda_0': 0.6892,
'omega_b_0': 0.04883,
'omega_HI_0': 4.86e-4,
'N_eff': 3.046,
'h': 0.6761,
'ns': 0.96708,
'sigma_8': 0.8344,
'w0': -1.,
'wa': 0.,
'mnu': 0.,
'k_piv': 0.05,
'aperp': 1.,
'apar': 1.,
'bHI0': 0.677,
'sigma_nl': 1e-8, #7., # FIXME
'mnu': 0.,
'gamma': 0.55,
'foregrounds': foregrounds,
}
# Experimental setup A
expt = {
'mode': 'idish', # Interferometer or single dish
'Ndish': 32**2, # No. of dishes
'Nbeam': 1, # No. of beams
'Ddish': 10., # Single dish diameter [m]
'Tinst': 10.*(1e3), # Receiver temp. [mK]
'survey_dnutot': 1000., # Total bandwidth of *entire* survey [MHz]
'survey_numax': 1420., # Max. freq. of survey
'dnu': 0.2, # Bandwidth of single channel [MHz]
'Sarea': 2.*np.pi, # Total survey area [radians^2]
'epsilon_fg': 1e-14, # Foreground amplitude
'ttot': 43829.*HRS_MHZ, # Total integration time [MHz^-1]
'nu_line': 1420.406, # Rest-frame freq. of emission line [MHz]
'epsilon_fg': 1e-12, # FG subtraction residual amplitude
'use': USE # Which constraints to use/ignore
}
def baseline_dist(Nx, Ny, Ddish, nu=1420.):
"""
Creates interpolation function for (circularised) baseline density n(d),
assuming a regular grid.
"""
# Generate regular grid
y = np.arange(Ny, step=Ddish)
x, y = np.meshgrid( np.arange(Nx) * Ddish,
np.arange(Ny) * Ddish )
# Calculate baseline separations
d = scipy.spatial.distance.pdist(np.column_stack((x.flatten(),
y.flatten())) ).flatten()
# Calculate FOV and sensible uv-plane bin size
Ndish = Nx * Ny
l = 3e8 / (nu*1e6)
fov = 180. * 1.22 * (l/Ddish) * (np.pi/180.)**2.
du = 1. / np.sqrt(fov) # 1.5 / ...
# Remove D < Ddish baselines
d = d[np.where(d > Ddish)] # Cut sub-FOV baselines
d /= l # Rescale into u = d / lambda
# Calculate bin edges
imax = int(np.max(d) / du) + 1
edges = np.linspace(0., imax * du, imax+1)
edges = np.arange(0., imax * du, 1.)# FIXME
print edges[1] - edges[0]
# Calculate histogram (no. baselines in each ring of width du)
bins, edges = np.histogram(d, edges)
u = np.array([ 0.5*(edges[i+1] + edges[i])
for i in range(edges.size-1) ]) # Centroids
# Convert to a density, n(u)
nn = bins / (2. * np.pi * u * du)
# Integrate n(u) to find norm. (should give 1 if no baseline cuts used)
norm = scipy.integrate.simps(2.*np.pi*nn*u, u)
#print "n(u) renorm. factor:", 0.5 * Ndish * (Ndish - 1) / norm
# Convert to freq.-independent expression, n(x) = n(u) * nu^2,
# where nu is in MHz.
n_x = nn * nu**2.
x = u / nu
# Plot n(u) as a fn. of k_perp
kperp = 2.*np.pi*u / (0.5*(2733 + 1620.)) # @ avg. of z = 0.42, 0.78
P.plot(kperp, n_x / 900.**2., lw=1.8, color='r')
#P.xscale('log')
P.ylabel("$n(u)$", fontsize=18)
P.xlabel(r"$k_\perp$ ${\rm Mpc}^{-1}$", fontsize=18)
P.gca().tick_params(axis='both', which='major', labelsize=20, size=8.,
width=1.5, pad=8.)
P.gca().tick_params(axis='both', which='minor', labelsize=20, size=5.,
width=1.5, pad=8.)
P.tight_layout()
P.show()
exit()
return scipy.interpolate.interp1d(x, n_x, kind='linear',
bounds_error=False, fill_value=0.)
# Set baseline density
expt['n(x)'] = baseline_dist(32, 32, 10.) # Interferometer antenna density
# Define redshift bins
dat = np.genfromtxt("slosar_background_zlow.dat").T
zmin = dat[0]
bias = dat[4]
#zs = np.concatenate((zmin, [zmin[1] - zmin[0],]))
#zc = 0.5 * (zs[:-1] + zs[1:])
# Single bin between 800 - 1000 MHz
zs = np.array([1420./1000. - 1., 1420./800. - 1.])
zc = 0.5 * (zs[:-1] + zs[1:])
# Define kbins (used for output)
kbins = np.arange(0., 5.*cosmo['h'], 0.1*cosmo['h']) # Bins of 0.1 h/Mpc
################################################################################
# Precompute cosmological functions and P(k)
cosmo_fns = rf.background_evolution_splines(cosmo)
# Load P(k) and split into smooth P(k) and BAO wiggle function
k_in, pk_in = np.genfromtxt("slosar_pk_z0.dat").T # Already in non-h^-1 units
cosmo['pk_nobao'], cosmo['fbao'] = rf.spline_pk_nobao(k_in, pk_in)
cosmo['k_in_max'] = np.max(k_in)
cosmo['k_in_min'] = np.min(k_in)
# Switch-off massive neutrinos, fNL, MG etc.
mnu_fn = None
transfer_fn = None
Neff_fn = None
switches = []
H, r, D, f = cosmo_fns
################################################################################
# Compare Anze's functions with the ones we calculate internally
################################################################################
"""
# Distance, r(z) [Mpc]
zz = dat[0]
P.plot(zz, dat[1], 'b-', lw=1.8)
P.plot(zz, (1.+zz)*r(zz), 'y--', lw=1.8)
# Growth (normalised to 1 at z=0)
P.plot(zz, dat[2], 'r-', lw=1.8)
P.plot(zz, D(zz)/D(0.), 'y--', lw=1.8)
# Growth rate, f(z)
P.plot(zz, dat[3], 'g-', lw=1.8)
P.plot(zz, f(zz), 'y--', lw=1.8)
P.show()
exit()
"""
################################################################################
# Loop through redshift bins, assigning them to each process
################################################################################
for i in range(zs.size-1):
if i % size != myid:
continue
print ">>> %2d working on redshift bin %2d -- z = %3.3f" % (myid, i, zc[i])
# Calculate bandwidth
numin = expt['nu_line'] / (1. + zs[i+1])
numax = expt['nu_line'] / (1. + zs[i])
expt['dnutot'] = numax - numin
z = zc[i]
# Pack values and functions into the dictionaries cosmo, expt
HH, rr, DD, ff = cosmo_fns
cosmo['A'] = 1.
cosmo['omega_HI'] = rf.omega_HI(z, cosmo)
cosmo['bHI'] = rf.bias_HI(z, cosmo) # FIXME
cosmo['btot'] = cosmo['bHI']
cosmo['Tb'] = rf.Tb(z, cosmo)
cosmo['z'] = z; cosmo['D'] = DD(z)
cosmo['f'] = ff(z)
cosmo['r'] = rr(z); cosmo['rnu'] = C*(1.+z)**2. / HH(z)
cosmo['switches'] = switches
# Physical volume (in rad^2 Mpc^3) (note factor of nu_line in here)
Vphys = expt['Sarea'] * (expt['dnutot']/expt['nu_line']) \
* cosmo['r']**2. * cosmo['rnu']
print "Vphys = %3.3e Mpc^3" % Vphys
#---------------------------------------------------------------------------
# Noise power spectrum
#---------------------------------------------------------------------------
# Get grid of (q,y) coordinates
kgrid = np.linspace(1e-4, 5.*cosmo['h'], 500)
KPAR, KPERP = np.meshgrid(kgrid, kgrid)
y = cosmo['rnu'] * KPAR
q = cosmo['r'] * KPERP
# Get noise power spectrum (units ~ mK^2)
cn = rf.Cnoise(q, y, cosmo, expt) * cosmo['r']**2. * cosmo['rnu'] \
* cosmo['h']**3. \
* 0.1**3. # FIXME: Fudge factor to get in
# the same ballpark!
print "%3.3e Mpc^3" % (cosmo['r']**2. * cosmo['rnu'])
# Plot noise power spectrum
fig, ax = P.subplots(1)
ax.set_aspect('equal')
mat = ax.matshow(np.log10(cn).T, origin='lower',
extent=[0., np.max(kgrid)/cosmo['h'],
0., np.max(kgrid)/cosmo['h']],
aspect='auto', vmin=-3.7, vmax=-2.)
# Lines of constant |k|
from matplotlib.patches import Circle
for n in range(1, 6):
ax.add_patch( Circle((0., 0.), n, fc='none', ec='w', alpha=0.5, lw=2.2) )
P.xlabel(r"$k_\perp$ $[h/{\rm Mpc}]$", fontsize=18)
P.ylabel(r"$k_\parallel$ $[h/{\rm Mpc}]$", fontsize=18)
# Colour bar
clr = P.colorbar(mat)
clr.set_label(r"$\log_{10}[P_N(k_\perp, k_\parallel)]$ $[{\rm mK}^2 {\rm Mpc}^3]$", fontsize=18)
# Tweak tick labels
P.gca().tick_params(axis='both', which='major', labelsize=20, size=8.,
width=1.5, pad=8.)
P.gca().tick_params(axis='both', which='minor', labelsize=20, size=5.,
width=1.5, pad=8.)
P.show()
exit()
#---------------------------------------------------------------------------
# Set binning
Nperp = 50
Npar = 45
dk = 0.1 * cosmo['h'] # k bin size
# Loop over bins
dP = np.zeros((Nperp, Npar))
for ii in range(Nperp):
kperp_min = 1e-4 + ii*dk
kperp_max = kperp_min + dk
kperp = np.logspace(np.log10(kperp_min), np.log10(kperp_max), 80)
#kperp = np.linspace(kperp_min, kperp_max, 120)
for jj in range(Npar):
kpar_min = 1e-4 + jj*dk
kpar_max = kpar_min + dk
kpar = np.logspace(np.log10(kpar_min), np.log10(kpar_max), 40)
#kpar = np.linspace(kpar_min, kpar_max, 80)
# Get grid of (q,y) coordinates
KPAR, KPERP = np.meshgrid(kpar, kperp)
y = cosmo['rnu'] * KPAR
q = cosmo['r'] * KPERP
# Calculate integrand
cs = rf.Csignal(q, y, cosmo, expt)
cn = rf.Cnoise(q, y, cosmo, expt)
integrand = KPERP * (cs / (cs + cn))**2.
# Do double integration
Ik = [simps(integrand.T[i], kperp) for i in range(kpar.size)]
dP[ii,jj] = simps(Ik, kpar)
# Rescale deltaP/P
dP *= Vphys / (8. * np.pi**2.)
dP = 1. / np.sqrt(dP)
fig, ax = P.subplots(1)
ax.set_aspect('equal')
mat = ax.matshow(np.log10(dP).T, vmin=-3.7, vmax=-2., origin='lower',
extent=[0., Nperp*0.1, 0., Npar*0.1], aspect='auto')
from matplotlib.patches import Circle
for n in range(1, 6):
ax.add_patch( Circle((0., 0.), n, fc='none', ec='w', alpha=0.5, lw=2.2) )
P.xlabel(r"$k_\perp$ $[h/{\rm Mpc}]$", fontsize=18)
P.ylabel(r"$k_\parallel$ $[h/{\rm Mpc}]$", fontsize=18)
#P.yscale('log')
#P.xscale('log')
clr = P.colorbar(mat)
clr.set_label("$\log_{10}[\sigma_P / P\,(k_\perp, k_\parallel)]$", fontsize=18)
P.gca().tick_params(axis='both', which='major', labelsize=20, size=8.,
width=1.5, pad=8.)
P.gca().tick_params(axis='both', which='minor', labelsize=20, size=5.,
width=1.5, pad=8.)
#P.tight_layout()
P.show()
exit()
# Evaluate at output grid points
#Ikpar(kgrid)
#cumtrapz(Ik, kgrid, initial=0.)
comm.barrier()
if myid == 0: print "Finished."