def test_gp_parameter(self): """Test GP basis model with parameterized basis.""" pl = utils.powerlaw(log10_A=parameter.Uniform(-18, -12), gamma=parameter.Uniform(0, 7)) basis_env = utils.createfourierdesignmatrix_env( log10_Amp=parameter.Uniform(-10, -5), t0=parameter.Uniform(4.3e9, 5e9), log10_Q=parameter.Uniform(0, 4)) basis_red = utils.createfourierdesignmatrix_red() rn_env = gp_signals.BasisGP(pl, basis_env, name="env") rn = gp_signals.BasisGP(pl, basis_red) s = rn_env + rn m = s(self.psr) # parameters log10_A, gamma = -14.5, 4.33 log10_A_env, gamma_env = -14.0, 2.5 log10_Amp, log10_Q, t0 = -7.3, np.log10(345), 55000 * 86400 params = { "B1855+09_log10_A": log10_A, "B1855+09_gamma": gamma, "B1855+09_env_log10_A": log10_A_env, "B1855+09_env_gamma": gamma_env, "B1855+09_env_log10_Q": log10_Q, "B1855+09_env_log10_Amp": log10_Amp, "B1855+09_env_t0": t0, } # get basis Fred, f2_red = utils.createfourierdesignmatrix_red(self.psr.toas, nmodes=30) Fenv, f2_env = utils.createfourierdesignmatrix_env(self.psr.toas, nmodes=30, log10_Amp=log10_Amp, log10_Q=log10_Q, t0=t0) F = np.hstack((Fenv, Fred)) phi_env = utils.powerlaw(f2_env, log10_A=log10_A_env, gamma=gamma_env) phi_red = utils.powerlaw(f2_red, log10_A=log10_A, gamma=gamma) phi = np.concatenate((phi_env, phi_red)) # basis matrix test msg = "F matrix incorrect for GP Fourier signal." assert np.allclose(F, m.get_basis(params)), msg # spectrum test msg = "Spectrum incorrect for GP Fourier signal." assert np.all(m.get_phi(params) == phi), msg # inverse spectrum test msg = "Spectrum inverse incorrect for GP Fourier signal." assert np.all(m.get_phiinv(params) == 1 / phi), msg # test shape msg = "F matrix shape incorrect" assert m.get_basis(params).shape == F.shape, msg
def test_kernel(self): 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") sem = se(self.psr) # parameters log10_lam, log10_sigma = 7.4, -6.4 params = {"B1855+09_se_log10_lam": log10_lam, "B1855+09_se_log10_sigma": log10_sigma} # basis check U, avetoas = create_quant_matrix(self.psr.toas, dt=7 * 86400) msg = "Kernel Basis incorrect" assert np.allclose(U, sem.get_basis(params)), msg # kernel test K = se_kernel(avetoas, log10_lam=log10_lam, log10_sigma=log10_sigma) msg = "Kernel incorrect" assert np.allclose(K, sem.get_phi(params)), msg # inverse kernel test Kinv = np.linalg.inv(K) msg = "Kernel inverse incorrect" assert np.allclose(Kinv, sem.get_phiinv(params)), msg
def test_free_spec_prior(self): """Test that red noise signal returns correct values.""" # set up signal parameter pr = gp_priors.free_spectrum( log10_rho=parameter.Uniform(-10, -4, size=30)) basis = gp_bases.createfourierdesignmatrix_red(nmodes=30) rn = gp_signals.BasisGP(priorFunction=pr, basisFunction=basis, name="red_noise") rnm = rn(self.psr) # parameters rhos = np.random.uniform(-10, -4, size=30) params = {"B1855+09_red_noise_log10_rho": rhos} # basis matrix test F, f2 = gp_bases.createfourierdesignmatrix_red(self.psr.toas, nmodes=30) msg = "F matrix incorrect for free spectrum." assert np.allclose(F, rnm.get_basis(params)), msg # spectrum test phi = gp_priors.free_spectrum(f2, log10_rho=rhos) msg = "Spectrum incorrect for free spectrum." assert np.all(rnm.get_phi(params) == phi), msg # inverse spectrum test msg = "Spectrum inverse incorrect for free spectrum." assert np.all(rnm.get_phiinv(params) == 1 / phi), msg # test shape msg = "F matrix shape incorrect" assert rnm.get_basis(params).shape == F.shape, msg
def chromred(self, option="vary"): """ This is an generalization of DM noise, with the dependence of Fourier amplitudes on radio frequency nu as ~ 1/nu^chi, where chi is a free parameter. Examples of chi: - Pulse scattering in the ISM: chi = 4 (Lyne A., Graham-Smith F., 2012, Pulsar astronomy) - Refractive propagation: chi = 6.4 (Shannon, R. M., and J. M. Cordes. MNRAS, 464.2 (2017): 2075-2089). """ log10_A = parameter.Uniform(self.params.dmn_lgA[0], self.params.dmn_lgA[1]) gamma = parameter.Uniform(self.params.dmn_gamma[0], self.params.dmn_gamma[1]) pl = utils.powerlaw(log10_A=log10_A, gamma=gamma, \ components=self.params.red_general_nfouriercomp) nfreqs = self.determine_nfreqs(sel_func_name=None) if option == "vary": idx = parameter.Uniform(self.params.chrom_idx[0], \ self.params.chrom_idx[1]) else: idx = option chr_basis = models.createfourierdesignmatrix_chromatic( nmodes=nfreqs, Tspan=self.params.Tspan, idx=idx) chrn = gp_signals.BasisGP(pl, chr_basis, name='chromatic_gp') return chrn
def dm_noise(self, option="powerlaw"): """ A term to account for stochastic variations in DM. It is based on spin noise model, with Fourier amplitudes depending on radio frequency nu as ~ 1/nu^2. """ log10_A = parameter.Uniform(self.params.dmn_lgA[0], self.params.dmn_lgA[1]) gamma = parameter.Uniform(self.params.dmn_gamma[0], self.params.dmn_gamma[1]) if option == "powerlaw": pl = utils.powerlaw(log10_A=log10_A, gamma=gamma, \ components=self.params.red_general_nfouriercomp) elif option == "turnover": fc = parameter.Uniform(self.params.sn_fc[0], self.params.sn_fc[1]) pl = powerlaw_bpl(log10_A=log10_A, gamma=gamma, fc=fc, components=self.params.red_general_nfouriercomp) nfreqs = self.determine_nfreqs(sel_func_name=None) dm_basis = utils.createfourierdesignmatrix_dm(nmodes=nfreqs, Tspan=self.params.Tspan, fref=self.params.fref) dmn = gp_signals.BasisGP(pl, dm_basis, name='dm_gp') return dmn
def test_kernel_backend(self): # set up signal parameter selection = Selection(selections.by_backend) 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, selection=selection, name="se") sem = se(self.psr) # parameters log10_sigmas = [-7, -6, -6.4, -8.5] log10_lams = [8.3, 7.4, 6.8, 5.6] params = { "B1855+09_se_430_ASP_log10_lam": log10_lams[0], "B1855+09_se_430_ASP_log10_sigma": log10_sigmas[0], "B1855+09_se_430_PUPPI_log10_lam": log10_lams[1], "B1855+09_se_430_PUPPI_log10_sigma": log10_sigmas[1], "B1855+09_se_L-wide_ASP_log10_lam": log10_lams[2], "B1855+09_se_L-wide_ASP_log10_sigma": log10_sigmas[2], "B1855+09_se_L-wide_PUPPI_log10_lam": log10_lams[3], "B1855+09_se_L-wide_PUPPI_log10_sigma": log10_sigmas[3], } # get the basis bflags = self.psr.backend_flags Fmats, fs, phis = [], [], [] for ct, flag in enumerate(np.unique(bflags)): mask = bflags == flag U, avetoas = create_quant_matrix(self.psr.toas[mask], dt=7 * 86400) Fmats.append(U) fs.append(avetoas) phis.append( se_kernel(avetoas, log10_sigma=log10_sigmas[ct], log10_lam=log10_lams[ct])) nf = sum(F.shape[1] for F in Fmats) U = np.zeros((len(self.psr.toas), nf)) K = sl.block_diag(*phis) Kinv = np.linalg.inv(K) nftot = 0 for ct, flag in enumerate(np.unique(bflags)): mask = bflags == flag nn = Fmats[ct].shape[1] U[mask, nftot:nn + nftot] = Fmats[ct] nftot += nn msg = "Kernel basis incorrect for backend signal." assert np.allclose(U, sem.get_basis(params)), msg # spectrum test msg = "Kernel incorrect for backend signal." assert np.allclose(sem.get_phi(params), K), msg # inverse spectrum test msg = "Kernel inverse incorrect for backend signal." assert np.allclose(sem.get_phiinv(params), Kinv), msg
def test_turnover_knee_prior(self): """Test that red noise signal returns correct values.""" # set up signal parameter pr = gp_priors.turnover_knee( log10_A=parameter.Uniform(-18, -12), gamma=parameter.Uniform(1, 7), lfb=parameter.Uniform(-9, -7.5), lfk=parameter.Uniform(-9, -7.5), kappa=parameter.Uniform(2.5, 5), delta=parameter.Uniform(0.01, 1), ) basis = gp_bases.createfourierdesignmatrix_red(nmodes=30) rn = gp_signals.BasisGP(priorFunction=pr, basisFunction=basis, name="red_noise") rnm = rn(self.psr) # parameters log10_A, gamma, lfb = -14.5, 4.33, -8.5 lfk, kappa, delta = -8.5, 3, 0.5 params = { "B1855+09_red_noise_log10_A": log10_A, "B1855+09_red_noise_gamma": gamma, "B1855+09_red_noise_lfb": lfb, "B1855+09_red_noise_lfk": lfk, "B1855+09_red_noise_kappa": kappa, "B1855+09_red_noise_delta": delta, } # basis matrix test F, f2 = gp_bases.createfourierdesignmatrix_red(self.psr.toas, nmodes=30) msg = "F matrix incorrect for turnover." assert np.allclose(F, rnm.get_basis(params)), msg # spectrum test phi = gp_priors.turnover_knee(f2, log10_A=log10_A, gamma=gamma, lfb=lfb, lfk=lfk, kappa=kappa, delta=delta) msg = "Spectrum incorrect for turnover." assert np.all(rnm.get_phi(params) == phi), msg # inverse spectrum test msg = "Spectrum inverse incorrect for turnover." assert np.all(rnm.get_phiinv(params) == 1 / phi), msg # test shape msg = "F matrix shape incorrect" assert rnm.get_basis(params).shape == F.shape, msg
def test_adapt_t_process_prior(self): """Test that red noise signal returns correct values.""" # set up signal parameter pr = gp_priors.t_process_adapt( log10_A=parameter.Uniform(-18, -12), gamma=parameter.Uniform(1, 7), alphas_adapt=gp_priors.InvGamma(), nfreq=parameter.Uniform(5, 25), ) basis = gp_bases.createfourierdesignmatrix_red(nmodes=30) rn = gp_signals.BasisGP(priorFunction=pr, basisFunction=basis, name="red_noise") rnm = rn(self.psr) # parameters alphas = scipy.stats.invgamma.rvs(1, scale=1, size=1) log10_A, gamma, nfreq = -15, 4.33, 12 params = { "B1855+09_red_noise_log10_A": log10_A, "B1855+09_red_noise_gamma": gamma, "B1855+09_red_noise_alphas_adapt": alphas, "B1855+09_red_noise_nfreq": nfreq, } # basis matrix test F, f2 = gp_bases.createfourierdesignmatrix_red(self.psr.toas, nmodes=30) msg = "F matrix incorrect for free spectrum." assert np.allclose(F, rnm.get_basis(params)), msg # spectrum test phi = gp_priors.t_process_adapt(f2, log10_A=log10_A, gamma=gamma, alphas_adapt=alphas, nfreq=nfreq) msg = "Spectrum incorrect for free spectrum." assert np.all(rnm.get_phi(params) == phi), msg # inverse spectrum test msg = "Spectrum inverse incorrect for free spectrum." assert np.all(rnm.get_phiinv(params) == 1 / phi), msg # test shape msg = "F matrix shape incorrect" assert rnm.get_basis(params).shape == F.shape, msg
def chromred(self,option="vary"): """ This is an generalization of DM noise, with the dependence of Fourier amplitudes on radio frequency nu as ~ 1/nu^chi, where chi is a free parameter. Examples of chi: - Pulse scattering in the ISM: chi = 4 (Lyne A., Graham-Smith F., 2012, Pulsar astronomy) - Refractive propagation: chi = 6.4 (Shannon, R. M., and J. M. Cordes. MNRAS, 464.2 (2017): 2075-2089). """ log10_A = parameter.Uniform(self.params.dmn_lgA[0],self.params.dmn_lgA[1]) gamma = parameter.Uniform(self.params.dmn_gamma[0],self.params.dmn_gamma[1]) option, nfreqs = self.option_nfreqs(option, sel_func_name=None) if type(option) is str and "turnover" in option: fc = parameter.Uniform(self.params.sn_fc[0],self.params.sn_fc[1]) pl = powerlaw_bpl(log10_A=log10_A, gamma=gamma, fc=fc, components=self.params.red_general_nfouriercomp) option_split = option.split("_") del option_split[option_split.index("turnover")] option = "_".join(option_split) if option.isdigit(): option = float(option) else: pl = utils.powerlaw(log10_A=log10_A, gamma=gamma, \ components=self.params.red_general_nfouriercomp) #idx_code = option.split"_").index("idx") + 1 if option=="vary": idx = parameter.Uniform(self.params.chrom_idx[0], \ self.params.chrom_idx[1]) else: idx = option chr_basis = gp_bases.createfourierdesignmatrix_chromatic(nmodes=nfreqs, Tspan=self.params.Tspan, idx=idx) chrn = gp_signals.BasisGP(pl, chr_basis, name='chromatic_gp') return chrn
def test_powerlaw_genmodes_prior(self): """Test that red noise signal returns correct values.""" # set up signal parameter pr = gp_priors.powerlaw_genmodes(log10_A=parameter.Uniform(-18, -12), gamma=parameter.Uniform(1, 7)) basis = gp_bases.createfourierdesignmatrix_chromatic(nmodes=30) rn = gp_signals.BasisGP(priorFunction=pr, basisFunction=basis, name="red_noise") rnm = rn(self.psr) # parameters log10_A, gamma = -14.5, 4.33 params = { "B1855+09_red_noise_log10_A": log10_A, "B1855+09_red_noise_gamma": gamma } # basis matrix test F, f2 = gp_bases.createfourierdesignmatrix_chromatic(self.psr.toas, self.psr.freqs, nmodes=30) msg = "F matrix incorrect for turnover." assert np.allclose(F, rnm.get_basis(params)), msg # spectrum test phi = gp_priors.powerlaw_genmodes(f2, log10_A=log10_A, gamma=gamma) msg = "Spectrum incorrect for turnover." assert np.all(rnm.get_phi(params) == phi), msg # inverse spectrum test msg = "Spectrum inverse incorrect for turnover." assert np.all(rnm.get_phiinv(params) == 1 / phi), msg # test shape msg = "F matrix shape incorrect" assert rnm.get_basis(params).shape == F.shape, msg
def solar_wind_block(n_earth=None, ACE_prior=False, include_swgp=True, swgp_prior=None, swgp_basis=None, Tspan=None): """ Returns Solar Wind DM noise model. Best model from Hazboun, et al (in prep) Contains a single mean electron density with an auxiliary perturbation modeled using a gaussian process. The GP has common prior parameters between all pulsars, but the realizations are different for all pulsars. Solar Wind DM noise modeled as a power-law with 30 sampling frequencies :param n_earth: Solar electron density at 1 AU. :param ACE_prior: Whether to use the ACE SWEPAM data as an astrophysical prior. :param swgp_prior: Prior function for solar wind Gaussian process. Default is a power law. :param swgp_basis: Basis to be used for solar wind Gaussian process. Options includes ['powerlaw'.'periodic','sq_exp'] :param Tspan: Sets frequency sampling f_i = i / Tspan. Default will use overall time span for individual pulsar. Default is to use 15 frequencies (1/Tspan,15/Tspan). """ if n_earth is None and not ACE_prior: n_earth = parameter.Uniform(0,30)('n_earth') elif n_earth is None and ACE_prior: n_earth = ACE_SWEPAM_Parameter()('n_earth') else: pass deter_sw = solar_wind(n_earth=n_earth) mean_sw = deterministic_signals.Deterministic(deter_sw, name='n_earth') sw_model = mean_sw if include_swgp: if swgp_basis == 'powerlaw': # dm noise parameters that are common log10_A_sw = parameter.Uniform(-10,1) gamma_sw = parameter.Uniform(-2,1) sw_prior = utils.powerlaw(log10_A=log10_A_sw, gamma=gamma_sw) if Tspan is not None: freqs = np.linspace(1/Tspan,30/Tspan,30) freqs = freqs[1/freqs > 1.5*yr_in_sec] sw_basis = createfourierdesignmatrix_solar_dm(modes=freqs) else: sw_basis = createfourierdesignmatrix_solar_dm(nmodes=15, Tspan=Tspan) elif swgp_basis == 'periodic': # Periodic GP kernel for DM log10_sigma = parameter.Uniform(-10, -6) log10_ell = parameter.Uniform(1, 4) log10_p = parameter.Uniform(-4, 1) log10_gam_p = parameter.Uniform(-3, 2) sw_basis = gpk.linear_interp_basis_dm(dt=6*86400) sw_prior = gpk.periodic_kernel(log10_sigma=log10_sigma, log10_ell=log10_ell, log10_gam_p=log10_gam_p, log10_p=log10_p) elif swgp_basis == 'sq_exp': # squared-exponential GP kernel for DM log10_sigma = parameter.Uniform(-10, -4) log10_ell = parameter.Uniform(1, 4) sw_basis = gpk.linear_interp_basis_dm(dt=6*86400) sw_prior = gpk.se_dm_kernel(log10_sigma=log10_sigma, log10_ell=log10_ell) gp_sw = gp_signals.BasisGP(sw_prior, sw_basis, name='gp_sw') sw_model += gp_sw return sw_model
def init_pta(params_all): """ Initiate enterprise signal models and enterprise.signals.signal_base.PTA. """ ptas = dict.fromkeys(params_all.models) for ii, params in params_all.models.items(): allpsr_model = params_all.noise_model_obj(psr=params_all.psrs, params=params) models = list() from_par_file = list() ecorrexists = np.zeros(len(params_all.psrs)) # Including parameters common for all pulsars if params.tm == 'default': tm = gp_signals.TimingModel() elif params.tm == 'ridge_regression': log10_variance = parameter.Uniform(-20, -10) basis = scaled_tm_basis() prior = ridge_prior(log10_variance=log10_variance) tm = gp_signals.BasisGP(prior, basis, name='ridge') # Adding common noise terms for all pulsars # Only those common signals are added that are listed in the noise model # file, getting Enterprise models from the noise model object. if 'm_all' in locals(): del m_all for psp, option in params.common_signals.items(): if 'm_all' in locals(): m_all += getattr(allpsr_model, psp)(option=option) else: m_all = tm + getattr(allpsr_model, psp)(option=option) # Including single pulsar noise models for pnum, psr in enumerate(params_all.psrs): singlepsr_model = params_all.noise_model_obj(psr=psr, params=params) # Determine if ecorr is mentioned in par file try: for key, val in psr.t2pulsar.noisemodel.items(): if key.startswith('ecorr') or key.startswith('ECORR'): ecorrexists[pnum] = True except Exception as pint_problem: print(pint_problem) ecorrexists[pnum] = False # Add noise models if psr.name in params.noisemodel.keys(): noise_model_dict_psr = params.noisemodel[psr.name] else: noise_model_dict_psr = params.universal for psp, option in noise_model_dict_psr.items(): if 'm_sep' in locals(): m_sep += getattr(singlepsr_model, psp)(option=option) elif 'm_all' in locals(): m_sep = m_all + getattr(singlepsr_model, psp)(option=option) else: m_sep = tm + getattr(singlepsr_model, psp)(option=option) models.append(m_sep(psr)) del m_sep pta = signal_base.PTA(models) if 'noisefiles' in params.__dict__.keys(): noisedict = get_noise_dict(psrlist=[p.name for p in params_all.psrs],\ noisefiles=params.noisefiles) print('For constant parameters using noise files in PAL2 format') pta.set_default_params(noisedict) print('Model',ii,'params (',len(pta.param_names),') in order: ', \ pta.param_names) if params.opts.mpi_regime != 2: np.savetxt(params.output_dir + '/pars.txt', pta.param_names, fmt='%s') ptas[ii] = pta return ptas
# backend selection selection = selections.Selection(selections.no_selection) ef = white_signals.MeasurementNoise(efac=efac, selection=selection) eq = white_signals.EquadNoise(log10_equad=equad, selection=selection) # red noise pl = utils.powerlaw(log10_A=parameter.Uniform(-18, -12), gamma=parameter.Uniform(1, 7)) rn = gp_signals.FourierBasisGP(spectrum=pl, components=30) # timing model basis = svd_tm_basis() prior = tm_prior() tm = gp_signals.BasisGP(prior, basis) # combined signal s = ef + eq + rn + tm outdirs = ['output_outlier', 'output_no_outlier'] for psr, outdir in zip(psrs, outdirs): # PTA pta = signal_base.PTA([s(psr)]) ## Set up different outlier models ## mdls = {} # emulate Vallisneri and van Haasteren mixture model
def chromatic_noise_block(gp_kernel='nondiag', psd='powerlaw', nondiag_kernel='periodic', prior='log-uniform', dt=15, df=200, idx=4, include_quadratic=False, Tspan=None, name='chrom', components=30, coefficients=False): """ Returns GP chromatic noise model : 1. Chromatic modeled with user defined PSD with 30 sampling frequencies. Available PSDs are ['powerlaw', 'turnover' 'spectrum'] :param gp_kernel: Whether to use a diagonal kernel for the GP. ['diag','nondiag'] :param nondiag_kernel: Which nondiagonal kernel to use for the GP. ['periodic','sq_exp','periodic_rfband','sq_exp_rfband'] :param psd: PSD to use for common red noise signal. Available options are ['powerlaw', 'turnover' 'spectrum'] :param prior: What type of prior to use for amplitudes. ['log-uniform','uniform'] :param dt: time-scale for linear interpolation basis (days) :param df: frequency-scale for linear interpolation basis (MHz) :param idx: Index of radio frequency dependence (i.e. DM is 2). Any float will work. :param include_quadratic: Whether to include a quadratic fit. :param name: Name of signal :param Tspan: Tspan from which to calculate frequencies for PSD-based GPs. :param components: Number of frequencies to use in 'diag' GPs. :param coefficients: Whether to keep coefficients of the GP. """ if gp_kernel == 'diag': chm_basis = gpb.createfourierdesignmatrix_chromatic(nmodes=components, Tspan=Tspan) if psd in ['powerlaw', 'turnover']: if prior == 'uniform': log10_A = parameter.LinearExp(-18, -11) elif prior == 'log-uniform': log10_A = parameter.Uniform(-18, -11) gamma = parameter.Uniform(0, 7) # PSD if psd == 'powerlaw': chm_prior = utils.powerlaw(log10_A=log10_A, gamma=gamma) elif psd == 'turnover': kappa = parameter.Uniform(0, 7) lf0 = parameter.Uniform(-9, -7) chm_prior = utils.turnover(log10_A=log10_A, gamma=gamma, lf0=lf0, kappa=kappa) if psd == 'spectrum': if prior == 'uniform': log10_rho = parameter.LinearExp(-10, -4, size=components) elif prior == 'log-uniform': log10_rho = parameter.Uniform(-10, -4, size=components) chm_prior = gpp.free_spectrum(log10_rho=log10_rho) elif gp_kernel == 'nondiag': if nondiag_kernel == 'periodic': # Periodic GP kernel for DM log10_sigma = parameter.Uniform(-10, -4) log10_ell = parameter.Uniform(1, 4) log10_p = parameter.Uniform(-4, 1) log10_gam_p = parameter.Uniform(-3, 2) chm_basis = gpk.linear_interp_basis_chromatic(dt=dt * const.day) chm_prior = gpk.periodic_kernel(log10_sigma=log10_sigma, log10_ell=log10_ell, log10_gam_p=log10_gam_p, log10_p=log10_p) elif nondiag_kernel == 'periodic_rfband': # Periodic GP kernel for DM with RQ radio-frequency dependence log10_sigma = parameter.Uniform(-10, -4) log10_ell = parameter.Uniform(1, 4) log10_ell2 = parameter.Uniform(2, 7) log10_alpha_wgt = parameter.Uniform(-4, 1) log10_p = parameter.Uniform(-4, 1) log10_gam_p = parameter.Uniform(-3, 2) chm_basis = gpk.get_tf_quantization_matrix(df=df, dt=dt * const.day, dm=True, idx=idx) chm_prior = gpk.tf_kernel(log10_sigma=log10_sigma, log10_ell=log10_ell, log10_gam_p=log10_gam_p, log10_p=log10_p, log10_alpha_wgt=log10_alpha_wgt, log10_ell2=log10_ell2) elif nondiag_kernel == 'sq_exp': # squared-exponential kernel for DM log10_sigma = parameter.Uniform(-10, -4) log10_ell = parameter.Uniform(1, 4) chm_basis = gpk.linear_interp_basis_chromatic(dt=dt * const.day, idx=idx) chm_prior = gpk.se_dm_kernel(log10_sigma=log10_sigma, log10_ell=log10_ell) elif nondiag_kernel == 'sq_exp_rfband': # Sq-Exp GP kernel for Chrom with RQ radio-frequency dependence log10_sigma = parameter.Uniform(-10, -4) log10_ell = parameter.Uniform(1, 4) log10_ell2 = parameter.Uniform(2, 7) log10_alpha_wgt = parameter.Uniform(-4, 1) dm_basis = gpk.get_tf_quantization_matrix(df=df, dt=dt * const.day, dm=True, idx=idx) dm_prior = gpk.sf_kernel(log10_sigma=log10_sigma, log10_ell=log10_ell, log10_alpha_wgt=log10_alpha_wgt, log10_ell2=log10_ell2) cgp = gp_signals.BasisGP(chm_prior, chm_basis, name=name + '_gp', coefficients=coefficients) if include_quadratic: # quadratic piece basis_quad = chrom.chromatic_quad_basis(idx=idx) prior_quad = chrom.chromatic_quad_prior() cquad = gp_signals.BasisGP(prior_quad, basis_quad, name=name + '_quad') cgp += cquad return cgp
def dm_noise_block(gp_kernel='diag', psd='powerlaw', nondiag_kernel='periodic', prior='log-uniform', dt=15, df=200, Tspan=None, components=30, gamma_val=None, coefficients=False): """ Returns DM noise model: 1. DM noise modeled as a power-law with 30 sampling frequencies :param psd: PSD function [e.g. powerlaw (default), spectrum, tprocess] :param prior: Prior on log10_A. Default if "log-uniform". Use "uniform" for upper limits. :param dt: time-scale for linear interpolation basis (days) :param df: frequency-scale for linear interpolation basis (MHz) :param Tspan: Sets frequency sampling f_i = i / Tspan. Default will use overall time span for indivicual pulsar. :param components: Number of frequencies in sampling of DM-variations. :param gamma_val: If given, this is the fixed slope of the power-law for powerlaw, turnover, or tprocess DM-variations """ # dm noise parameters that are common if gp_kernel == 'diag': if psd in ['powerlaw', 'turnover', 'tprocess', 'tprocess_adapt']: # parameters shared by PSD functions if prior == 'uniform': log10_A_dm = parameter.LinearExp(-20, -11) elif prior == 'log-uniform' and gamma_val is not None: if np.abs(gamma_val - 4.33) < 0.1: log10_A_dm = parameter.Uniform(-20, -11) else: log10_A_dm = parameter.Uniform(-20, -11) else: log10_A_dm = parameter.Uniform(-20, -11) if gamma_val is not None: gamma_dm = parameter.Constant(gamma_val) else: gamma_dm = parameter.Uniform(0, 7) # different PSD function parameters if psd == 'powerlaw': dm_prior = utils.powerlaw(log10_A=log10_A_dm, gamma=gamma_dm) elif psd == 'turnover': kappa_dm = parameter.Uniform(0, 7) lf0_dm = parameter.Uniform(-9, -7) dm_prior = utils.turnover(log10_A=log10_A_dm, gamma=gamma_dm, lf0=lf0_dm, kappa=kappa_dm) elif psd == 'tprocess': df = 2 alphas_dm = gpp.InvGamma(df / 2, df / 2, size=components) dm_prior = gpp.t_process(log10_A=log10_A_dm, gamma=gamma_dm, alphas=alphas_dm) elif psd == 'tprocess_adapt': df = 2 alpha_adapt_dm = gpp.InvGamma(df / 2, df / 2, size=1) nfreq_dm = parameter.Uniform(-0.5, 10 - 0.5) dm_prior = gpp.t_process_adapt(log10_A=log10_A_dm, gamma=gamma_dm, alphas_adapt=alpha_adapt_dm, nfreq=nfreq_dm) if psd == 'spectrum': if prior == 'uniform': log10_rho_dm = parameter.LinearExp(-10, -4, size=components) elif prior == 'log-uniform': log10_rho_dm = parameter.Uniform(-10, -4, size=components) dm_prior = gpp.free_spectrum(log10_rho=log10_rho_dm) dm_basis = utils.createfourierdesignmatrix_dm(nmodes=components, Tspan=Tspan) elif gp_kernel == 'nondiag': if nondiag_kernel == 'periodic': # Periodic GP kernel for DM log10_sigma = parameter.Uniform(-10, -4) log10_ell = parameter.Uniform(1, 4) log10_p = parameter.Uniform(-4, 1) log10_gam_p = parameter.Uniform(-3, 2) dm_basis = gpk.linear_interp_basis_dm(dt=dt * const.day) dm_prior = gpk.periodic_kernel(log10_sigma=log10_sigma, log10_ell=log10_ell, log10_gam_p=log10_gam_p, log10_p=log10_p) elif nondiag_kernel == 'periodic_rfband': # Periodic GP kernel for DM with RQ radio-frequency dependence log10_sigma = parameter.Uniform(-10, -4) log10_ell = parameter.Uniform(1, 4) log10_ell2 = parameter.Uniform(2, 7) log10_alpha_wgt = parameter.Uniform(-4, 1) log10_p = parameter.Uniform(-4, 1) log10_gam_p = parameter.Uniform(-3, 2) dm_basis = gpk.get_tf_quantization_matrix(df=df, dt=dt * const.day, dm=True) dm_prior = gpk.tf_kernel(log10_sigma=log10_sigma, log10_ell=log10_ell, log10_gam_p=log10_gam_p, log10_p=log10_p, log10_alpha_wgt=log10_alpha_wgt, log10_ell2=log10_ell2) elif nondiag_kernel == 'sq_exp': # squared-exponential GP kernel for DM log10_sigma = parameter.Uniform(-10, -4) log10_ell = parameter.Uniform(1, 4) dm_basis = gpk.linear_interp_basis_dm(dt=dt * const.day) dm_prior = gpk.se_dm_kernel(log10_sigma=log10_sigma, log10_ell=log10_ell) elif nondiag_kernel == 'sq_exp_rfband': # Sq-Exp GP kernel for DM with RQ radio-frequency dependence log10_sigma = parameter.Uniform(-10, -4) log10_ell = parameter.Uniform(1, 4) log10_ell2 = parameter.Uniform(2, 7) log10_alpha_wgt = parameter.Uniform(-4, 1) dm_basis = gpk.get_tf_quantization_matrix(df=df, dt=dt * const.day, dm=True) dm_prior = gpk.sf_kernel(log10_sigma=log10_sigma, log10_ell=log10_ell, log10_alpha_wgt=log10_alpha_wgt, log10_ell2=log10_ell2) elif nondiag_kernel == 'dmx_like': # DMX-like signal log10_sigma = parameter.Uniform(-10, -4) dm_basis = gpk.linear_interp_basis_dm(dt=dt * const.day) dm_prior = gpk.dmx_ridge_prior(log10_sigma=log10_sigma) dmgp = gp_signals.BasisGP(dm_prior, dm_basis, name='dm_gp', coefficients=coefficients) return dmgp
psd='powerlaw', prior='log-uniform', Tspan=None, components=10, gamma_val=None, coefficients=False) n_earth = SW.ACE_SWEPAM_Parameter()('n_earth') sw = SW.solar_wind(n_earth=n_earth) mean_sw = deterministic_signals.Deterministic(sw, name='mean_sw') log10_sigma = parameter.Uniform(-10, -4) log10_ell = parameter.Uniform(1, 4) dm_se_basis = models.linear_interp_basis_dm(dt=15 * 86400) dm_se_prior = models.se_dm_kernel(log10_sigma=log10_sigma, log10_ell=log10_ell) se = gp_signals.BasisGP(dm_se_prior, dm_se_basis, name='dm_gp') log10_A_sw = parameter.Uniform(-10, 1)('log10_A_sw') gamma_sw = parameter.Uniform(-2, 1)('gamma_sw') dm_sw_basis = SW.createfourierdesignmatrix_solar_dm(nmodes=15, Tspan=None) dm_sw_prior = utils.powerlaw(log10_A=log10_A_sw, gamma=gamma_sw) gp_sw = gp_signals.BasisGP(priorFunction=dm_sw_prior, basisFunction=dm_sw_basis, name='gp_sw') sw_models = [] sw_models.append(m + dm_gp1) #Model 0, Just DMGP sw_models.append(m + mean_sw) #Model 1, Just Deterministic SW sw_models.append(m + dm_gp2 + mean_sw) #Model 2, DMGP + Deter SW sw_models.append(m + mean_sw + gp_sw) #Model 3, Deter SW + SW GP sw_models.append(m + SW.solar_wind_block(ACE_prior=True, include_dmgp=False) + dm_gp2) #Model 4, All the things
def dm_noise_block(gp_kernel='diag', psd='powerlaw', nondiag_kernel='periodic', prior='log-uniform', Tspan=None, components=30, gamma_val=None): """ Returns DM noise model: 1. DM noise modeled as a power-law with 30 sampling frequencies :param psd: PSD function [e.g. powerlaw (default), turnover, free 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 components: Number of frequencies in sampling of DM-variations. :param gamma_val: If given, this is the fixed slope of the power-law for powerlaw or turnover DM-variations """ # dm noise parameters that are common if gp_kernel == 'diag': if psd in ['powerlaw', 'turnover']: # parameters shared by PSD functions if prior == 'uniform': log10_A_dm = parameter.LinearExp(-20, -11) elif prior == 'log-uniform' and gamma_val is not None: if np.abs(gamma_val - 4.33) < 0.1: log10_A_dm = parameter.Uniform(-20, -11) else: log10_A_dm = parameter.Uniform(-20, -11) else: log10_A_dm = parameter.Uniform(-20, -11) if gamma_val is not None: gamma_dm = parameter.Constant(gamma_val) else: gamma_dm = parameter.Uniform(0, 7) # different PSD function parameters if psd == 'powerlaw': dm_prior = utils.powerlaw(log10_A=log10_A_dm, gamma=gamma_dm) elif psd == 'turnover': kappa_dm = parameter.Uniform(0, 7) lf0_dm = parameter.Uniform(-9, -7) dm_prior = utils.turnover(log10_A=log10_A_dm, gamma=gamma_dm, lf0=lf0_dm, kappa=kappa_dm) if psd == 'spectrum': if prior == 'uniform': log10_rho_dm = parameter.LinearExp(-10, -4, size=components) elif prior == 'log-uniform': log10_rho_dm = parameter.Uniform(-10, -4, size=components) dm_prior = free_spectrum(log10_rho=log10_rho_dm) dm_basis = utils.createfourierdesignmatrix_dm(nmodes=components, Tspan=Tspan) elif gp_kernel == 'nondiag': if nondiag_kernel == 'periodic': # Periodic GP kernel for DM log10_sigma = parameter.Uniform(-10, -4) log10_ell = parameter.Uniform(1, 4) period = parameter.Uniform(0.2, 5.0) gam_p = parameter.Uniform(0.1, 30.0) dm_basis = linear_interp_basis_dm(dt=15 * const.day) dm_prior = periodic_kernel(log10_sigma=log10_sigma, log10_ell=log10_ell, gam_p=gam_p, p=period) elif nondiag_kernel == 'periodic_rfband': # Periodic GP kernel for DM with RQ radio-frequency dependence log10_sigma = parameter.Uniform(-10, -4) log10_ell = parameter.Uniform(1, 4) log10_ell2 = parameter.Uniform(2, 7) alpha_wgt = parameter.Uniform(0.2, 6) period = parameter.Uniform(0.2, 5.0) gam_p = parameter.Uniform(0.1, 30.0) dm_basis = get_tf_quantization_matrix(df=200, dt=15 * const.day, dm=True) dm_prior = tf_kernel(log10_sigma=log10_sigma, log10_ell=log10_ell, gam_p=gam_p, p=period, alpha_wgt=alpha_wgt, log10_ell2=log10_ell2) elif nondiag_kernel == 'dmx_like': # DMX-like signal log10_sigma = parameter.Uniform(-10, -4) dm_basis = linear_interp_basis_dm(dt=30 * const.day) dm_prior = dmx_ridge_prior(log10_sigma=log10_sigma) dmgp = gp_signals.BasisGP(dm_prior, dm_basis, name='dm_gp') return dmgp
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
orf = 'hd' else: orf = None gw = models.common_red_noise_block(psd=args.psd, prior=prior, Tspan=Tspan, orf=orf, gamma_val=args.gamma_gw, name='gw') model += gw log10_sigma = parameter.Uniform(-10, -4) log10_ell = parameter.Uniform(1, 4) dm_basis = linear_interp_basis_dm(dt=15 * 86400) dm_prior = se_dm_kernel(log10_sigma=log10_sigma, log10_ell=log10_ell) dm_gp = gp_signals.BasisGP(dm_prior, dm_basis, name='dm_gp') dm_block = dm_gp # Make solar wind signals print('sw_r2p ', args.sw_r2p) # if isinstance(args.sw_r2p,(float,int)): # args.sw_r2p = [args.sw_r2p] if args.sw_r2p_ranges is None: sw_r2p_ranges = args.sw_r2p elif len(args.sw_r2p) != len(args.sw_r2p_ranges): raise ValueError('Number of SW powers must match number of prior ranges!! ' 'Set # nonvarying ') else: sw_r2p_ranges = args.sw_r2p_ranges
# 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() rn = gp_signals.FourierBasisGP(spectrum=rn_pl, components=30, Tspan=Tspan) gwb = gp_signals.FourierBasisCommonGP(gwb_pl, orf, components=30, Tspan=Tspan, name='gw') tm = gp_signals.TimingModel(use_svd=True) be = deterministic_signals.PhysicalEphemerisSignal( # widen prior on jup orbit use_epoch_toas=True, jup_orb_elements=parameter.Uniform(-0.1, 0.1, size=6)('jup_orb_elements'))
ptas = {} all_kwargs = {} # Periodic GP kernel for DM log10_sigma = parameter.Uniform(-10, -4.8) log10_ell = parameter.Uniform(1, 2.4) log10_p = parameter.Uniform(-2, -1) log10_gam_p = parameter.Uniform(-2, 2) dm_basis = gpk.linear_interp_basis_dm(dt=3 * 86400) dm_prior = gpk.periodic_kernel(log10_sigma=log10_sigma, log10_ell=log10_ell, log10_gam_p=log10_gam_p, log10_p=log10_p) dmgp = gp_signals.BasisGP(dm_prior, dm_basis, name='dm_gp1') # Periodic GP kernel for DM log10_sigma2 = parameter.Uniform(-4.8, -3) log10_ell2 = parameter.Uniform(2.4, 5) log10_p2 = parameter.Uniform(-2, 2) log10_gam_p2 = parameter.Uniform(-2, 2) dm_basis2 = gpk.linear_interp_basis_dm(dt=3 * 86400) dm_prior2 = gpk.periodic_kernel(log10_sigma=log10_sigma2, log10_ell=log10_ell2, log10_gam_p=log10_gam_p2, log10_p=log10_p2) dmgp2 = gp_signals.BasisGP(dm_prior2, dm_basis2, name='dm_gp2')
def test_combine_signals(self): """Test for combining different signals.""" # set up signal parameter ecorr = parameter.Uniform(-10, -5) ec = gp_signals.EcorrBasisModel(log10_ecorr=ecorr) pl = utils.powerlaw(log10_A=parameter.Uniform(-18, -12), gamma=parameter.Uniform(1, 7)) rn = gp_signals.FourierBasisGP(spectrum=pl, components=30) 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") ts = gp_signals.TimingModel() s = ec + rn + ts + se m = s(self.psr) # parameters ecorr = -6.4 log10_A, gamma = -14.5, 4.33 log10_lam, log10_sigma = 7.4, -6.4 params = { "B1855+09_basis_ecorr_log10_ecorr": ecorr, "B1855+09_red_noise_log10_A": log10_A, "B1855+09_red_noise_gamma": gamma, "B1855+09_se_log10_lam": log10_lam, "B1855+09_se_log10_sigma": log10_sigma, } # combined basis matrix U = utils.create_quantization_matrix(self.psr.toas)[0] M = self.psr.Mmat.copy() norm = np.sqrt(np.sum(M ** 2, axis=0)) M /= norm F, f2 = utils.createfourierdesignmatrix_red(self.psr.toas, nmodes=30) U2, avetoas = create_quant_matrix(self.psr.toas, dt=7 * 86400) T = np.hstack((U, F, M, U2)) # combined prior vector jvec = 10 ** (2 * ecorr) * np.ones(U.shape[1]) phim = np.ones(self.psr.Mmat.shape[1]) * 1e40 phi = utils.powerlaw(f2, log10_A=log10_A, gamma=gamma) K = se_kernel(avetoas, log10_lam=log10_lam, log10_sigma=log10_sigma) phivec = np.concatenate((jvec, phi, phim)) phi = sl.block_diag(np.diag(phivec), K) phiinv = np.linalg.inv(phi) # basis matrix test msg = "Basis matrix incorrect for combined signal." assert np.allclose(T, m.get_basis(params)), msg # Kernal test msg = "Prior matrix incorrect for combined signal." assert np.allclose(m.get_phi(params), phi), msg # inverse Kernel test msg = "Prior matrix inverse incorrect for combined signal." assert np.allclose(m.get_phiinv(params), phiinv), msg # test shape msg = "Basis matrix shape incorrect size for combined signal." assert m.get_basis(params).shape == T.shape, msg
ptas = {} all_kwargs = {} # Periodic GP kernel for DM log10_sigma = parameter.Uniform(-10, -4.8) log10_ell = parameter.Uniform(1, 2.4) log10_p = parameter.Uniform(-2, -1) log10_gam_p = parameter.Uniform(-2, 2) dm_basis = gpk.linear_interp_basis_dm(dt=14*86400) dm_prior = gpk.periodic_kernel(log10_sigma=log10_sigma, log10_ell=log10_ell, log10_gam_p=log10_gam_p, log10_p=log10_p) dmgp = gp_signals.BasisGP(dm_prior, dm_basis, name='dm_gp1') # Periodic GP kernel for DM log10_sigma2 = parameter.Uniform(-4.8, -4) log10_ell2 = parameter.Uniform(2.4, 4) log10_p2 = parameter.Uniform(-2, 1) log10_gam_p2 = parameter.Uniform(-2, 2) dm_basis2 = gpk.linear_interp_basis_dm(dt=14*86400) dm_prior2 = gpk.periodic_kernel(log10_sigma=log10_sigma2, log10_ell=log10_ell2, log10_gam_p=log10_gam_p2, log10_p=log10_p2) dmgp2 = gp_signals.BasisGP(dm_prior2, dm_basis2, name='dm_gp2')
def solar_wind_block(n_earth=None, ACE_prior=False, include_dmgp=False, sw_prior=None, sw_basis=None, Tspan=None): """ Returns Solar Wind DM noise model. Best model from Hazboun, et al (in prep) Contains a single mean electron density with an auxiliary perturbation modeled using a gaussian process. The GP has common prior parameters between all pulsars, but the realizations are different for all pulsars. Solar Wind DM noise modeled as a power-law with 30 sampling frequencies :param n_earth: Solar electron density at 1 AU. :param ACE_prior: Whether to use the ACE SWEPAM data as an astrophysical prior. :param include_dmgp: Boolean flag to add in a simple power-law DM GP automatically. :param sw_prior: Prior function for solar wind Gaussian process. Default is a power law. :param sw_basis: Basis to be used for solar wind Gaussian process. Default is to use the built in function to creat a GP with 15 frequencies (1/Tspan,15/Tspan). :param Tspan: Sets frequency sampling f_i = i / Tspan. Default will use overall time span for indivicual pulsar. """ # dm noise parameters that are common if sw_prior is None: log10_A_sw = parameter.Uniform(-10, 1)('log10_A_sw') gamma_sw = parameter.Uniform(-2, 1)('gamma_sw') sw_prior = utils.powerlaw(log10_A=log10_A_sw, gamma=gamma_sw) if n_earth is None and ACE_prior: n_earth = parameter.Uniform(0, 30)('n_earth') elif n_earth is None and not ACE_prior: n_earth = ACE_SWEPAM_Parameter()('n_earth') else: pass if sw_basis is None: sw_basis = createfourierdesignmatrix_solar_dm(nmodes=15, Tspan=Tspan) else: pass gp_sw = gp_signals.BasisGP(sw_prior, sw_basis, name='gp_sw') deter_sw = solar_wind(n_earth=n_earth) mean_sw = deterministic_signals.Deterministic(deter_sw, name='n_earth') sw_model = mean_sw + gp_sw if include_dmgp: # DM GP signals log10_A_dm = parameter.Uniform(-20, -12) gamma_dm = parameter.Uniform(0, 7) dm_basis = utils.createfourierdesignmatrix_dm(nmodes=10, Tspan=Tspan, logf=True) dm_prior = utils.powerlaw(log10_A=log10_A_dm, gamma=gamma_dm) dmgp = gp_signals.BasisGP(dm_prior, dm_basis, name='dm_gp') sw_model += dmgp return sw_model
selection_ch = selections.Selection(channelized_backends) selection = selections.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_ch) # red noise (powerlaw with 5 frequencies) pl = utils.powerlaw(log10_A=log10_A, gamma=gamma) basis = utils.createfourierdesignmatrix_red(Tspan=Tspan, nmodes=args.nfreqs, logf=args.logf) rn = gp_signals.BasisGP(priorFunction=pl, name='red_noise', basisFunction=basis) # timing model tm = gp_signals.TimingModel(use_svd=False) model = tm + ef + eq + ec + rn if args.dm_gp_psrs[0] == args.psr: dm_basis = utils.createfourierdesignmatrix_dm(Tspan=Tspan, nmodes=args.nfreqs, logf=args.logf) dm_gp = gp_signals.BasisGP(priorFunction=pl, basisFunction=dm_basis, name='dm_gp') model += dm_gp
psrs.append(psr) save1 = np.load('noisepars.npy') save2 = np.load('noisepardict.npy') save3 = np.load('dpdmpars-maxposprob.npy') save4 = np.load('dpdmpardict.npy') Dict = {save2[i]: save1[i] for i in range(len(save2))} Dict.update({save4[i]: save3[i] for i in range(len(save4))}) # The Big Model # dm noise log10_A_dm = parameter.Constant() gamma_dm = parameter.Constant() pl_dm = utils.powerlaw(log10_A=log10_A_dm, gamma=gamma_dm) dm_basis = utils.createfourierdesignmatrix_dm(nmodes=50, Tspan=None) dmn = gp_signals.BasisGP(pl_dm, dm_basis, name='dm_gp', coefficients=False) # spin noise log10_A = parameter.Constant() gamma = parameter.Constant() pl = utils.powerlaw(log10_A=log10_A, gamma=gamma) selection = selections.Selection(selections.no_selection) spn = gp_signals.FourierBasisGP(pl, components=50, Tspan=None, coefficients=False, selection=selection, modes=None) dp = DPDM.dpdm_block(type_='Bayes') tm = gp_signals.TimingModel() eph = deterministic_signals.PhysicalEphemerisSignal(use_epoch_toas=True)
ptas = {} all_kwargs = {} # Periodic GP kernel for DM log10_sigma = parameter.Uniform(-4.4, -3) log10_ell = parameter.Uniform(3, 4) log10_p = parameter.Uniform(-1, 1) log10_gam_p = parameter.Uniform(-1.5, 1) dm_basis = gpk.linear_interp_basis_dm(dt=14 * 86400) dm_prior = gpk.periodic_kernel(log10_sigma=log10_sigma, log10_ell=log10_ell, log10_gam_p=log10_gam_p, log10_p=log10_p) dmgp2 = gp_signals.BasisGP(dm_prior, dm_basis, name='dm_gp2') @signal_base.function def chromatic_quad(toas, freqs, quad_coeff=np.ones(3) * 1e-10, idx=4): """ Basis for chromatic quadratic function. :param idx: index of chromatic dependence :return ret: normalized quadratic basis matrix [Ntoa, 3] """ t0 = (toas.max() + toas.min()) / 2 a, b, c = 10**quad_coeff[0], 10**quad_coeff[1], 10**quad_coeff[2] quad = (a * (toas - t0)**2 + b * (toas - t0) + c) * (1400 / freqs)**idx