示例#1
0
    def test_orf(self):
        """Test ORF functions."""
        p1 = np.array([0.3, -0.5, 0.7])
        p2 = np.array([0.9, 0.1, -0.6])

        # test auto terms
        hd = utils.hd_orf(p1, p1)
        hd_exp = 1.0
        dp = utils.dipole_orf(p1, p1)
        dp_exp = 1.0 + 1e-5
        mp = utils.monopole_orf(p1, p1)
        mp_exp = 1.0 + 1e-5

        msg = 'ORF auto term incorrect for {}'
        keys = ['hd', 'dipole', 'monopole']
        vals = [(hd, hd_exp), (dp, dp_exp), (mp, mp_exp)]
        for key, val in zip(keys, vals):
            assert val[0] == val[1], msg.format(key)

        # test off diagonal terms
        hd = utils.hd_orf(p1, p2)
        omc2 = (1 - np.dot(p1, p2)) / 2
        hd_exp = 1.5 * omc2 * np.log(omc2) - 0.25 * omc2 + 0.5
        dp = utils.dipole_orf(p1, p2)
        dp_exp = np.dot(p1, p2)
        mp = utils.monopole_orf(p1, p2)
        mp_exp = 1.0

        msg = 'ORF cross term incorrect for {}'
        keys = ['hd', 'dipole', 'monopole']
        vals = [(hd, hd_exp), (dp, dp_exp), (mp, mp_exp)]
        for key, val in zip(keys, vals):
            assert val[0] == val[1], msg.format(key)
示例#2
0
def common_red_noise_block(psd='powerlaw',
                           prior='log-uniform',
                           Tspan=None,
                           gamma_val=None,
                           orf=None,
                           name='gwb'):
    """
    Returns common red noise model:
        1. Red noise modeled with user defined PSD with
        30 sampling frequencies. Available PSDs are
        ['powerlaw', 'turnover' 'spectrum']
    :param psd:
        PSD to use for common red noise signal. Available options
        are ['powerlaw', 'turnover' 'spectrum']
    :param prior:
        Prior on log10_A. Default if "log-uniform". Use "uniform" for
        upper limits.
    :param Tspan:
        Sets frequency sampling f_i = i / Tspan. Default will
        use overall time span for indivicual pulsar.
    :param gamma_val:
        Value of spectral index for power-law and turnover
        models. By default spectral index is varied of range [0,7]
    :param orf:
        String representing which overlap reduction function to use.
        By default we do not use any spatial correlations. Permitted
        values are ['hd', 'dipole', 'monopole'].
    :param name: Name of common red process
    """

    orfs = {
        'hd': utils.hd_orf(),
        'dipole': utils.dipole_orf(),
        'monopole': utils.monopole_orf()
    }

    # common red noise parameters
    if psd in ['powerlaw', 'turnover']:
        amp_name = '{}_log10_A'.format(name)
        if prior == 'uniform':
            log10_Agw = parameter.LinearExp(-18, -11)(amp_name)
        elif prior == 'log-uniform' and gamma_val is not None:
            if np.abs(gamma_val - 4.33) < 0.1:
                log10_Agw = parameter.Uniform(-18, -14)(amp_name)
            else:
                log10_Agw = parameter.Uniform(-18, -11)(amp_name)
        else:
            log10_Agw = parameter.Uniform(-18, -11)(amp_name)

        gam_name = '{}_gamma'.format(name)
        if gamma_val is not None:
            gamma_gw = parameter.Constant(gamma_val)(gam_name)
        else:
            gamma_gw = parameter.Uniform(0, 7)(gam_name)

        # common red noise PSD
        if psd == 'powerlaw':
            cpl = utils.powerlaw(log10_A=log10_Agw, gamma=gamma_gw)
        elif psd == 'turnover':
            kappa_name = '{}_kappa'.format(name)
            lf0_name = '{}_log10_fbend'.format(name)
            kappa_gw = parameter.Uniform(0, 7)(kappa_name)
            lf0_gw = parameter.Uniform(-9, -7)(lf0_name)
            cpl = utils.turnover(log10_A=log10_Agw,
                                 gamma=gamma_gw,
                                 lf0=lf0_gw,
                                 kappa=kappa_gw)

    if orf is None:
        crn = gp_signals.FourierBasisGP(cpl, components=30, Tspan=Tspan)
    elif orf in orfs.keys():
        crn = gp_signals.FourierBasisCommonGP(cpl,
                                              orfs[orf],
                                              components=30,
                                              Tspan=Tspan)
    else:
        raise ValueError('ORF {} not recognized'.format(orf))

    return crn
示例#3
0
    def gwb(self, option="hd_vary_gamma"):
        """
    Spatially-correlated quadrupole signal from the nanohertz stochastic
    gravitational-wave background.
    """
        name = 'gw'

        if "_nfreqs" in option:
            split_idx_nfreqs = option.split('_').index('nfreqs') - 1
            nfreqs = int(option.split('_')[split_idx_nfreqs])
        else:
            nfreqs = self.determine_nfreqs(sel_func_name=None,
                                           common_signal=True)
        print('Number of Fourier frequencies for the GWB/CPL signal: ', nfreqs)

        if "_gamma" in option:
            amp_name = '{}_log10_A'.format(name)
            if self.params.gwb_lgA_prior == "uniform":
                gwb_log10_A = parameter.Uniform(
                    self.params.gwb_lgA[0], self.params.gwb_lgA[1])(amp_name)
            elif self.params.gwb_lgA_prior == "linexp":
                gwb_log10_A = parameter.LinearExp(
                    self.params.gwb_lgA[0], self.params.gwb_lgA[1])(amp_name)

            gam_name = '{}_gamma'.format(name)
            if "vary_gamma" in option:
                gwb_gamma = parameter.Uniform(
                    self.params.gwb_gamma[0],
                    self.params.gwb_gamma[1])(gam_name)
            elif "fixed_gamma" in option:
                gwb_gamma = parameter.Constant(4.33)(gam_name)
            else:
                split_idx_gamma = option.split('_').index('gamma') - 1
                gamma_val = float(option.split('_')[split_idx_gamma])
                gwb_gamma = parameter.Constant(gamma_val)(gam_name)
            gwb_pl = utils.powerlaw(log10_A=gwb_log10_A, gamma=gwb_gamma)
        elif "freesp" in option:
            amp_name = '{}_log10_rho'.format(name)
            log10_rho = parameter.Uniform(self.params.gwb_lgrho[0],
                                          self.params.gwb_lgrho[1],
                                          size=nfreqs)(amp_name)
            gwb_pl = gp_priors.free_spectrum(log10_rho=log10_rho)

        if "hd" in option:
            print('Adding HD ORF')
            orf = utils.hd_orf()
            gwb = gp_signals.FourierBasisCommonGP(gwb_pl,
                                                  orf,
                                                  components=nfreqs,
                                                  name='gwb',
                                                  Tspan=self.params.Tspan)
        elif "mono" in option:
            print('Adding monopole ORF')
            orf = utils.monopole_orf()
            gwb = gp_signals.FourierBasisCommonGP(gwb_pl,
                                                  orf,
                                                  components=nfreqs,
                                                  name='gwb',
                                                  Tspan=self.params.Tspan)
        elif "dipo" in option:
            print('Adding dipole ORF')
            orf = utils.dipole_orf()
            gwb = gp_signals.FourierBasisCommonGP(gwb_pl,
                                                  orf,
                                                  components=nfreqs,
                                                  name='gwb',
                                                  Tspan=self.params.Tspan)
        elif "varorf" in option:
            corr_coeff = parameter.Uniform(-1., 1., size=7)('corr_coeff')
            orf = infer_orf(corr_coeff=corr_coeff)
            gwb = gp_signals.FourierBasisCommonGP(gwb_pl,
                                                  orf,
                                                  components=nfreqs,
                                                  name='gwb',
                                                  Tspan=self.params.Tspan)
        else:
            gwb = gp_signals.FourierBasisGP(gwb_pl,
                                            components=nfreqs,
                                            name='gwb',
                                            Tspan=self.params.Tspan)

        return gwb
示例#4
0
    def test_orf(self):
        """Test ORF functions."""
        p1 = np.array([0.3, 0.648, 0.7])
        p2 = np.array([0.2, 0.775, -0.6])

        # test auto terms
        #
        hd = utils.hd_orf(p1, p1)
        hd_exp = 1.0
        #
        dp = utils.dipole_orf(p1, p1)
        dp_exp = 1.0 + 1e-5
        #
        mp = utils.monopole_orf(p1, p1)
        mp_exp = 1.0 + 1e-5
        #
        psr_positions = np.array([[1.318116071652818, 2.2142974355881808],
                                  [1.1372584174390601, 0.79539883018414359]])
        anis_basis = anis.anis_basis(psr_positions, lmax=1)
        anis_orf = round(
            utils.anis_orf(p1,
                           p1, [0.0, 1.0, 0.0],
                           anis_basis=anis_basis,
                           psrs_pos=[p1, p2],
                           lmax=1), 3)
        anis_orf_exp = 1.147
        #

        msg = "ORF auto term incorrect for {}"
        keys = ["hd", "dipole", "monopole", "anisotropy"]
        vals = [(hd, hd_exp), (dp, dp_exp), (mp, mp_exp),
                (anis_orf, anis_orf_exp)]
        for key, val in zip(keys, vals):
            assert val[0] == val[1], msg.format(key)

        # test off diagonal terms
        #
        hd = utils.hd_orf(p1, p2)
        omc2 = (1 - np.dot(p1, p2)) / 2
        hd_exp = 1.5 * omc2 * np.log(omc2) - 0.25 * omc2 + 0.5
        #
        dp = utils.dipole_orf(p1, p2)
        dp_exp = np.dot(p1, p2)
        #
        mp = utils.monopole_orf(p1, p2)
        mp_exp = 1.0
        #
        psr_positions = np.array([[1.318116071652818, 2.2142974355881808],
                                  [1.1372584174390601, 0.79539883018414359]])
        anis_basis = anis.anis_basis(psr_positions, lmax=1)
        anis_orf = round(
            utils.anis_orf(p1,
                           p2, [0.0, 1.0, 0.0],
                           anis_basis=anis_basis,
                           psrs_pos=[p1, p2],
                           lmax=1), 3)
        anis_orf_exp = -0.150
        #

        msg = "ORF cross term incorrect for {}"
        keys = ["hd", "dipole", "monopole", "anisotropy"]
        vals = [(hd, hd_exp), (dp, dp_exp), (mp, mp_exp),
                (anis_orf, anis_orf_exp)]
        for key, val in zip(keys, vals):
            assert val[0] == val[1], msg.format(key)
示例#5
0
def common_red_noise_block(psd='powerlaw',
                           prior='log-uniform',
                           Tspan=None,
                           components=30,
                           log10_A_val=None,
                           gamma_val=None,
                           delta_val=None,
                           orf=None,
                           orf_ifreq=0,
                           leg_lmax=5,
                           name='gw',
                           coefficients=False,
                           pshift=False,
                           pseed=None):
    """
    Returns common red noise model:

        1. Red noise modeled with user defined PSD with
        30 sampling frequencies. Available PSDs are
        ['powerlaw', 'turnover' 'spectrum']

    :param psd:
        PSD to use for common red noise signal. Available options
        are ['powerlaw', 'turnover' 'spectrum', 'broken_powerlaw']
    :param prior:
        Prior on log10_A. Default if "log-uniform". Use "uniform" for
        upper limits.
    :param Tspan:
        Sets frequency sampling f_i = i / Tspan. Default will
        use overall time span for individual pulsar.
    :param log10_A_val:
        Value of log10_A parameter for fixed amplitude analyses.
    :param gamma_val:
        Value of spectral index for power-law and turnover
        models. By default spectral index is varied of range [0,7]
    :param delta_val:
        Value of spectral index for high frequencies in broken power-law
        and turnover models. By default spectral index is varied in range [0,7].
    :param orf:
        String representing which overlap reduction function to use.
        By default we do not use any spatial correlations. Permitted
        values are ['hd', 'dipole', 'monopole'].
    :param orf_ifreq:
        Frequency bin at which to start the Hellings & Downs function with 
        numbering beginning at 0. Currently only works with freq_hd orf.
    :param leg_lmax:
        Maximum multipole of a Legendre polynomial series representation 
        of the overlap reduction function [default=5]
    :param pshift:
        Option to use a random phase shift in design matrix. For testing the
        null hypothesis.
    :param pseed:
        Option to provide a seed for the random phase shift.
    :param name: Name of common red process

    """

    orfs = {
        'crn':
        None,
        'hd':
        utils.hd_orf(),
        'dipole':
        utils.dipole_orf(),
        'monopole':
        utils.monopole_orf(),
        'param_hd':
        model_orfs.param_hd_orf(a=parameter.Uniform(-1.5,
                                                    3.0)('gw_orf_param0'),
                                b=parameter.Uniform(-1.0,
                                                    0.5)('gw_orf_param1'),
                                c=parameter.Uniform(-1.0,
                                                    1.0)('gw_orf_param2')),
        'spline_orf':
        model_orfs.spline_orf(
            params=parameter.Uniform(-0.9, 0.9, size=7)('gw_orf_spline')),
        'bin_orf':
        model_orfs.bin_orf(
            params=parameter.Uniform(-1.0, 1.0, size=7)('gw_orf_bin')),
        'zero_diag_hd':
        model_orfs.zero_diag_hd(),
        'zero_diag_bin_orf':
        model_orfs.zero_diag_bin_orf(params=parameter.Uniform(
            -1.0, 1.0, size=7)('gw_orf_bin_zero_diag')),
        'freq_hd':
        model_orfs.freq_hd(params=[components, orf_ifreq]),
        'legendre_orf':
        model_orfs.legendre_orf(
            params=parameter.Uniform(-1.0, 1.0, size=leg_lmax +
                                     1)('gw_orf_legendre')),
        'zero_diag_legendre_orf':
        model_orfs.zero_diag_legendre_orf(
            params=parameter.Uniform(-1.0, 1.0, size=leg_lmax +
                                     1)('gw_orf_legendre_zero_diag'))
    }

    # common red noise parameters
    if psd in ['powerlaw', 'turnover', 'turnover_knee', 'broken_powerlaw']:
        amp_name = '{}_log10_A'.format(name)
        if log10_A_val is not None:
            log10_Agw = parameter.Constant(log10_A_val)(amp_name)
        else:
            if prior == 'uniform':
                log10_Agw = parameter.LinearExp(-18, -11)(amp_name)
            elif prior == 'log-uniform' and gamma_val is not None:
                if np.abs(gamma_val - 4.33) < 0.1:
                    log10_Agw = parameter.Uniform(-18, -14)(amp_name)
                else:
                    log10_Agw = parameter.Uniform(-18, -11)(amp_name)
            else:
                log10_Agw = parameter.Uniform(-18, -11)(amp_name)

        gam_name = '{}_gamma'.format(name)
        if gamma_val is not None:
            gamma_gw = parameter.Constant(gamma_val)(gam_name)
        else:
            gamma_gw = parameter.Uniform(0, 7)(gam_name)

        # common red noise PSD
        if psd == 'powerlaw':
            cpl = utils.powerlaw(log10_A=log10_Agw, gamma=gamma_gw)
        elif psd == 'broken_powerlaw':
            delta_name = '{}_delta'.format(name)
            kappa_name = '{}_kappa'.format(name)
            log10_fb_name = '{}_log10_fb'.format(name)
            kappa_gw = parameter.Uniform(0.01, 0.5)(kappa_name)
            log10_fb_gw = parameter.Uniform(-10, -7)(log10_fb_name)

            if delta_val is not None:
                delta_gw = parameter.Constant(delta_val)(delta_name)
            else:
                delta_gw = parameter.Uniform(0, 7)(delta_name)
            cpl = gpp.broken_powerlaw(log10_A=log10_Agw,
                                      gamma=gamma_gw,
                                      delta=delta_gw,
                                      log10_fb=log10_fb_gw,
                                      kappa=kappa_gw)
        elif psd == 'turnover':
            kappa_name = '{}_kappa'.format(name)
            lf0_name = '{}_log10_fbend'.format(name)
            kappa_gw = parameter.Uniform(0, 7)(kappa_name)
            lf0_gw = parameter.Uniform(-9, -7)(lf0_name)
            cpl = utils.turnover(log10_A=log10_Agw,
                                 gamma=gamma_gw,
                                 lf0=lf0_gw,
                                 kappa=kappa_gw)
        elif psd == 'turnover_knee':
            kappa_name = '{}_kappa'.format(name)
            lfb_name = '{}_log10_fbend'.format(name)
            delta_name = '{}_delta'.format(name)
            lfk_name = '{}_log10_fknee'.format(name)
            kappa_gw = parameter.Uniform(0, 7)(kappa_name)
            lfb_gw = parameter.Uniform(-9.3, -8)(lfb_name)
            delta_gw = parameter.Uniform(-2, 0)(delta_name)
            lfk_gw = parameter.Uniform(-8, -7)(lfk_name)
            cpl = gpp.turnover_knee(log10_A=log10_Agw,
                                    gamma=gamma_gw,
                                    lfb=lfb_gw,
                                    lfk=lfk_gw,
                                    kappa=kappa_gw,
                                    delta=delta_gw)

    if psd == 'spectrum':
        rho_name = '{}_log10_rho'.format(name)
        if prior == 'uniform':
            log10_rho_gw = parameter.LinearExp(-9, -4,
                                               size=components)(rho_name)
        elif prior == 'log-uniform':
            log10_rho_gw = parameter.Uniform(-9, -4, size=components)(rho_name)

        cpl = gpp.free_spectrum(log10_rho=log10_rho_gw)

    if orf is None:
        crn = gp_signals.FourierBasisGP(cpl,
                                        coefficients=coefficients,
                                        components=components,
                                        Tspan=Tspan,
                                        name=name,
                                        pshift=pshift,
                                        pseed=pseed)
    elif orf in orfs.keys():
        if orf == 'crn':
            crn = gp_signals.FourierBasisGP(cpl,
                                            coefficients=coefficients,
                                            components=components,
                                            Tspan=Tspan,
                                            name=name,
                                            pshift=pshift,
                                            pseed=pseed)
        else:
            crn = gp_signals.FourierBasisCommonGP(cpl,
                                                  orfs[orf],
                                                  components=components,
                                                  Tspan=Tspan,
                                                  name=name,
                                                  pshift=pshift,
                                                  pseed=pseed)
    elif isinstance(orf, types.FunctionType):
        crn = gp_signals.FourierBasisCommonGP(cpl,
                                              orf,
                                              components=components,
                                              Tspan=Tspan,
                                              name=name,
                                              pshift=pshift,
                                              pseed=pseed)
    else:
        raise ValueError('ORF {} not recognized'.format(orf))

    return crn
示例#6
0
  def gwb(self,option="hd_vary_gamma"):
    """
    Spatially-correlated quadrupole signal from the nanohertz stochastic
    gravitational-wave background.
    """
    name = 'gw'
    optsp = option.split('+')
    for option in optsp:
      if "_nfreqs" in option:
        split_idx_nfreqs = option.split('_').index('nfreqs') - 1
        nfreqs = int(option.split('_')[split_idx_nfreqs])
      else:
        nfreqs = self.determine_nfreqs(sel_func_name=None, common_signal=True)
      print('Number of Fourier frequencies for the GWB/CPL signal: ', nfreqs)

      if "_gamma" in option:
        amp_name = '{}_log10_A'.format(name)
        if (len(optsp) > 1 and 'hd' in option) or ('namehd' in option):
          amp_name += '_hd'
        elif (len(optsp) > 1 and ('varorf' in option or \
                                  'interporf' in option)) \
                                  or ('nameorf' in option):
          amp_name += '_orf'
        if self.params.gwb_lgA_prior == "uniform":
          gwb_log10_A = parameter.Uniform(self.params.gwb_lgA[0],
                                          self.params.gwb_lgA[1])(amp_name)
        elif self.params.gwb_lgA_prior == "linexp":
          gwb_log10_A = parameter.LinearExp(self.params.gwb_lgA[0],
                                            self.params.gwb_lgA[1])(amp_name)

        gam_name = '{}_gamma'.format(name)
        if "vary_gamma" in option:
          gwb_gamma = parameter.Uniform(self.params.gwb_gamma[0],
                                        self.params.gwb_gamma[1])(gam_name)
        elif "fixed_gamma" in option:
          gwb_gamma = parameter.Constant(4.33)(gam_name)
        else:
          split_idx_gamma = option.split('_').index('gamma') - 1
          gamma_val = float(option.split('_')[split_idx_gamma])
          gwb_gamma = parameter.Constant(gamma_val)(gam_name)
        gwb_pl = utils.powerlaw(log10_A=gwb_log10_A, gamma=gwb_gamma)
      elif "freesp" in option:
        amp_name = '{}_log10_rho'.format(name)
        log10_rho = parameter.Uniform(self.params.gwb_lgrho[0],
                                      self.params.gwb_lgrho[1],
                                      size=nfreqs)(amp_name)
        gwb_pl = gp_priors.free_spectrum(log10_rho=log10_rho)

      if "hd" in option:
        print('Adding HD ORF')
        if "noauto" in option:
          print('Removing auto-correlation')
          orf = hd_orf_noauto()
        else:
          orf = utils.hd_orf()
        if len(optsp) > 1 or 'namehd' in option:
          gwname = 'gw_hd'
        else:
          gwname = 'gw'
        gwb = gp_signals.FourierBasisCommonGP(gwb_pl, orf, components=nfreqs,
                                              name=gwname,
                                              Tspan=self.params.Tspan)
      elif "mono" in option:
        print('Adding monopole ORF')
        orf = utils.monopole_orf()
        gwb = gp_signals.FourierBasisCommonGP(gwb_pl, orf, components=nfreqs,
                                              name='gw',
                                              Tspan=self.params.Tspan)
      elif "dipo" in option:
        print('Adding dipole ORF')
        orf = utils.dipole_orf()
        gwb = gp_signals.FourierBasisCommonGP(gwb_pl, orf, components=nfreqs,
                                              name='gw',
                                              Tspan=self.params.Tspan)

      else:
        gwb = gp_signals.FourierBasisGP(gwb_pl, components=nfreqs,
                                        name='gw', Tspan=self.params.Tspan)
      if 'gw_total' in locals():
        gwb_total += gwb
      else:
        gwb_total = gwb

    return gwb_total
示例#7
0
    def test_pta_phiinv_methods(self):
        ef = white_signals.MeasurementNoise(efac=parameter.Uniform(0.1, 5))

        span = np.max(self.psrs[0].toas) - np.min(self.psrs[0].toas)

        pl = utils.powerlaw(log10_A=parameter.Uniform(-16, -13),
                            gamma=parameter.Uniform(1, 7))

        orf = utils.hd_orf()
        vrf = utils.dipole_orf()

        rn = gp_signals.FourierBasisGP(spectrum=pl, components=30, Tspan=span)

        hdrn = gp_signals.FourierBasisCommonGP(spectrum=pl,
                                               orf=orf,
                                               components=20,
                                               Tspan=span,
                                               name='gw')

        vrn = gp_signals.FourierBasisCommonGP(spectrum=pl,
                                              orf=vrf,
                                              components=20,
                                              Tspan=span,
                                              name='vec')

        vrn2 = gp_signals.FourierBasisCommonGP(spectrum=pl,
                                               orf=vrf,
                                               components=20,
                                               Tspan=span * 1.234,
                                               name='vec2')

        # two common processes, sharing basis partially

        model = ef + rn + hdrn  # + vrn

        pta = signal_base.PTA([model(psr) for psr in self.psrs])

        ps = parameter.sample(pta.params)

        phi = pta.get_phi(ps)
        ldp = np.linalg.slogdet(phi)[1]

        inv1, ld1 = pta.get_phiinv(ps, method='cliques', logdet=True)
        inv2, ld2 = pta.get_phiinv(ps, method='partition', logdet=True)
        inv3, ld3 = pta.get_phiinv(ps, method='sparse', logdet=True)
        if not isinstance(inv3, np.ndarray):
            inv3 = inv3.toarray()

        for ld in [ld1, ld2, ld3]:
            msg = "Wrong phi log determinant for two common processes"
            assert np.allclose(ldp, ld, rtol=1e-15, atol=1e-6), msg

        for inv in [inv1, inv2, inv3]:
            msg = "Wrong phi inverse for two common processes"
            assert np.allclose(np.dot(phi, inv),
                               np.eye(phi.shape[0]),
                               rtol=1e-15,
                               atol=1e-6), msg

        for inva, invb in itertools.combinations([inv1, inv2, inv3], 2):
            assert np.allclose(inva, invb)

        # two common processes, no sharing basis

        model = ef + rn + vrn2

        pta = signal_base.PTA([model(psr) for psr in self.psrs])

        ps = parameter.sample(pta.params)

        phi = pta.get_phi(ps)
        ldp = np.linalg.slogdet(phi)[1]

        inv1, ld1 = pta.get_phiinv(ps, method='cliques', logdet=True)
        inv2, ld2 = pta.get_phiinv(ps, method='partition', logdet=True)
        inv3, ld3 = pta.get_phiinv(ps, method='sparse', logdet=True)
        if not isinstance(inv3, np.ndarray):
            inv3 = inv3.toarray()

        for ld in [ld1, ld2, ld3]:
            msg = "Wrong phi log determinant for two common processes"
            assert np.allclose(ldp, ld, rtol=1e-15, atol=1e-6), msg

        for inv in [inv1, inv2, inv3]:
            msg = "Wrong phi inverse for two processes"
            assert np.allclose(np.dot(phi, inv),
                               np.eye(phi.shape[0]),
                               rtol=1e-15,
                               atol=1e-6), msg

        for inva, invb in itertools.combinations([inv1, inv2, inv3], 2):
            assert np.allclose(inva, invb)

        # three common processes, sharing basis partially

        model = ef + rn + hdrn + vrn

        pta = signal_base.PTA([model(psr) for psr in self.psrs])

        ps = parameter.sample(pta.params)

        phi = pta.get_phi(ps)
        ldp = np.linalg.slogdet(phi)[1]

        inv1, ld1 = pta.get_phiinv(ps, method='cliques', logdet=True)
        inv2, ld2 = pta.get_phiinv(ps, method='partition', logdet=True)
        inv3, ld3 = pta.get_phiinv(ps, method='sparse', logdet=True)
        if not isinstance(inv3, np.ndarray):
            inv3 = inv3.toarray()

        for ld in [ld1, ld3]:
            msg = "Wrong phi log determinant for two common processes"
            assert np.allclose(ldp, ld, rtol=1e-15, atol=1e-6), msg

        for inv in [inv1, inv3]:
            msg = "Wrong phi inverse for three common processes"
            assert np.allclose(np.dot(phi, inv),
                               np.eye(phi.shape[0]),
                               rtol=1e-15,
                               atol=1e-6), msg

        for inva, invb in itertools.combinations([inv1, inv3], 2):
            assert np.allclose(inva, invb)

        # four common processes, three sharing basis partially

        model = ef + rn + hdrn + vrn + vrn2

        pta = signal_base.PTA([model(psr) for psr in self.psrs])

        ps = parameter.sample(pta.params)

        phi = pta.get_phi(ps)
        ldp = np.linalg.slogdet(phi)[1]

        inv1, ld1 = pta.get_phiinv(ps, method='cliques', logdet=True)
        inv2, ld2 = pta.get_phiinv(ps, method='partition', logdet=True)
        inv3, ld3 = pta.get_phiinv(ps, method='sparse', logdet=True)
        if not isinstance(inv3, np.ndarray):
            inv3 = inv3.toarray()

        for ld in [ld1, ld3]:
            msg = "Wrong phi log determinant for two common processes"
            assert np.allclose(ldp, ld, rtol=1e-15, atol=1e-6), msg

        for inv in [inv1, inv3]:
            msg = "Wrong phi inverse for four processes"
            assert np.allclose(np.dot(phi, inv),
                               np.eye(phi.shape[0]),
                               rtol=1e-15,
                               atol=1e-6), msg

        for inva, invb in itertools.combinations([inv1, inv3], 2):
            assert np.allclose(inva, invb)
示例#8
0
def common_red_noise_block(psd='powerlaw',
                           prior='log-uniform',
                           Tspan=None,
                           components=30,
                           gamma_val=None,
                           orf=None,
                           name='gw',
                           coefficients=False,
                           pshift=False,
                           pseed=None):
    """
    Returns common red noise model:

        1. Red noise modeled with user defined PSD with
        30 sampling frequencies. Available PSDs are
        ['powerlaw', 'turnover' 'spectrum']

    :param psd:
        PSD to use for common red noise signal. Available options
        are ['powerlaw', 'turnover' 'spectrum']
    :param prior:
        Prior on log10_A. Default if "log-uniform". Use "uniform" for
        upper limits.
    :param Tspan:
        Sets frequency sampling f_i = i / Tspan. Default will
        use overall time span for indivicual pulsar.
    :param gamma_val:
        Value of spectral index for power-law and turnover
        models. By default spectral index is varied of range [0,7]
    :param orf:
        String representing which overlap reduction function to use.
        By default we do not use any spatial correlations. Permitted
        values are ['hd', 'dipole', 'monopole'].
    :param pshift:
        Option to use a random phase shift in design matrix. For testing the
        null hypothesis.
    :param pseed:
        Option to provide a seed for the random phase shift.
    :param name: Name of common red process

    """

    orfs = {
        'hd': utils.hd_orf(),
        'dipole': utils.dipole_orf(),
        'monopole': utils.monopole_orf()
    }

    # common red noise parameters
    if psd in ['powerlaw', 'turnover', 'turnover_knee']:
        amp_name = '{}_log10_A'.format(name)
        if prior == 'uniform':
            log10_Agw = parameter.LinearExp(-18, -11)(amp_name)
        elif prior == 'log-uniform' and gamma_val is not None:
            if np.abs(gamma_val - 4.33) < 0.1:
                log10_Agw = parameter.Uniform(-18, -14)(amp_name)
            else:
                log10_Agw = parameter.Uniform(-18, -11)(amp_name)
        else:
            log10_Agw = parameter.Uniform(-18, -11)(amp_name)

        gam_name = '{}_gamma'.format(name)
        if gamma_val is not None:
            gamma_gw = parameter.Constant(gamma_val)(gam_name)
        else:
            gamma_gw = parameter.Uniform(0, 7)(gam_name)

        # common red noise PSD
        if psd == 'powerlaw':
            cpl = utils.powerlaw(log10_A=log10_Agw, gamma=gamma_gw)
        elif psd == 'turnover':
            kappa_name = '{}_kappa'.format(name)
            lf0_name = '{}_log10_fbend'.format(name)
            kappa_gw = parameter.Uniform(0, 7)(kappa_name)
            lf0_gw = parameter.Uniform(-9, -7)(lf0_name)
            cpl = utils.turnover(log10_A=log10_Agw,
                                 gamma=gamma_gw,
                                 lf0=lf0_gw,
                                 kappa=kappa_gw)
        elif psd == 'turnover_knee':
            kappa_name = '{}_kappa'.format(name)
            lfb_name = '{}_log10_fbend'.format(name)
            delta_name = '{}_delta'.format(name)
            lfk_name = '{}_log10_fknee'.format(name)
            kappa_gw = parameter.Uniform(0, 7)(kappa_name)
            lfb_gw = parameter.Uniform(-9.3, -8)(lfb_name)
            delta_gw = parameter.Uniform(-2, 0)(delta_name)
            lfk_gw = parameter.Uniform(-8, -7)(lfk_name)
            cpl = gpp.turnover_knee(log10_A=log10_Agw,
                                    gamma=gamma_gw,
                                    lfb=lfb_gw,
                                    lfk=lfk_gw,
                                    kappa=kappa_gw,
                                    delta=delta_gw)

    if psd == 'spectrum':
        rho_name = '{}_log10_rho'.format(name)
        if prior == 'uniform':
            log10_rho_gw = parameter.LinearExp(-9, -4,
                                               size=components)(rho_name)
        elif prior == 'log-uniform':
            log10_rho_gw = parameter.Uniform(-9, -4, size=components)(rho_name)

        cpl = gpp.free_spectrum(log10_rho=log10_rho_gw)

    if orf is None:
        crn = gp_signals.FourierBasisGP(cpl,
                                        coefficients=coefficients,
                                        components=components,
                                        Tspan=Tspan,
                                        name=name,
                                        pshift=pshift,
                                        pseed=pseed)
    elif orf in orfs.keys():
        crn = gp_signals.FourierBasisCommonGP(cpl,
                                              orfs[orf],
                                              components=components,
                                              Tspan=Tspan,
                                              name=name,
                                              pshift=pshift,
                                              pseed=pseed)
    elif isinstance(orf, types.FunctionType):
        crn = gp_signals.FourierBasisCommonGP(cpl,
                                              orf,
                                              components=components,
                                              Tspan=Tspan,
                                              name=name,
                                              pshift=pshift,
                                              pseed=pseed)
    else:
        raise ValueError('ORF {} not recognized'.format(orf))

    return crn
  def gwb(self,option="hd_vary_gamma"):
    """
    Spatially-correlated quadrupole signal from the nanohertz stochastic
    gravitational-wave background.
    """
    name = 'gw'
    optsp = option.split('+')
    for option in optsp:
      if "_nfreqs" in option:
        split_idx_nfreqs = option.split('_').index('nfreqs') - 1
        nfreqs = int(option.split('_')[split_idx_nfreqs])
      else:
        nfreqs = self.determine_nfreqs(sel_func_name=None, common_signal=True)
      print('Number of Fourier frequencies for the GWB/CPL signal: ', nfreqs)

      if "_gamma" in option:
        amp_name = '{}_log10_A'.format(name)
        if (len(optsp) > 1 and 'hd' in option) or ('namehd' in option):
          amp_name += '_hd'
        elif (len(optsp) > 1 and ('varorf' in option or \
                                  'interporf' in option)) \
                                  or ('nameorf' in option):
          amp_name += '_orf'
        if self.params.gwb_lgA_prior == "uniform":
          gwb_log10_A = parameter.Uniform(self.params.gwb_lgA[0],
                                          self.params.gwb_lgA[1])(amp_name)
        elif self.params.gwb_lgA_prior == "linexp":
          gwb_log10_A = parameter.LinearExp(self.params.gwb_lgA[0],
                                            self.params.gwb_lgA[1])(amp_name)
        elif self.params.gwb_lgA_prior == "normal":
          gwb_log10_A = parameter.Normal(mu=self.params.gwb_lgA[0],
                                         sigma=self.params.gwb_lgA[1])(amp_name)

        gam_name = '{}_gamma'.format(name)
        if "vary_gamma" in option:
          if self.params.gwb_gamma_prior == "uniform":
            gwb_gamma = parameter.Uniform(self.params.gwb_gamma[0],
                                          self.params.gwb_gamma[1])(gam_name)
          if self.params.gwb_gamma_prior == "normal":
            gwb_gamma = parameter.Normal(sigma=self.params.gwb_gamma[1],
                                         mu=self.params.gwb_gamma[0])(gam_name)
        elif "fixed_gamma" in option:
          gwb_gamma = parameter.Constant(4.33)(gam_name)
        else:
          split_idx_gamma = option.split('_').index('gamma') - 1
          gamma_val = float(option.split('_')[split_idx_gamma])
          gwb_gamma = parameter.Constant(gamma_val)(gam_name)
        gwb_pl = utils.powerlaw(log10_A=gwb_log10_A, gamma=gwb_gamma)
      elif "freesp" in option:
        amp_name = '{}_log10_rho'.format(name)
        log10_rho = parameter.Uniform(self.params.gwb_lgrho[0],
                                      self.params.gwb_lgrho[1],
                                      size=nfreqs)(amp_name)
        gwb_pl = gp_priors.free_spectrum(log10_rho=log10_rho)

      if "hd" in option:
        print('Adding HD ORF')
        if "noauto" in option:
          print('Removing auto-correlation')
          orf = hd_orf_noauto()
        else:
          import time
          print('AZ about to do hd orf', time.perf_counter())
          orf = utils.hd_orf()
          print('AZ called utils.hd_orf', time.perf_counter())
        if len(optsp) > 1 or 'namehd' in option:
          gwname = 'gwb_hd'
        else:
          gwname = 'gwb'
        #print('evaluating gwb fourierbasiscommongp', time.perf_counter())
        gwb = gp_signals.FourierBasisCommonGP(gwb_pl, orf, components=nfreqs,
                                              name=gwname,
                                              Tspan=self.params.Tspan)
        #print('evaluating gwb fourierbasiscommongp', time.perf_counter())
      elif "mono" in option:
        print('Adding monopole ORF')
        orf = utils.monopole_orf()
        gwb = gp_signals.FourierBasisCommonGP(gwb_pl, orf, components=nfreqs,
                                              name='gwb',
                                              Tspan=self.params.Tspan)
      elif "dipo" in option:
        print('Adding dipole ORF')
        orf = utils.dipole_orf()
        gwb = gp_signals.FourierBasisCommonGP(gwb_pl, orf, components=nfreqs,
                                              name='gwb',
                                              Tspan=self.params.Tspan)
      elif "halfdip" in option:
        print('Adding dipole/2 ORF')
        orf = halfdip_orf()
        gwb = gp_signals.FourierBasisCommonGP(gwb_pl, orf, components=nfreqs,
                                              name='gwb',
                                              Tspan=self.params.Tspan)
      elif "varorf" in option:
        if len(optsp) > 1 or 'nameorf' in option:
          gwname = 'gwb_orf'
        else:
          gwname = 'gwb'
        corr_coeff = parameter.Uniform(-1., 1., size=7)('corr_coeff')
        if "noauto" in option:
          orf = infer_orf_noauto(corr_coeff=corr_coeff)
        else:
          orf = infer_orf(corr_coeff=corr_coeff)
        gwb = gp_signals.FourierBasisCommonGP(gwb_pl, orf, components=nfreqs,
                                              name=gwname,
                                              Tspan=self.params.Tspan)
      elif "interporf" in option:
        print("Adding numpy-interpolated free ORF")
        if len(optsp) > 1 or 'nameorf' in option:
          gwname = 'gwb_orf'
        else:
          gwname = 'gwb'
        corr_coeff = parameter.Uniform(-1., 1., size=7)('corr_coeff')
        if "noauto" in option:
          orf = infer_orf_npinterp_noauto(corr_coeff=corr_coeff)
        else:
          orf = infer_orf_npinterp(corr_coeff=corr_coeff)
        if "skyscr" in option:
          gwb = FourierBasisSkyscrambledGP(gwb_pl, orf, components=nfreqs,
                                           name=gwname+'_skyscr',
                                           Tspan=self.params.Tspan)
        else:
          gwb = gp_signals.FourierBasisCommonGP(gwb_pl, orf, components=nfreqs,
                                                name=gwname,
                                                Tspan=self.params.Tspan)
      else:
        gwb = gp_signals.FourierBasisGP(gwb_pl, components=nfreqs,
                                        name='gwb', Tspan=self.params.Tspan)
      if 'gwb_total' in locals():
        gwb_total += gwb
      else:
        gwb_total = gwb

    return gwb_total
示例#10
0
    def test_pta_phiinv_methods(self):
        ef = white_signals.MeasurementNoise(efac=parameter.Uniform(0.1, 5))

        span = np.max(self.psrs[0].toas) - np.min(self.psrs[0].toas)

        pl = utils.powerlaw(log10_A=parameter.Uniform(-16,-13),
                            gamma=parameter.Uniform(1,7))

        orf = utils.hd_orf()
        vrf = utils.dipole_orf()

        rn = gp_signals.FourierBasisGP(spectrum=pl,
                                       components=30, Tspan=span)

        hdrn = gp_signals.FourierBasisCommonGP(spectrum=pl, orf=orf,
                                               components=20, Tspan=span,
                                               name='gw')

        vrn = gp_signals.FourierBasisCommonGP(spectrum=pl, orf=vrf,
                                              components=20, Tspan=span,
                                              name='vec')

        vrn2 = gp_signals.FourierBasisCommonGP(spectrum=pl, orf=vrf,
                                               components=20, Tspan=span*1.234,
                                               name='vec2')

        # two common processes, sharing basis partially

        model = ef + rn + hdrn  # + vrn

        pta = signal_base.PTA([model(psr) for psr in self.psrs])

        ps = {p.name: float(p.sample()) for p in pta.params}

        phi = pta.get_phi(ps)
        ldp = np.linalg.slogdet(phi)[1]

        inv1, ld1 = pta.get_phiinv(ps,method='cliques', logdet=True)
        inv2, ld2 = pta.get_phiinv(ps,method='partition', logdet=True)
        inv3, ld3 = pta.get_phiinv(ps,method='sparse', logdet=True)
        inv3 = inv3.toarray()

        for ld in [ld1, ld2, ld3]:
            msg = "Wrong phi log determinant for two common processes"
            assert np.allclose(ldp, ld, rtol=1e-15, atol=1e-6), msg

        for inv in [inv1,inv2,inv3]:
            msg = "Wrong phi inverse for two common processes"
            assert np.allclose(np.dot(phi, inv), np.eye(phi.shape[0]),
                               rtol=1e-15, atol=1e-6), msg

        for inva, invb in itertools.combinations([inv1,inv2,inv3],2):
            assert np.allclose(inva,invb)

        # two common processes, no sharing basis

        model = ef + rn + vrn2

        pta = signal_base.PTA([model(psr) for psr in self.psrs])

        ps = {p.name: float(p.sample()) for p in pta.params}

        phi = pta.get_phi(ps)
        ldp = np.linalg.slogdet(phi)[1]

        inv1, ld1 = pta.get_phiinv(ps,method='cliques', logdet=True)
        inv2, ld2 = pta.get_phiinv(ps,method='partition', logdet=True)
        inv3, ld3 = pta.get_phiinv(ps,method='sparse', logdet=True)
        inv3 = inv3.toarray()

        for ld in [ld1, ld2, ld3]:
            msg = "Wrong phi log determinant for two common processes"
            assert np.allclose(ldp, ld, rtol=1e-15, atol=1e-6), msg

        for inv in [inv1,inv2,inv3]:
            msg = "Wrong phi inverse for two processes"
            assert np.allclose(np.dot(phi, inv), np.eye(phi.shape[0]),
                               rtol=1e-15, atol=1e-6), msg

        for inva, invb in itertools.combinations([inv1,inv2,inv3],2):
            assert np.allclose(inva,invb)

        # three common processes, sharing basis partially

        model = ef + rn + hdrn + vrn

        pta = signal_base.PTA([model(psr) for psr in self.psrs])

        ps = {p.name: float(p.sample()) for p in pta.params}

        phi = pta.get_phi(ps)
        ldp = np.linalg.slogdet(phi)[1]

        inv1, ld1 = pta.get_phiinv(ps,method='cliques', logdet=True)
        inv2, ld2 = pta.get_phiinv(ps,method='partition', logdet=True)
        inv3, ld3 = pta.get_phiinv(ps,method='sparse', logdet=True)
        inv3 = inv3.toarray()

        for ld in [ld1, ld3]:
            msg = "Wrong phi log determinant for two common processes"
            assert np.allclose(ldp, ld, rtol=1e-15, atol=1e-6), msg

        for inv in [inv1,inv3]:
            msg = "Wrong phi inverse for three common processes"
            assert np.allclose(np.dot(phi, inv), np.eye(phi.shape[0]),
                               rtol=1e-15, atol=1e-6), msg

        for inva, invb in itertools.combinations([inv1,inv3],2):
            assert np.allclose(inva,invb)

        # four common processes, three sharing basis partially

        model = ef + rn + hdrn + vrn + vrn2

        pta = signal_base.PTA([model(psr) for psr in self.psrs])

        ps = {p.name: float(p.sample()) for p in pta.params}

        phi = pta.get_phi(ps)
        ldp = np.linalg.slogdet(phi)[1]

        inv1, ld1 = pta.get_phiinv(ps,method='cliques', logdet=True)
        inv2, ld2 = pta.get_phiinv(ps,method='partition', logdet=True)
        inv3, ld3 = pta.get_phiinv(ps,method='sparse', logdet=True)
        inv3 = inv3.toarray()

        for ld in [ld1, ld3]:
            msg = "Wrong phi log determinant for two common processes"
            assert np.allclose(ldp, ld, rtol=1e-15, atol=1e-6), msg

        for inv in [inv1, inv3]:
            msg = "Wrong phi inverse for four processes"
            assert np.allclose(np.dot(phi, inv), np.eye(phi.shape[0]),
                               rtol=1e-15, atol=1e-6), msg

        for inva, invb in itertools.combinations([inv1, inv3],2):
            assert np.allclose(inva, invb)