def __init__(self, model='vol_co', z_max=2.0, H_0=67.74, W_m=0.3089, W_v=0.6911, alpha=-1.5): """Draw from particular number density distributions. Args: model (str): Which number density model to follow. z_max (float): Maximum redshift. H_0 (float): Hubble constant. W_m (float): Density parameter Ω_m. W_v (float): Cosmological constant Ω_Λ. alpha (float, optional): Desired log N log S slope for a perfect, non-cosmological population. """ self.z_max = z_max # Convert various maximum distance values self.dt = pc.DistanceTable(H_0=H_0, W_m=W_m, W_v=W_v).lookup m = self.dt(z=np.array([z_max])) self.dist_co_max = m[1] self.vol_co_max = m[2] self.cdf_sfr_max = m[-2] self.cdf_smd_max = m[-1] self.dist_co_max = self.dist_co_max[0] self.vol_co_max = self.vol_co_max[0] self.alpha = alpha # Determine from which type of distribution to draw if model == 'vol_co': self.draw = self.from_vol_co elif model == 'sfr': self.draw = self.from_sfr elif model == 'smd': self.draw = self.from_smd # Allow for the steepness of log N log S to be adapted if alpha != -1.5: self.draw = self.sloped_dist self.power = -self.alpha/1.5 self.maxi = self.vol_co_max**self.power
def gen_dist(self): """Generate distances.""" # Cosmology calculations r = go.Redshift(self.z_max, H_0=self.H_0, W_m=self.W_m, W_v=self.W_v) self.dist_co_max = r.dist_co() self.vol_co_max = r.vol_co() # Ensure precalculations are done if necessary pc.DistanceTable(H_0=self.H_0, W_m=self.W_m, W_v=self.W_v) # Set up number density n_den = NumberDensity(model=self.n_model, z_max=self.z_max, alpha=self.alpha, H_0=self.H_0, W_m=self.W_m, W_v=self.W_v).draw frbs = self.frbs # Draw from number density frbs.z, frbs.dist_co = n_den(self.n_gen)
plt.ylabel(r'$\text{d}n_{\text{FRB}}/\text{d}z$') plt.yscale('log') plt.legend() plt.tight_layout() plt.savefig(rel_path('plots/number_frbs.pdf')) plt.clf() if DENSITY_FRBS: plot_aa_style() fig = plt.figure() ax = fig.add_subplot(111) # Get dV import frbpoppy.precalc as pc d = pc.DistanceTable().lookup(z=bincentres) dvols = d[3] dens = {} i = 0 for s in pop_types: dens[s] = ns[s] / dvols title = titles[i] plt.step(bincentres, dens[s] / dens[s][0], where='mid', label=title) i += 1 plt.xlabel('$z$') plt.ylabel(r'$\rho_{\text{FRB}} / \rho_{\text{FRB}}(0)$') plt.yscale('log') plt.legend() plt.tight_layout()
def gen_precalc(self): """Check whether pre-calculations have been run.""" pc.DistanceTable(H_0=self.H_0, W_m=self.W_m, W_v=self.W_v)
def __init__(self, n_gen, days=1, name='cosmic', H_0=67.74, W_m=0.3089, W_v=0.6911, dm_host_model='normal', dm_host_mu=100, dm_host_sigma=200, dm_igm_index=1000, dm_igm_sigma=None, dm_mw_model='ne2001', emission_range=[10e6, 10e9], lum_range=[1e40, 1e45], lum_index=0, n_model='sfr', alpha=-1.5, pulse_model='lognormal', pulse_range=[0.1, 10], pulse_mu=0.1, pulse_sigma=0.5, si_mu=-1.4, si_sigma=1., z_max=2.5): """Generate a popuation of FRBs. Args: n_gen (int): Number of FRB sources/sky/time to generate. days (float): Number of days over which FRBs are generated. name (str): Population name. H_0 (float): Hubble constant. W_m (float): Density parameter Ω_m. W_v (float): Cosmological constant Ω_Λ. dm_host_model (float): Dispersion measure host model. Options are 'normal' or 'lognormal'. dm_host_mu (float): Mean dispersion measure host [pc/cm^3]. dm_host_sigma (float): Deviation dispersion measure host [pc/cm^3]. dm_igm_index (float): Dispersion measure slope for IGM [pc/cm^3]. dm_igm_sigma (float): Scatter around dm_igm. Defaults 0.2*slope*z dm_mw_model (str): Dispersion measure model for the Milky Way. Options are 'ne2001' or 'zero'. emission_range (list): The frequency range [Hz] between which FRB sources should emit the given bolometric luminosity. lum_range (list): Bolometric luminosity (distance) range [erg/s]. lum_index (float): Power law index. n_model (str): Number density model. Either 'vol_co', 'sfr' or 'smd'. alpha (float): Desired logN/logS of perfectly detected population. pulse_model (str): Pulse width model, 'lognormal' or 'uniform'. pulse_range (list): Pulse width range [ms]. pulse_mu (float): Mean pulse width [ms]. pulse_sigma (float): Deviation pulse width [ms]. si_mu (float): Mean spectral index. si_sigma (float): Standard deviation spectral index. z_max (float): Maximum redshift. Returns: Population: Population of FRBs. """ # Set up population Population.__init__(self) self.alpha = alpha self.dm_host_model = dm_host_model self.dm_host_mu = dm_host_mu self.dm_host_sigma = dm_host_sigma self.dm_igm_index = dm_igm_index self.dm_igm_sigma = dm_igm_sigma self.dm_mw_model = dm_mw_model self.f_max = emission_range[1] self.f_min = emission_range[0] self.H_0 = H_0 self.lum_max = lum_range[1] self.lum_min = lum_range[0] self.lum_pow = lum_index self.name = name self.n_gen = n_gen self.n_model = n_model self.si_mu = si_mu self.si_sigma = si_sigma self.time = days * 86400 # Convert to seconds self.w_model = pulse_model self.w_max = pulse_range[1] self.w_min = pulse_range[0] self.w_mu = pulse_mu self.w_sigma = pulse_sigma self.W_m = W_m self.W_v = W_v self.z_max = z_max # Cosmology calculations r = go.Redshift(self.z_max, H_0=self.H_0, W_m=self.W_m, W_v=self.W_v) self.dist_co_max = r.dist_co() self.vol_co_max = r.vol_co() # Ensure precalculations are done if necessary pc.DistanceTable(H_0=self.H_0, W_m=self.W_m, W_v=self.W_v) # Set up number density n_den = NumberDensity(model=self.n_model, z_max=self.z_max, alpha=self.alpha, H_0=self.H_0, W_m=self.W_m, W_v=self.W_v).draw # Let user know what's happening pprint(f'Generating {self.name} population') frbs = self.frbs # Add random directional coordinates frbs.gl = np.random.random(n_gen) * 360.0 - 180 frbs.gb = np.degrees(np.arcsin(np.random.random(n_gen))) frbs.gb[::2] *= -1 # Convert frbs.ra, frbs.dec = go.lb_to_radec(frbs.gl, frbs.gb) # Draw from number density frbs.z, frbs.dist_co = n_den(n_gen) # Get the proper distance dist_pr = frbs.dist_co / (1 + frbs.z) # Convert into galactic coordinates frbs.gx, frbs.gy, frbs.gz = go.lb_to_xyz(frbs.gl, frbs.gb, dist_pr) # Dispersion measure of the Milky Way if self.dm_mw_model == 'ne2001': frbs.dm_mw = pc.NE2001Table().lookup(frbs.gl, frbs.gb) elif self.dm_mw_model == 'zero': frbs.dm_mw = np.zeros_like(frbs.z) # Dispersion measure of the intergalactic medium frbs.dm_igm = go.ioka_dm_igm(frbs.z, slope=self.dm_igm_index, sigma=self.dm_igm_sigma) # Dispersion measure of the host (Tendulkar) if self.dm_host_model == 'normal': frbs.dm_host = dis.trunc_norm(self.dm_host_mu, self.dm_host_sigma, n_gen).astype(np.float64) elif self.dm_host_model == 'lognormal': frbs.dm_host = np.random.lognormal(self.dm_host_mu, self.dm_host_sigma, n_gen).astype(np.float64) frbs.dm_host /= (1 + frbs.z) # Total dispersion measure frbs.dm = frbs.dm_mw + frbs.dm_igm + frbs.dm_host # Get a random intrinsic pulse width [ms] if self.w_model == 'lognormal': frbs.w_int = np.random.lognormal(self.w_mu, self.w_sigma, n_gen) if self.w_model == 'uniform': frbs.w_int = np.random.uniform(self.w_min, self.w_max, n_gen) # Calculate the pulse width upon arrival to Earth frbs.w_arr = frbs.w_int * (1 + frbs.z) # Add bolometric luminosity [erg/s] frbs.lum_bol = dis.powerlaw(self.lum_min, self.lum_max, self.lum_pow, n_gen) # Add spectral index frbs.si = np.random.normal(si_mu, si_sigma, n_gen) pprint('Finished')