Пример #1
0
    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
Пример #2
0
    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)
Пример #3
0
    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()
Пример #4
0
 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)
Пример #5
0
    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')