Ejemplo n.º 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)
Ejemplo n.º 2
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)

    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:
      orf = utils.hd_orf()
      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
 def gwb(self,option="common_pl"):
   """
   Spatially-correlated quadrupole signal from the nanohertz stochastic
   gravitational-wave background.
   """
   gwb_log10_A = parameter.Uniform(params.gwb_lgA[0],params.gwb_lgA[1])
   if option=="common_pl":
     gwb_gamma = parameter.Uniform(params.gwb_gamma[0],params.gwb_gamma[1])
   elif option=="fixed_gamma":
     gwb_gamma = parameter.Constant(4.33)
   gwb_pl = utils.powerlaw(log10_A=gwb_log10_A, gamma=gwb_gamma)
   nfreqs = self.determine_nfreqs(sel_func_name=None)
   orf = utils.hd_orf()
   gwb = gp_signals.FourierBasisCommonGP(gwb_pl, orf, components=nfreqs, \
                                         name='gwb', Tspan=self.params.Tspan)
   return gwb
Ejemplo n.º 4
0
    def test_summary(self):
        """ Test summary table."""
        T1, T3 = 3.16e8, 3.16e8
        nf1 = 30

        pl = utils.powerlaw(log10_A=parameter.Uniform(-18,-12),
                            gamma=parameter.Uniform(1,7))
        orf = utils.hd_orf()
        rn = gp_signals.FourierBasisGP(spectrum=pl, components=nf1, Tspan=T1)
        crn = gp_signals.FourierBasisCommonGP(spectrum=pl, orf=orf,
                                              components=1, name='gw',
                                              Tspan=T3)

        model = rn + crn
        pta = model(self.psrs[0]) + model(self.psrs[1])
        pta.summary()
def make_true_orf(psrs):
    """Computes the ORF by looping over pulsar pairs"""

    npsr = len(psrs)

    orf = np.zeros(int(npsr * (npsr - 1) / 2))

    idx = 0
    for i in range(npsr):
        for j in range(i + 1, npsr):

            orf[idx] = utils.hd_orf(psrs[i].pos, psrs[j].pos)

            idx += 1

    return orf
Ejemplo n.º 6
0
    def test_summary(self):
        """ Test summary table."""
        T1, T3 = 3.16e8, 3.16e8
        nf1 = 30

        pl = utils.powerlaw(log10_A=parameter.Uniform(-18, -12),
                            gamma=parameter.Uniform(1, 7))
        orf = utils.hd_orf()
        rn = gp_signals.FourierBasisGP(spectrum=pl, components=nf1, Tspan=T1)
        crn = gp_signals.FourierBasisCommonGP(spectrum=pl,
                                              orf=orf,
                                              components=1,
                                              name='gw',
                                              Tspan=T3)

        model = rn + crn
        pta = model(self.psrs[0]) + model(self.psrs[1])
        pta.summary(to_stdout=True)
Ejemplo n.º 7
0
# DMGP parameters and powerlaw
dm_log10_A = parameter.Uniform(-20, -11)
dm_gamma = parameter.Uniform(0, 7)
dm_pl = utils.powerlaw(log10_A=dm_log10_A, gamma=dm_gamma)
dm_basis = utils.createfourierdesignmatrix_dm(nmodes=30, Tspan=Tspan)

# red noise parameters and powerlaw
if args.ul:
    rn_log10_A = parameter.LinearExp(-20, -11)
else:
    rn_log10_A = parameter.Uniform(-20, -11)
rn_gamma = parameter.Uniform(0, 7)
rn_pl = utils.powerlaw(log10_A=rn_log10_A, gamma=rn_gamma)

# GWB parameters and powerlaw
orf = utils.hd_orf()
if args.ul:
    gwb_log10_A = parameter.LinearExp(-18, -12)('gwb_log10_A')
else:
    gwb_log10_A = parameter.Uniform(-18, -12)('gwb_log10_A')
gwb_gamma = parameter.Constant(13 / 3)('gwb_gamma')
gwb_pl = utils.powerlaw(log10_A=gwb_log10_A, gamma=gwb_gamma)

# signals
ef = white_signals.MeasurementNoise(efac=efac, selection=bkend)
eq = white_signals.EquadNoise(log10_equad=equad, selection=bkend)
ec = white_signals.EcorrKernelNoise(log10_ecorr=ecorr, selection=bkend_NG)

dmgp = gp_signals.BasisGP(dm_pl, dm_basis, name='dm_gp')
dmexp = models.dm_exponential_dip(tmin=54500, tmax=55000, name='dmexp_1')
dm1yr = models.dm_annual_signal()
Ejemplo n.º 8
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)
Ejemplo n.º 9
0
    def test_pta_phi(self):
        T1, T2, T3 = 3.16e8, 3.16e8, 3.16e8
        nf1, nf2, nf3 = 2, 2, 1

        pl = utils.powerlaw(log10_A=parameter.Uniform(-18, -12),
                            gamma=parameter.Uniform(1, 7))
        orf = utils.hd_orf()
        rn = gp_signals.FourierBasisGP(spectrum=pl, components=nf1, Tspan=T1)
        crn = gp_signals.FourierBasisCommonGP(spectrum=pl,
                                              orf=orf,
                                              components=1,
                                              name='gw',
                                              Tspan=T3)

        model = rn + crn
        pta = model(self.psrs[0]) + model(self.psrs[1])

        lA1, gamma1 = -13, 1e-15
        lA2, gamma2 = -13.3, 1e-15
        lAc, gammac = -13.1, 1e-15

        params = {
            'gw_log10_A': lAc,
            'gw_gamma': gammac,
            'B1855+09_red_noise_log10_A': lA1,
            'B1855+09_red_noise_gamma': gamma1,
            'J1909-3744_red_noise_log10_A': lA2,
            'J1909-3744_red_noise_gamma': gamma2
        }

        phi = pta.get_phi(params)
        phiinv = pta.get_phiinv(params)

        T1, T2, T3 = 3.16e8, 3.16e8, 3.16e8
        nf1, nf2, nf3 = 2, 2, 1

        F1, f1 = utils.createfourierdesignmatrix_red(self.psrs[0].toas,
                                                     nf1,
                                                     Tspan=T1)
        F2, f2 = utils.createfourierdesignmatrix_red(self.psrs[1].toas,
                                                     nf2,
                                                     Tspan=T2)
        F1c, fc = utils.createfourierdesignmatrix_red(self.psrs[0].toas,
                                                      nf3,
                                                      Tspan=T3)
        F2c, fc = utils.createfourierdesignmatrix_red(self.psrs[1].toas,
                                                      nf3,
                                                      Tspan=T3)

        nftot = 2 * 2 * nf1
        phidiag = np.zeros(nftot)
        phit = np.zeros((nftot, nftot))

        phidiag[:4] = utils.powerlaw(f1, lA1, gamma1)
        phidiag[:2] += utils.powerlaw(fc, lAc, gammac)
        phidiag[4:] = utils.powerlaw(f2, lA2, gamma2)
        phidiag[4:6] += utils.powerlaw(fc, lAc, gammac)

        phit[np.diag_indices(nftot)] = phidiag

        phit[:2, 4:6] = np.diag(
            hd_powerlaw(fc, self.psrs[0].pos, self.psrs[1].pos, lAc, gammac))
        phit[4:6, :2] = np.diag(
            hd_powerlaw(fc, self.psrs[0].pos, self.psrs[1].pos, lAc, gammac))

        msg = '{} {}'.format(np.diag(phi), np.diag(phit))
        assert np.allclose(phi, phit, rtol=1e-15, atol=1e-17), msg

        msg = 'PTA Phi inverse is incorrect {}.'.format(params)
        assert np.allclose(phiinv, np.linalg.inv(phit), rtol=1e-15,
                           atol=1e-17), msg
Ejemplo n.º 10
0
    def test_pta_phi(self):
        T1, T2, T3 = 3.16e8, 3.16e8, 3.16e8
        nf1, nf2, nf3 = 2, 2, 1

        pl = utils.powerlaw(log10_A=parameter.Uniform(-18,-12),
                            gamma=parameter.Uniform(1,7))
        orf = utils.hd_orf()
        rn = gp_signals.FourierBasisGP(spectrum=pl, components=nf1, Tspan=T1)
        crn = gp_signals.FourierBasisCommonGP(spectrum=pl, orf=orf,
                                              components=1, name='gw',
                                              Tspan=T3)

        model = rn + crn
        pta = model(self.psrs[0]) + model(self.psrs[1])

        lA1, gamma1 = -13, 1e-15
        lA2, gamma2 = -13.3, 1e-15
        lAc, gammac = -13.1, 1e-15

        params = {'gw_log10_A': lAc, 'gw_gamma': gammac,
                  'B1855+09_log10_A': lA1, 'B1855+09_gamma': gamma1,
                  'J1909-3744_log10_A': lA2, 'J1909-3744_gamma': gamma2}

        phi = pta.get_phi(params)
        phiinv = pta.get_phiinv(params)

        T1, T2, T3 = 3.16e8, 3.16e8, 3.16e8
        nf1, nf2, nf3 = 2, 2, 1

        F1, f1 = utils.createfourierdesignmatrix_red(
            self.psrs[0].toas, nf1, Tspan=T1)
        F2, f2 = utils.createfourierdesignmatrix_red(
            self.psrs[1].toas, nf2, Tspan=T2)
        F1c, fc = utils.createfourierdesignmatrix_red(
            self.psrs[0].toas, nf3, Tspan=T3)
        F2c, fc = utils.createfourierdesignmatrix_red(
            self.psrs[1].toas, nf3, Tspan=T3)

        nftot = 2 * 2 * nf1
        phidiag = np.zeros(nftot)
        phit = np.zeros((nftot, nftot))

        phidiag[:4] = utils.powerlaw(f1, lA1, gamma1)
        phidiag[:2] += utils.powerlaw(fc, lAc, gammac)
        phidiag[4:] = utils.powerlaw(f2, lA2, gamma2)
        phidiag[4:6] += utils.powerlaw(fc, lAc, gammac)

        phit[np.diag_indices(nftot)] = phidiag

        phit[:2, 4:6] = np.diag(hd_powerlaw(fc, self.psrs[0].pos,
                                            self.psrs[1].pos, lAc,
                                            gammac))
        phit[4:6, :2] = np.diag(hd_powerlaw(fc, self.psrs[0].pos,
                                            self.psrs[1].pos, lAc,
                                            gammac))

        msg = '{} {}'.format(np.diag(phi), np.diag(phit))
        assert np.allclose(phi, phit, rtol=1e-15, atol=1e-17), msg

        msg = 'PTA Phi inverse is incorrect {}.'.format(params)
        assert np.allclose(phiinv, np.linalg.inv(phit),
                           rtol=1e-15, atol=1e-17), msg
Ejemplo n.º 11
0
        def test_common_red_noise(self):
            """Test of a coefficient-based common GP."""
            pl = utils.powerlaw(log10_A=parameter.Uniform(-18, -12),
                                gamma=parameter.Uniform(1, 7))

            ef = white_signals.MeasurementNoise(
                efac=parameter.Uniform(0.1, 5.0))

            Tspan = max(self.psr.toas.max(), self.psr2.toas.max()) - min(
                self.psr.toas.max(), self.psr2.toas.max())

            pl = utils.powerlaw(log10_A=parameter.Uniform(-18, -12),
                                gamma=parameter.Uniform(1, 7))

            rn = gp_signals.FourierBasisCommonGP(spectrum=pl,
                                                 orf=utils.hd_orf(),
                                                 components=20,
                                                 Tspan=Tspan)

            model = ef + rn

            rnc = gp_signals.FourierBasisCommonGP(spectrum=pl,
                                                  orf=utils.hd_orf(),
                                                  components=20,
                                                  Tspan=Tspan,
                                                  coefficients=True)

            modelc = ef + rnc

            pta = signal_base.PTA([model(self.psr), model(self.psr2)])
            ptac = signal_base.PTA([modelc(self.psr), modelc(self.psr2)])

            params = {
                "B1855+09_efac": 1.0,
                "B1937+21_efac": 1.0,
                "common_fourier_gamma": 5,
                "common_fourier_log10_A": -15,
            }

            # get GP delays in two different ways

            cf, cf2 = np.random.randn(40), np.random.randn(40)

            bs = pta.get_basis(params)
            da = [np.dot(bs[0], cf), np.dot(bs[1], cf2)]

            params.update({
                "B1855+09_common_fourier_coefficients": cf,
                "B1937+21_common_fourier_coefficients": cf2
            })

            db = ptac.get_delay(params)

            msg = "Implicit and explicit GP delays are different."
            assert np.allclose(da[0], db[0]), msg
            assert np.allclose(da[1], db[1]), msg

            cpar = [p for p in ptac.params if "coefficients" in p.name]

            def shouldfail():
                return cpar[0].get_logpdf(params)

            self.assertRaises(NotImplementedError, shouldfail)
Ejemplo n.º 12
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
Ejemplo n.º 13
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)
Ejemplo n.º 14
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
Ejemplo n.º 15
0
def hd_powerlaw(f, pos1, pos2, log10_A=-15, gamma=4.3):
    return utils.powerlaw(f, log10_A, gamma) * utils.hd_orf(pos1, pos2)
Ejemplo n.º 16
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)
        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
Ejemplo n.º 17
0
    def test_conditional_gp(self):
        ef = white_signals.MeasurementNoise(efac=parameter.Uniform(0.1, 5.0))
        tm = gp_signals.TimingModel()
        ec = gp_signals.EcorrBasisModel(log10_ecorr=parameter.Uniform(-10, -5))
        pl = utils.powerlaw(log10_A=parameter.Uniform(-18, -12),
                            gamma=parameter.Uniform(1, 7))
        rn = gp_signals.FourierBasisGP(spectrum=pl,
                                       components=10,
                                       combine=False)

        model = ef + tm + ec + rn
        pta = signal_base.PTA([model(self.psr), model(self.psr2)])

        p0 = {
            "B1855+09_basis_ecorr_log10_ecorr": -6.051740765663904,
            "B1855+09_efac": 2.9027266737466095,
            "B1855+09_red_noise_gamma": 6.9720332277819725,
            "B1855+09_red_noise_log10_A": -16.749192700991543,
            "B1937+21_basis_ecorr_log10_ecorr": -9.726747733721872,
            "B1937+21_efac": 3.959178240268702,
            "B1937+21_red_noise_gamma": 2.9030772884814797,
            "B1937+21_red_noise_log10_A": -17.978562921948992,
        }

        c = utils.ConditionalGP(pta)
        cmean = c.get_mean_coefficients(p0)

        # build index for the global coefficient vector
        idx, ntot = {}, 0
        for l, v in cmean.items():
            idx[l] = slice(ntot, ntot + len(v))
            ntot = ntot + len(v)

        # repeat the computation using the common-signal formalism
        TNrs = pta.get_TNr(p0)
        TNTs = pta.get_TNT(p0)
        phiinvs = pta.get_phiinv(p0, logdet=False, method="cliques")

        TNr = np.concatenate(TNrs)
        Sigma = sps.block_diag(TNTs, "csc") + sps.block_diag(
            [np.diag(phiinvs[0]), np.diag(phiinvs[1])])

        ch = cholesky(Sigma)
        mn = ch(TNr)
        iSigma = sps.linalg.inv(Sigma)

        # check mean values
        msg = "Conditional GP coefficient value does not match"
        for l, v in cmean.items():
            assert np.allclose(mn[idx[l]], v, atol=1e-4, rtol=1e-4), msg

        # check variances
        par = "B1937+21_linear_timing_model_coefficients"
        c1 = np.cov(
            np.array([cs[par] for cs in c.sample_coefficients(p0, n=10000)]).T)
        c2 = iSigma[idx[par], idx[par]].toarray().T
        msg = "Conditional GP coefficient variance does not match"
        assert np.allclose(c1, c2, atol=1e-4, rtol=1e-4), msg

        # check mean processes
        proc = "B1937+21_linear_timing_model"
        p1 = c.get_mean_processes(p0)[proc]
        p2 = np.dot(pta["B1937+21"]["linear_timing_model"].get_basis(),
                    mn[idx[par]])
        msg = "Conditional GP time series does not match"
        assert np.allclose(p1, p2, atol=1e-4, rtol=1e-4), msg

        # check mean of sampled processes
        p2 = np.mean(np.array(
            [pc[proc] for pc in c.sample_processes(p0, n=1000)]),
                     axis=0)
        msg = "Mean of sampled conditional GP processes does not match"
        assert np.allclose(p1, p2, atol=1e-4, rtol=1e-4)

        # now try with a common process

        crn = gp_signals.FourierBasisCommonGP(spectrum=pl,
                                              orf=utils.hd_orf(),
                                              components=10,
                                              combine=False)

        model = ef + tm + ec + crn
        pta = signal_base.PTA([model(self.psr), model(self.psr2)])

        p0 = {
            "B1855+09_basis_ecorr_log10_ecorr": -5.861847220080768,
            "B1855+09_efac": 4.588342210948306,
            "B1937+21_basis_ecorr_log10_ecorr": -9.151872649912377,
            "B1937+21_efac": 0.8947815819783302,
            "common_fourier_gamma": 6.638289750637263,
            "common_fourier_log10_A": -15.68180643904114,
        }

        c = utils.ConditionalGP(pta)
        cmean = c.get_mean_coefficients(p0)

        idx, ntot = {}, 0
        for l, v in cmean.items():
            idx[l] = slice(ntot, ntot + len(v))
            ntot = ntot + len(v)

        TNrs = pta.get_TNr(p0)
        TNTs = pta.get_TNT(p0)
        phiinvs = pta.get_phiinv(p0, logdet=False, method="cliques")

        TNr = np.concatenate(TNrs)
        Sigma = sps.block_diag(TNTs, "csc") + sps.csc_matrix(phiinvs)

        ch = cholesky(Sigma)
        mn = ch(TNr)

        msg = "Conditional GP coefficient value does not match for common GP"
        for l, v in cmean.items():
            assert np.allclose(mn[idx[l]], v)
Ejemplo n.º 18
0
def hd_powerlaw(f, pos1, pos2, log10_A=-15, gamma=4.3):
    return utils.powerlaw(f, log10_A, gamma) * utils.hd_orf(pos1, pos2)
Ejemplo n.º 19
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
Ejemplo n.º 20
0
def model_simple(psrs, psd='powerlaw', efac=False, n_gwbfreqs=30,
                 components=30, freqs=None,
                 vary_gamma=False, upper_limit=False, bayesephem=False,
                 select='backend', red_noise=False, Tspan=None, hd_orf=False,
                 rn_dropout=False, dp_threshold=0.5):
    """
    Reads in list of enterprise Pulsar instance and returns a PTA
    instantiated with the most simple model allowable for enterprise:
    per pulsar:
        1. fixed EFAC per backend/receiver system at 1.0
        2. Linear timing model.
        3. Red noise modeled as a power-law with
            30 sampling frequencies. Default=False
    global:
        1.Common red noise modeled with user defined PSD with
        30 sampling frequencies. Available PSDs are
        ['powerlaw', 'turnover' 'spectrum']
        2. Optional physical ephemeris modeling.
    :param psd:
        PSD to use for common red noise signal. Available options
        are ['powerlaw', 'turnover' 'spectrum']. 'powerlaw' is default
        value.
    :param gamma_common:
        Fixed common red process spectral index value. By default we
        vary the spectral index over the range [0, 7].
    :param upper_limit:
        Perform upper limit on common red noise amplitude. By default
        this is set to False. Note that when performing upper limits it
        is recommended that the spectral index also be fixed to a specific
        value.
    :param bayesephem:
        Include BayesEphem model. Set to False by default
    """

    amp_prior = 'uniform' if upper_limit else 'log-uniform'

    # find the maximum time span to set GW frequency sampling
    if Tspan is None:
        Tspan = model_utils.get_tspan(psrs)

    # timing model
    model = gp_signals.TimingModel()

    #Only White Noise is EFAC set to 1.0
    selection = selections.Selection(selections.by_backend)
    if efac:
        ef = parameter.Uniform(0.1,10.0)
    else:
        ef = parameter.Constant(1.00)

    model += white_signals.MeasurementNoise(efac=ef, selection=selection)

    # common red noise block
    if upper_limit:
        log10_A_gw = parameter.LinearExp(-18,-12)('gw_log10_A')
    else:
        log10_A_gw = parameter.Uniform(-18,-12)('gw_log10_A')

    if vary_gamma:
        gamma_gw = parameter.Uniform(0,7)('gw_gamma')
    else:
        gamma_gw = parameter.Constant(4.33)('gw_gamma')

    pl = signal_base.Function(utils.powerlaw, log10_A=log10_A_gw,
                              gamma=gamma_gw)


    if hd_orf:
        if freqs is None:
            gw = gp_signals.FourierBasisCommonGP(spectrum=pl,
                                                 orf=utils.hd_orf(),
                                                 components=n_gwbfreqs,
                                                 Tspan=Tspan,
                                                 name='gw')
        else:
            gw = gp_signals.FourierBasisCommonGP(spectrum=pl,
                                                 orf=utils.hd_orf(),
                                                 modes=freqs,
                                                 name='gw')
        model += gw
    else:
        if freqs is None:
            crn = gp_signals.FourierBasisGP(spectrum=pl, components=n_gwbfreqs,
                                            Tspan=Tspan, name='gw')
        else:
            crn = gp_signals.FourierBasisGP(spectrum=pl, modes=freqs,
                                            name='gw')
        model += crn

    if red_noise and rn_dropout:
        if amp_prior == 'uniform':
            log10_A = parameter.LinearExp(-20, -11)
        elif amp_prior == 'log-uniform':
            log10_A = parameter.Uniform(-20, -11)
        else:
            log10_A = parameter.Uniform(-20, -11)

        gamma = parameter.Uniform(0, 7)
        k_drop = parameter.Uniform(0, 1)
        if dp_threshold == 6.0:
            dp_threshold = parameter.Uniform(0,1)('k_threshold')
        pl = dropout.dropout_powerlaw(log10_A=log10_A, gamma=gamma,
                                     k_drop=k_drop, k_threshold=dp_threshold)
        rn = gp_signals.FourierBasisGP(pl, components=components,
                                       Tspan=Tspan, name='red_noise')
        model += rn
    elif red_noise:
        # red noise
        model += models.red_noise_block(prior=amp_prior, Tspan=Tspan,
                                        components=components)

    # ephemeris model
    if bayesephem:
        model += deterministic_signals.PhysicalEphemerisSignal(use_epoch_toas=True)

    # set up PTA
    pta = signal_base.PTA([model(p) for p in psrs])

    return pta
Ejemplo n.º 21
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)
Ejemplo n.º 22
0
    def compute_like(self, npsrs=1, inc_corr=False, inc_kernel=False):

        # get parameters from PAL2 style noise files
        params = get_noise_from_pal2(datadir + "/B1855+09_noise.txt")
        params2 = get_noise_from_pal2(datadir + "/J1909-3744_noise.txt")
        params.update(params2)

        psrs = self.psrs if npsrs == 2 else [self.psrs[0]]

        if inc_corr:
            params.update({"GW_gamma": 4.33, "GW_log10_A": -15.0})

        # find the maximum time span to set GW frequency sampling
        tmin = [p.toas.min() for p in psrs]
        tmax = [p.toas.max() for p in psrs]
        Tspan = np.max(tmax) - np.min(tmin)

        # setup basic model
        efac = parameter.Constant()
        equad = parameter.Constant()
        ecorr = parameter.Constant()
        log10_A = parameter.Constant()
        gamma = parameter.Constant()

        selection = Selection(selections.by_backend)

        ef = white_signals.MeasurementNoise(efac=efac, selection=selection)
        eq = white_signals.EquadNoise(log10_equad=equad, selection=selection)
        ec = white_signals.EcorrKernelNoise(log10_ecorr=ecorr,
                                            selection=selection)

        pl = utils.powerlaw(log10_A=log10_A, gamma=gamma)
        rn = gp_signals.FourierBasisGP(pl)

        orf = utils.hd_orf()
        crn = gp_signals.FourierBasisCommonGP(pl,
                                              orf,
                                              components=20,
                                              name="GW",
                                              Tspan=Tspan)

        tm = gp_signals.TimingModel()

        log10_sigma = parameter.Uniform(-10, -5)
        log10_lam = parameter.Uniform(np.log10(86400), np.log10(1500 * 86400))
        basis = create_quant_matrix(dt=7 * 86400)
        prior = se_kernel(log10_sigma=log10_sigma, log10_lam=log10_lam)
        se = gp_signals.BasisGP(prior, basis, name="se")

        # set up kernel stuff
        if isinstance(inc_kernel, bool):
            inc_kernel = [inc_kernel] * npsrs

        if inc_corr:
            s = ef + eq + ec + rn + crn + tm
        else:
            s = ef + eq + ec + rn + tm

        models = []
        for ik, psr in zip(inc_kernel, psrs):
            snew = s + se if ik else s
            models.append(snew(psr))

        pta = signal_base.PTA(models)

        # set parameters
        pta.set_default_params(params)

        # SE kernel parameters
        log10_sigmas, log10_lams = [-7.0, -6.5], [7.0, 6.5]
        params.update({
            "B1855+09_se_log10_lam": log10_lams[0],
            "B1855+09_se_log10_sigma": log10_sigmas[0],
            "J1909-3744_se_log10_lam": log10_lams[1],
            "J1909-3744_se_log10_sigma": log10_sigmas[1],
        })

        # get parameters
        efacs, equads, ecorrs, log10_A, gamma = [], [], [], [], []
        lsig, llam = [], []
        for pname in [p.name for p in psrs]:
            efacs.append([
                params[key] for key in sorted(params.keys())
                if "efac" in key and pname in key
            ])
            equads.append([
                params[key] for key in sorted(params.keys())
                if "equad" in key and pname in key
            ])
            ecorrs.append([
                params[key] for key in sorted(params.keys())
                if "ecorr" in key and pname in key
            ])
            log10_A.append(params["{}_red_noise_log10_A".format(pname)])
            gamma.append(params["{}_red_noise_gamma".format(pname)])
            lsig.append(params["{}_se_log10_sigma".format(pname)])
            llam.append(params["{}_se_log10_lam".format(pname)])
        GW_gamma = 4.33
        GW_log10_A = -15.0

        # correct value
        tflags = [sorted(list(np.unique(p.backend_flags))) for p in psrs]
        cfs, logdets, phis, Ts = [], [], [], []
        for ii, (ik, psr, flags) in enumerate(zip(inc_kernel, psrs, tflags)):
            nvec0 = np.zeros_like(psr.toas)
            for ct, flag in enumerate(flags):
                ind = psr.backend_flags == flag
                nvec0[ind] = efacs[ii][ct]**2 * psr.toaerrs[ind]**2
                nvec0[ind] += 10**(2 * equads[ii][ct]) * np.ones(np.sum(ind))

            # get the basis
            bflags = psr.backend_flags
            Umats = []
            for flag in np.unique(bflags):
                mask = bflags == flag
                Umats.append(
                    utils.create_quantization_matrix(psr.toas[mask])[0])
            nepoch = sum(U.shape[1] for U in Umats)
            U = np.zeros((len(psr.toas), nepoch))
            jvec = np.zeros(nepoch)
            netot = 0
            for ct, flag in enumerate(np.unique(bflags)):
                mask = bflags == flag
                nn = Umats[ct].shape[1]
                U[mask, netot:nn + netot] = Umats[ct]
                jvec[netot:nn + netot] = 10**(2 * ecorrs[ii][ct])
                netot += nn

            # get covariance matrix
            cov = np.diag(nvec0) + np.dot(U * jvec[None, :], U.T)
            cf = sl.cho_factor(cov)
            logdet = np.sum(2 * np.log(np.diag(cf[0])))
            cfs.append(cf)
            logdets.append(logdet)

            F, f2 = utils.createfourierdesignmatrix_red(psr.toas,
                                                        nmodes=20,
                                                        Tspan=Tspan)
            Mmat = psr.Mmat.copy()
            norm = np.sqrt(np.sum(Mmat**2, axis=0))
            Mmat /= norm
            U2, avetoas = create_quant_matrix(psr.toas, dt=7 * 86400)
            if ik:
                T = np.hstack((F, Mmat, U2))
            else:
                T = np.hstack((F, Mmat))
            Ts.append(T)
            phi = utils.powerlaw(f2, log10_A=log10_A[ii], gamma=gamma[ii])
            if inc_corr:
                phigw = utils.powerlaw(f2, log10_A=GW_log10_A, gamma=GW_gamma)
            else:
                phigw = np.zeros(40)
            K = se_kernel(avetoas,
                          log10_sigma=log10_sigmas[ii],
                          log10_lam=log10_lams[ii])
            k = np.diag(
                np.concatenate((phi + phigw, np.ones(Mmat.shape[1]) * 1e40)))
            if ik:
                k = sl.block_diag(k, K)
            phis.append(k)

        # manually compute loglike
        loglike = 0
        TNrs, TNTs = [], []
        for ct, psr in enumerate(psrs):
            TNrs.append(np.dot(Ts[ct].T, sl.cho_solve(cfs[ct], psr.residuals)))
            TNTs.append(np.dot(Ts[ct].T, sl.cho_solve(cfs[ct], Ts[ct])))
            loglike += -0.5 * (
                np.dot(psr.residuals, sl.cho_solve(cfs[ct], psr.residuals)) +
                logdets[ct])

        TNr = np.concatenate(TNrs)
        phi = sl.block_diag(*phis)

        if inc_corr:
            hd = utils.hd_orf(psrs[0].pos, psrs[1].pos)
            phi[len(phis[0]):len(phis[0]) + 40, :40] = np.diag(phigw * hd)
            phi[:40, len(phis[0]):len(phis[0]) + 40] = np.diag(phigw * hd)

        cf = sl.cho_factor(phi)
        phiinv = sl.cho_solve(cf, np.eye(phi.shape[0]))
        logdetphi = np.sum(2 * np.log(np.diag(cf[0])))
        Sigma = sl.block_diag(*TNTs) + phiinv

        cf = sl.cho_factor(Sigma)
        expval = sl.cho_solve(cf, TNr)
        logdetsigma = np.sum(2 * np.log(np.diag(cf[0])))

        loglike -= 0.5 * (logdetphi + logdetsigma)
        loglike += 0.5 * np.dot(TNr, expval)

        method = ["partition", "sparse", "cliques"]
        for mth in method:
            eloglike = pta.get_lnlikelihood(params, phiinv_method=mth)
            msg = "Incorrect like for npsr={}, phiinv={}".format(npsrs, mth)
            assert np.allclose(eloglike, loglike), msg
Ejemplo n.º 23
0
    def compute_like(self, npsrs=1, inc_corr=False, inc_kernel=False):

        # get parameters from PAL2 style noise files
        params = get_noise_from_pal2(datadir+'/B1855+09_noise.txt')
        params2 = get_noise_from_pal2(datadir+'/J1909-3744_noise.txt')
        params.update(params2)

        psrs = self.psrs if npsrs == 2 else [self.psrs[0]]

        if inc_corr:
            params.update({'GW_gamma': 4.33, 'GW_log10_A':-15.0})

        # find the maximum time span to set GW frequency sampling
        tmin = [p.toas.min() for p in psrs]
        tmax = [p.toas.max() for p in psrs]
        Tspan = np.max(tmax) - np.min(tmin)

        # setup basic model
        efac = parameter.Constant()
        equad = parameter.Constant()
        ecorr = parameter.Constant()
        log10_A = parameter.Constant()
        gamma = parameter.Constant()

        selection = Selection(selections.by_backend)

        ef = white_signals.MeasurementNoise(efac=efac,
                                            selection=selection)
        eq = white_signals.EquadNoise(log10_equad=equad,
                                      selection=selection)
        ec = white_signals.EcorrKernelNoise(log10_ecorr=ecorr,
                                            selection=selection)

        pl = utils.powerlaw(log10_A=log10_A, gamma=gamma)
        rn = gp_signals.FourierBasisGP(pl)

        orf = utils.hd_orf()
        crn = gp_signals.FourierBasisCommonGP(pl, orf, components=20,
                                              name='GW', Tspan=Tspan)

        tm = gp_signals.TimingModel()

        log10_sigma = parameter.Uniform(-10, -5)
        log10_lam = parameter.Uniform(np.log10(86400), np.log10(1500*86400))
        basis = create_quant_matrix(dt=7*86400)
        prior = se_kernel(log10_sigma=log10_sigma, log10_lam=log10_lam)
        se = gp_signals.BasisGP(prior, basis, name='se')

        # set up kernel stuff
        if isinstance(inc_kernel, bool):
            inc_kernel = [inc_kernel] * npsrs

        if inc_corr:
            s = ef + eq + ec + rn + crn + tm
        else:
            s = ef + eq + ec + rn + tm

        models = []
        for ik, psr in zip(inc_kernel, psrs):
            snew = s + se if ik else s
            models.append(snew(psr))

        pta = signal_base.PTA(models)

        # set parameters
        pta.set_default_params(params)

        # SE kernel parameters
        log10_sigmas, log10_lams = [-7.0, -6.5], [7.0, 6.5]
        params.update({'B1855+09_se_log10_lam': log10_lams[0],
                       'B1855+09_se_log10_sigma': log10_sigmas[0],
                       'J1909-3744_se_log10_lam': log10_lams[1],
                       'J1909-3744_se_log10_sigma': log10_sigmas[1]})

        # get parameters
        efacs, equads, ecorrs, log10_A, gamma = [], [], [], [], []
        lsig, llam = [], []
        for pname in [p.name for p in psrs]:
            efacs.append([params[key] for key in sorted(params.keys())
                          if 'efac' in key and pname in key])
            equads.append([params[key] for key in sorted(params.keys())
                           if 'equad' in key and pname in key])
            ecorrs.append([params[key] for key in sorted(params.keys())
                           if 'ecorr' in key and pname in key])
            log10_A.append(params['{}_log10_A'.format(pname)])
            gamma.append(params['{}_gamma'.format(pname)])
            lsig.append(params['{}_se_log10_sigma'.format(pname)])
            llam.append(params['{}_se_log10_lam'.format(pname)])
        GW_gamma = 4.33
        GW_log10_A = -15.0

        # correct value
        tflags = [sorted(list(np.unique(p.backend_flags))) for p in psrs]
        cfs, logdets, phis, Ts = [], [], [], []
        for ii, (ik, psr, flags) in enumerate(zip(inc_kernel, psrs, tflags)):
            nvec0 = np.zeros_like(psr.toas)
            for ct, flag in enumerate(flags):
                ind = psr.backend_flags == flag
                nvec0[ind] = efacs[ii][ct]**2 * psr.toaerrs[ind]**2
                nvec0[ind] += 10**(2*equads[ii][ct]) * np.ones(np.sum(ind))

            # get the basis
            bflags = psr.backend_flags
            Umats = []
            for flag in np.unique(bflags):
                mask = bflags == flag
                Umats.append(utils.create_quantization_matrix(
                    psr.toas[mask])[0])
            nepoch = sum(U.shape[1] for U in Umats)
            U = np.zeros((len(psr.toas), nepoch))
            jvec = np.zeros(nepoch)
            netot = 0
            for ct, flag in enumerate(np.unique(bflags)):
                mask = bflags == flag
                nn = Umats[ct].shape[1]
                U[mask, netot:nn+netot] = Umats[ct]
                jvec[netot:nn+netot] = 10**(2*ecorrs[ii][ct])
                netot += nn

            # get covariance matrix
            cov = np.diag(nvec0) + np.dot(U*jvec[None, :], U.T)
            cf = sl.cho_factor(cov)
            logdet = np.sum(2*np.log(np.diag(cf[0])))
            cfs.append(cf)
            logdets.append(logdet)

            F, f2 = utils.createfourierdesignmatrix_red(psr.toas,
                                                        nmodes=20,
                                                        Tspan=Tspan)
            Mmat = psr.Mmat.copy()
            norm = np.sqrt(np.sum(Mmat**2, axis=0))
            Mmat /= norm
            U2, avetoas = create_quant_matrix(psr.toas, dt=7*86400)
            if ik:
                T = np.hstack((F, Mmat, U2))
            else:
                T = np.hstack((F, Mmat))
            Ts.append(T)
            phi = utils.powerlaw(f2, log10_A=log10_A[ii],
                                 gamma=gamma[ii])
            if inc_corr:
                phigw = utils.powerlaw(f2, log10_A=GW_log10_A,
                                       gamma=GW_gamma)
            else:
                phigw = np.zeros(40)
            K = se_kernel(avetoas, log10_sigma=log10_sigmas[ii],
                          log10_lam=log10_lams[ii])
            k = np.diag(np.concatenate((phi+phigw,
                                        np.ones(Mmat.shape[1])*1e40)))
            if ik:
                k = sl.block_diag(k, K)
            phis.append(k)

        # manually compute loglike
        loglike = 0
        TNrs, TNTs = [], []
        for ct, psr in enumerate(psrs):
            TNrs.append(np.dot(Ts[ct].T, sl.cho_solve(cfs[ct], psr.residuals)))
            TNTs.append(np.dot(Ts[ct].T, sl.cho_solve(cfs[ct], Ts[ct])))
            loglike += -0.5 * (np.dot(psr.residuals, sl.cho_solve(
                cfs[ct], psr.residuals)) + logdets[ct])

        TNr = np.concatenate(TNrs)
        phi = sl.block_diag(*phis)

        if inc_corr:
            hd = utils.hd_orf(psrs[0].pos, psrs[1].pos)
            phi[len(phis[0]):len(phis[0])+40, :40] = np.diag(phigw * hd)
            phi[:40, len(phis[0]):len(phis[0])+40] = np.diag(phigw * hd)

        cf = sl.cho_factor(phi)
        phiinv = sl.cho_solve(cf, np.eye(phi.shape[0]))
        logdetphi = np.sum(2*np.log(np.diag(cf[0])))
        Sigma = sl.block_diag(*TNTs) + phiinv

        cf = sl.cho_factor(Sigma)
        expval = sl.cho_solve(cf, TNr)
        logdetsigma = np.sum(2*np.log(np.diag(cf[0])))

        loglike -= 0.5 * (logdetphi + logdetsigma)
        loglike += 0.5 * np.dot(TNr, expval)

        method = ['partition', 'sparse', 'cliques']
        for mth in method:
            eloglike = pta.get_lnlikelihood(params, phiinv_method=mth)
            msg = 'Incorrect like for npsr={}, phiinv={}'.format(npsrs, mth)
            assert np.allclose(eloglike, loglike), msg
Ejemplo n.º 24
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