def plot_dA(zmin=15, zmax=35, nz=100): das = np.zeros(nz) zs = np.linspace(zmin, zmax, nz) for i, z in enumerate(zs): das[i] = cf.val_dA(z) / Mpc_in_cm # Mpc comoving #kmin = 2.*np.pi/(dA*sint/Mpc_in_cm) # 1/Mpc comoving #kmax = kmin * DeltaL_cm / lambda_z # 1/Mpc comoving plt.plot(zs, das, lw=3)
def plot_dA(zmin=15,zmax=35,nz=100): das = np.zeros(nz) zs = np.linspace(zmin,zmax,nz) for i,z in enumerate(zs): das[i] = cf.val_dA( z )/Mpc_in_cm # Mpc comoving #kmin = 2.*np.pi/(dA*sint/Mpc_in_cm) # 1/Mpc comoving #kmax = kmin * DeltaL_cm / lambda_z # 1/Mpc comoving plt.plot(zs,das,lw=3)
def nest_integrator(neval=100, Nz=20, DeltaL_km=2., kminmin=0.0001, kmaxmax=10., zmax=35, zmin=10, Omega_survey=1., Omega_patch=1., thetan=np.pi / 2., phin=0.): """Alternative integrator for B0 and xi sensitivity; NOTE: does not return the same units output as rand_integrator. """ DeltaL_cm = DeltaL_km * 1e5 zs = np.linspace(zmin, zmax, Nz) thetas = np.linspace(0., np.pi, neval) phis = np.linspace(0., 2. * np.pi, neval) ks = np.zeros(neval) samplesz = np.zeros(Nz) samplesp = np.zeros(neval) samplest = np.zeros(neval) samplesk = np.zeros(neval) for i, z in enumerate(zs): print(z) dA = cf.val_dA(z) lambda_z = lambda21 * (1. + z) for j, phik in enumerate(phis): for l, thetak in enumerate(thetas): thetak_n = np.arccos( np.sin(thetak) * np.cos(phik) * np.sin(thetan) * np.cos(phin) + np.sin(thetak) * np.sin(phik) * np.sin(thetan) * np.sin(phin) + np.cos(thetak) * np.cos(thetan)) sint = np.sin(thetak_n) kmin = 2. * np.pi / (dA * sint / Mpc_in_cm) # 1/Mpc comoving kmax = kmin * DeltaL_cm / lambda_z # 1/Mpc comoving ks = np.linspace(kmin, kmax, neval) kVol = kmax - kmin samplesk = np.zeros(neval) for m, k in enumerate(ks): x = np.array([z, k, thetak, phik]) samplesk[m] = integrand(x, DeltaL_km=DeltaL_km, Omega_patch=Omega_patch) samplest[l] = samplesk.mean() * kVol tVol = np.pi samplesp[j] = samplest.mean() * tVol pVol = 2. * np.pi samplesz[i] = samplesp.mean() * pVol zVol = zmax - zmin res = samplesz.mean() * zVol alpha_survey = (Omega_survey)**0.5 result_all_survey = res / Omega_patch * np.pi * ( alpha_survey + np.cos(alpha_survey) * np.sin(alpha_survey)) result = 1. / result_all_survey**0.5 return result
def calc_SNR(zmin=15, zmax=25, t_yr=1., DeltaL_km=1., kminmin=0.01, kmaxmax=1., neval=100, neval_PBi=5000, Omega_survey=1., thetan=np.pi / 2., phin=0., debug=False, plotter_calling=False): """This is a master function for calculating SNR for detecting amplitude A0^2[Gauss^2] = 1/SNR at 1 sigma. This function only works for FFTT setup. It takes the stuff described below, returns sigma_A0 in Gauss. :param zmin: The minimum inegration redshift :type zmin: ``float`` :param zmax: The maximum inegration redshift :type zmax: ``float`` :param DeltaL_km: The size of the FFTT coverage on a side in kilometers. :type DeltaL_km: ``float`` :param kminmin: The minimum wavenumber k considered, in 1/Mpc comoving; not the same as the integration limit kmin. :type kminmin: ``float`` :param kmaxmax: The maximum wavenumber k considered, in 1/Mpc comoving; not the same as the integration limit kmax. :type kmaxmax: ``float`` :param neval: The number of evaluations of the integrand, in z direction; neval = 100 is usually enough for convergence at a ~50% level. :type neval: ``int`` :param neval_PBi: The number of evaluations of the integrand for the calculation of PBi, in k, theta, phi directions; neval_PBi = 500 is usually enough for convergence at a ~10% level. :type neval_PBi: ``int`` :param Omega_survey: The survey area (on the sky) in steradians. :type Omega_survey: ``float`` :params thetan,phin: These define direction of the LOS in the frame where mag. field vector B is along the z axis. Do not change these unless you know exactly what you're getting into. :type thetan,phin: ``float`` """ if plotter_calling: zs = np.linspace(zmin, zmax, neval) else: zs = np.random.random(size=neval) * (zmax - zmin) + zmin samples = np.zeros(neval) for i, z in enumerate(zs): PBi = calc_PBi(z, neval=neval_PBi, t_yr=t_yr, DeltaL_km=DeltaL_km, Omega_survey=Omega_survey, kminmin=kminmin, kmaxmax=kmaxmax, thetan=thetan, phin=phin) dA = cf.val_dA(z) # cm H_z = cf.H(z) dV = Vpatch_factor(z, dA=dA, H_z=H_z, Omega_patch=Omega_survey) lambda_z = lambda21 * (1. + z) * 1e-5 #converting lambda to km samples[i] = dV / PBi**2 * (1. - (lambda_z / DeltaL_km)**3) / ( 2. * np.pi / (dA / Mpc_in_cm))**3 #* (1 + z)**8 if debug: print(z, samples[i], lambda_z, (1. - (DeltaL_km / lambda_z)**3)) if plotter_calling: return zs, 1 / (1. / (10. * np.pi**2) * samples)**0.25 / np.pi res = 1. / (10. * np.pi**2) * samples.mean() * (zmax - zmin ) #check coefficients? return 1. / res**0.25
def integrand_PBi(x, t_yr=1., Omega_survey=1., DeltaL_km=2., val_nk=FFTT_nk, val_Ts=rf.Ts_21cmfast_interp, val_Tk=rf.Tk_21cmfast_interp, val_Jlya=rf.Jlya_21cmfast_interp, val_x1s=rf.ones_x1s, val_Tsys=Tsys_Mao2008, val_Tg=rf.Tg_21cmfast_interp, phin=0., thetan=np.pi / 2., debug=False): """Calculates value of the integrand for noise per component of a stochastic mag. field vector B (eq 51 of detectability notes). This is called by :func:`calc_SNR` that integrates it over k, theta, phi. :param x: Array of the following form: x = z, k_Mpc, thetak, phik :type x: ``array`` :param t_yr: The total observation time in years. The time spent on a single field of view (=1sr for FFTT) is t_yr / Omega_survey. ??? :type t_yr: ``float`` :param DeltaL_km: The size of the FFTT coverage on a side in kilometers. :type DeltaL_km: ``float`` :param Omega_survey: The survey area (on the sky) in steradians. :type Omega_survey: ``float`` :params thetan,phin: These define direction of the LOS in the frame where mag. field vector B is along the z axis. Do not change these unless you know exactly what you're getting into. :type thetan,phin: ``float`` :params val_*: Helper functions, like the calulators for various temperatures etc. :type val_*: ``function`` """ z = x[0] k_Mpc = x[1] thetak = x[2] phik = x[3] thetak_n = np.arccos( np.sin(thetak) * np.cos(phik) * np.sin(thetan) * np.cos(phin) + np.sin(thetak) * np.sin(phik) * np.sin(thetan) * np.sin(phin) + np.cos(thetak) * np.cos(thetan)) sint = np.sin(thetak_n) if np.isclose(sint, 0.): if debug: return 0, 0, 0 return 0. DeltaL_cm = DeltaL_km * 1e5 # cm lambda_z = lambda21 * (1. + z) # cm dA = cf.val_dA(z) # cm kmin = 2. * np.pi / (dA * sint / Mpc_in_cm) # 1/Mpc comoving kmax = kmin * DeltaL_cm / lambda_z # 1/Mpc comoving if k_Mpc > kmax or k_Mpc < kmin: if debug: return 0, 0, 0 return 0. t_sec = 365. * 86400 * t_yr # sec k_cm = k_Mpc / Mpc_in_cm # cm N_ants = (DeltaL_cm / lambda_z)**2 Ntot = N_ants * (N_ants + 1.) / 2. nk = val_nk(k_cm, Ntot=Ntot, lambda_z=lambda_z, dA=dA, sin_thetak_n=sint, Lmax=DeltaL_cm, Lmin=lambda_z, DeltaL=DeltaL_cm) t1 = t_sec if Omega_survey > 1.: t1 = t_sec / Omega_survey H_z = cf.H(z) Tsys = val_Tsys(z) Ts = val_Ts(z) Tg = val_Tg(z) Tk = val_Tk(z) Jlya = val_Jlya(z) Salpha = cf.val_Salpha(Ts, Tk, z, 1., 0) xalpha = rf.val_xalpha(Salpha=Salpha, Jlya=Jlya, Tg=Tg) xc = rf.val_xc(z, Tk=Tk, Tg=Tg) xBcoeff = ge * muB * Tstar / (2. * hbar * A * Tg) Pnoise = P21_N(dA=dA, H_z=H_z, z=z, Tsys=Tsys, t1=t1, Ae=lambda_z**2, Lmax=DeltaL_cm, Lmin=lambda_z, lambda_z=lambda_z, nk=nk) if np.isnan(Pnoise): raise ValueError('Pnoise is nan.') Pdelta = cf.val_Pdelta(z, k_Mpc) G = pt.calc_G(thetak=thetak, phik=phik, thetan=thetan, phin=phin, Ts=Ts, Tg=Tg, z=z, verbose=False, xalpha=xalpha, xc=xc, xB=0., x1s=1.) dGdB = pt.calc_dGdB(thetak=thetak, phik=phik, thetan=thetan, phin=phin, Ts=Ts, Tg=Tg, z=z, verbose=False, xalpha=xalpha, xc=xc, xBcoeff=xBcoeff, x1s=1.) Psignal = Pdelta * G**2 Numerator = (2. * G * dGdB * (1. + z)**2 * Pdelta)**2 Denominator = 2. * (2. * np.pi)**3 * ( Psignal + Pnoise)**2 ###is 2pi factor right? check! res = k_Mpc**2 * np.sin(thetak) * Numerator / Denominator if debug: return res, Pnoise, nk, Numerator, G, dGdB return res
def integrand(x, mode='B0', t_yr=1., Omega_patch=1., DeltaL_km=2., val_nk=FFTT_nk, val_Ts=rf.Ts_21cmfast_interp, val_Tk=rf.Tk_21cmfast_interp, val_Jlya=rf.Jlya_21cmfast_interp, val_x1s=rf.ones_x1s, val_Tsys=Tsys_Mao2008, val_Tg=rf.Tg_21cmfast_interp, phin=0., thetan=np.pi / 2., print_klims=False, debug=False): """Calculates value of the integrand for sensitivity to uniform mag. field vector B (eqs 37,40 of detectability_notes). This is called by :func:`rand_integrator` that integrates it over z, k, theta, phi. :param x: Array of the following form: x = z, k_Mpc, thetak, phik :type x: ``array`` :param t_yr: The total observation time in years. The time spent on a single field of view (=1sr for FFTT) is t_yr / Omega_survey. ??? :type t_yr: ``float`` :param mode: The mode of calculation; if mode == 'B0', returns sensitivity to measuring uniform mag. field B0 if mode == 'xi', returns 1 sigma sensitivity to distinguishing saturated from unsaturated case, where xi is unitless and between 0 and 1. :type mode: ``str`` :param DeltaL_km: The size of the FFTT coverage on a side in kilometers. :type DeltaL_km: ``float`` :param Omega_patch: The area of a small (approx. flat, < 1sr) patch the sky in steradians. :type Omega_patch: ``float`` :params thetan,phin: These define direction of the LOS in the frame where mag. field vector B is along the z axis. Do not change these unless you know exactly what you're getting into. :type thetan,phin: ``float`` :params val_*: Helper functions, like the calulators for various temperatures etc. :type val_*: ``function`` """ z = x[0] k_Mpc = x[1] thetak = x[2] phik = x[3] thetak_n = np.arccos( np.sin(thetak) * np.cos(phik) * np.sin(thetan) * np.cos(phin) + np.sin(thetak) * np.sin(phik) * np.sin(thetan) * np.sin(phin) + np.cos(thetak) * np.cos(thetan)) sint = np.sin(thetak_n) if np.isclose(sint, 0.): if debug: return 0, 0, 0 return 0. DeltaL_cm = DeltaL_km * 1e5 # cm lambda_z = lambda21 * (1. + z) # cm dA = cf.val_dA(z) # cm comov. kmin = 2. * np.pi / (dA * sint / Mpc_in_cm) # 1/Mpc comoving kmax = kmin * DeltaL_cm / lambda_z # 1/Mpc comoving if print_klims: print('kmax={}, kmin={}'.format(kmax, kmin)) if k_Mpc > kmax or k_Mpc < kmin: if debug: return 0, 0, 0 return 0. t_sec = 365. * 86400 * t_yr # sec k_cm = k_Mpc / Mpc_in_cm # cm N_ants = (DeltaL_cm / lambda_z)**2 Ntot = N_ants * (N_ants + 1.) / 2. nk = val_nk(k_cm, Ntot=Ntot, lambda_z=lambda_z, dA=dA, sin_thetak_n=sint, Lmax=DeltaL_cm, Lmin=lambda_z, DeltaL=DeltaL_cm) t1 = t_sec if Omega_patch > 1.: t1 = t_sec / Omega_patch H_z = cf.H(z) Tsys = val_Tsys(z) Ts = val_Ts(z) Tg = val_Tg(z) Tk = val_Tk(z) Jlya = val_Jlya(z) Salpha = cf.val_Salpha(Ts, Tk, z, 1., 0) xalpha = rf.val_xalpha(Salpha=Salpha, Jlya=Jlya, Tg=Tg) xc = rf.val_xc(z, Tk=Tk, Tg=Tg) xBcoeff = ge * muB * Tstar / (2. * hbar * A * Tg) Vpatch = Vpatch_factor(z, dA=dA, H_z=H_z, Omega_patch=Omega_patch) Pnoise = P21_N(dA=dA, H_z=H_z, z=z, Tsys=Tsys, t1=t1, Ae=lambda_z**2, Lmax=DeltaL_cm, Lmin=lambda_z, lambda_z=lambda_z, nk=nk) if np.isnan(Pnoise): raise ValueError('Pnoise is nan.') Pdelta = cf.val_Pdelta(z, k_Mpc) if mode == 'B0': G = pt.calc_G(thetak=thetak, phik=phik, thetan=thetan, phin=phin, Ts=Ts, Tg=Tg, z=z, verbose=False, xalpha=xalpha, xc=xc, xB=0., x1s=1.) dGdB = pt.calc_dGdB(thetak=thetak, phik=phik, thetan=thetan, phin=phin, Ts=Ts, Tg=Tg, z=z, verbose=False, xalpha=xalpha, xc=xc, xBcoeff=xBcoeff, x1s=1.) Psignal = Pdelta * G**2 Numerator = (2. * G * dGdB * (1 + z)**2 * Pdelta)**2 Denominator = (Psignal + Pnoise)**2 res = k_Mpc**2 * np.sin(thetak) * Vpatch * Numerator / Denominator / ( 2. * np.pi)**3 if mode == 'xi': G_Bzero = pt.calc_G(thetak=thetak, phik=phik, thetan=thetan, phin=phin, Ts=Ts, Tg=Tg, z=z, verbose=False, xalpha=xalpha, xc=xc, x1s=1., xB=0.) G_Binfinity = pt.calc_G_Binfinity(thetak=thetak, phik=phik, thetan=thetan, phin=phin, Ts=Ts, Tg=Tg, z=z, verbose=False, xalpha=xalpha, xc=xc, x1s=1.) Psignal_Bzero = Pdelta * G_Bzero**2 Psignal_Binfinity = Pdelta * G_Binfinity**2 Numerator = (Psignal_Binfinity - Psignal_Bzero)**2 Denominator = 2. * (Psignal_Bzero + Pnoise)**2 res = k_Mpc**2 * np.sin(thetak) * Vpatch * Numerator / Denominator / ( 2. * np.pi)**3 if mode == 'Bi': G = pt.calc_G(thetak=thetak, phik=phik, thetan=thetan, phin=phin, Ts=Ts, Tg=Tg, z=z, verbose=False, xalpha=xalpha, xc=xc, xB=0., x1s=1.) dGdB = pt.calc_dGdB(thetak=thetak, phik=phik, thetan=thetan, phin=phin, Ts=Ts, Tg=Tg, z=z, verbose=False, xalpha=xalpha, xc=xc, xBcoeff=xBcoeff, x1s=1.) #/ (1.+z)**2 #!!! VG: check Psignal = Pdelta * G**2 Numerator = (2. * G * dGdB * (1 + z)**2 * Pdelta)**2 Denominator = 2. * (Psignal + Pnoise)**2 res = k_Mpc**2 * np.sin(thetak) * Numerator / Denominator if debug: dGdB, summ, xs = pt.calc_dGdB(thetak=thetak, phik=phik, thetan=thetan, phin=phin, Ts=Ts, Tg=Tg, z=z, verbose=False, xalpha=xalpha, xc=xc, xBcoeff=xBcoeff, x1s=1., debug=True) return res, Numerator, Denominator, Psignal, Pnoise, G, dGdB, Pdelta, Ts, Tg, summ, xs return res