def setup(self): np.random.seed(seed=41) self.z_L = 0.8 self.z_S = 3.0 self.H0_true = 70 self.omega_m_true = 0.3 self.cosmo = FlatLambdaCDM(H0=self.H0_true, Om0=self.omega_m_true, Ob0=0.05) lensCosmo = LensCosmo(self.z_L, self.z_S, cosmo=self.cosmo) self.Dd_true = lensCosmo.dd self.D_dt_true = lensCosmo.ddt self.sigma_Dd = 100 self.sigma_Ddt = 100 num_samples = 10000 self.D_dt_samples = np.random.normal(self.D_dt_true, self.sigma_Ddt, num_samples) self.D_d_samples = np.random.normal(self.Dd_true, self.sigma_Dd, num_samples) ani_param_array = np.linspace(0, 2, 10) ani_scaling_array = np.ones_like(ani_param_array) self.kwargs_lens_list = [{'z_lens': self.z_L, 'z_source': self.z_S, 'likelihood_type': 'DdtDdKDE', 'dd_samples': self.D_d_samples, 'ddt_samples': self.D_dt_samples, 'kde_type': 'scipy_gaussian', 'bandwidth': 1}, {'z_lens': self.z_L, 'z_source': self.z_S, 'likelihood_type': 'DsDdsGaussian', 'ds_dds_mean': lensCosmo.ds/lensCosmo.dds, 'ds_dds_sigma': 1, 'ani_param_array': ani_param_array, 'ani_scaling_array': ani_scaling_array}] self.likelihood = LensSampleLikelihood(kwargs_lens_list=self.kwargs_lens_list)
def __init__(self, kwargs_likelihood_list): """ :param kwargs_likelihood_list: list of likelihood kwargs of individual lenses consistent with the LensLikelihood module """ self._kwargs_likelihood_list = kwargs_likelihood_list self._sample_likelihood = LensSampleLikelihood(kwargs_likelihood_list)
class TestLensLikelihood(object): def setup(self): np.random.seed(seed=41) self.z_L = 0.8 self.z_S = 3.0 self.H0_true = 70 self.omega_m_true = 0.3 self.cosmo = FlatLambdaCDM(H0=self.H0_true, Om0=self.omega_m_true, Ob0=0.05) lensCosmo = LensCosmo(self.z_L, self.z_S, cosmo=self.cosmo) self.Dd_true = lensCosmo.dd self.D_dt_true = lensCosmo.ddt self.sigma_Dd = 100 self.sigma_Ddt = 100 num_samples = 10000 self.D_dt_samples = np.random.normal(self.D_dt_true, self.sigma_Ddt, num_samples) self.D_d_samples = np.random.normal(self.Dd_true, self.sigma_Dd, num_samples) ani_param_array = np.linspace(0, 2, 10) ani_scaling_array = np.ones_like(ani_param_array) self.kwargs_lens_list = [{'z_lens': self.z_L, 'z_source': self.z_S, 'likelihood_type': 'DdtDdKDE', 'dd_samples': self.D_d_samples, 'ddt_samples': self.D_dt_samples, 'kde_type': 'scipy_gaussian', 'bandwidth': 1}, {'z_lens': self.z_L, 'z_source': self.z_S, 'likelihood_type': 'DsDdsGaussian', 'ds_dds_mean': lensCosmo.ds/lensCosmo.dds, 'ds_dds_sigma': 1, 'ani_param_array': ani_param_array, 'ani_scaling_array': ani_scaling_array}] self.likelihood = LensSampleLikelihood(kwargs_lens_list=self.kwargs_lens_list) def test_log_likelihood(self): kwargs_lens = {'kappa_ext': 0, 'gamma_ppn': 1} kwargs_kin = {'a_ani': 1} logl = self.likelihood.log_likelihood(self.cosmo, kwargs_lens=kwargs_lens, kwargs_kin=kwargs_kin) cosmo = FlatLambdaCDM(H0=self.H0_true*0.99, Om0=self.omega_m_true, Ob0=0.05) logl_sigma = self.likelihood.log_likelihood(cosmo, kwargs_lens=kwargs_lens, kwargs_kin=kwargs_kin) npt.assert_almost_equal(logl - logl_sigma, 0.12, decimal=2) def test_num_data(self): num_data = self.likelihood.num_data() assert num_data == 3
class GoodnessOfFit(object): """ class to manage goodness of fit diagnostics """ def __init__(self, kwargs_likelihood_list): """ :param kwargs_likelihood_list: list of likelihood kwargs of individual lenses consistent with the LensLikelihood module """ self._kwargs_likelihood_list = kwargs_likelihood_list self._sample_likelihood = LensSampleLikelihood(kwargs_likelihood_list) def plot_ddt_fit(self, cosmo, kwargs_lens, kwargs_kin, color_measurement=None, color_prediction=None): """ plots the prediction and the uncorrelated error bars on the individual lenses currently works for likelihood classes 'TDKinGaussian', 'KinGaussian' :param cosmo: astropy.cosmology instance :param kwargs_lens: lens model parameter keyword arguments :param kwargs_kin: kinematics model keyword arguments :param color_measurement: color of measurement :param color_prediction: color of model prediction :return: fig, axes of matplotlib instance """ logL = self._sample_likelihood.log_likelihood(cosmo, kwargs_lens, kwargs_kin) print(logL, 'log likelihood') num_data = self._sample_likelihood.num_data() print(-logL * 2 / num_data, 'reduced chi2') ddt_name_list = [] ddt_model_mean_list = [] ddt_model_sigma_list = [] ddt_data_mean_list = [] ddt_data_sigma_list = [] for i, kwargs_likelihood in enumerate(self._kwargs_likelihood_list): name = kwargs_likelihood.get('name', 'lens ' + str(i)) likelihood = self._sample_likelihood._lens_list[i] ddt_mean_measurement, ddt_sigma_measurement = likelihood.ddt_measurement( ) if ddt_mean_measurement is not None: ddt_model_mean, ddt_model_sigma, dd_model_mean, dd_model_sigma = likelihood.ddt_dd_model_prediction( cosmo, kwargs_lens=kwargs_lens) ddt_name_list.append(name) ddt_model_mean_list.append(ddt_model_mean) ddt_model_sigma_list.append(ddt_model_sigma) ddt_data_mean_list.append(ddt_mean_measurement) ddt_data_sigma_list.append(ddt_sigma_measurement) f, ax = plt.subplots(1, 1, figsize=(len(ddt_name_list) / 1.5, 4)) ax.errorbar(np.arange(len(ddt_name_list)), ddt_data_mean_list, yerr=ddt_data_sigma_list, color=color_measurement, xerr=None, fmt='o', ecolor=None, elinewidth=None, capsize=None, barsabove=False, lolims=False, uplims=False, xlolims=False, xuplims=False, errorevery=1, capthick=None, data=None, label='measurement') ax.errorbar(np.arange(len(ddt_name_list)), ddt_model_mean_list, yerr=ddt_model_sigma_list, color=color_prediction, xerr=None, fmt='o', ecolor=None, elinewidth=None, capsize=None, barsabove=False, lolims=False, uplims=False, xlolims=False, xuplims=False, errorevery=1, capthick=None, data=None, label='prediction') ax.set_xticks(ticks=np.arange(len(ddt_name_list))) ax.set_xticklabels(labels=ddt_name_list, rotation='vertical') ax.set_ylabel(r'$D_{\Delta t}$ [Mpc]', fontsize=15) ax.legend() return f, ax def kin_fit(self, cosmo, kwargs_lens, kwargs_kin): """ plots the prediction and the uncorrelated error bars on the individual lenses currently works for likelihood classes 'TDKinGaussian', 'KinGaussian' :param cosmo: astropy.cosmology instance :param kwargs_lens: lens model parameter keyword arguments :param kwargs_kin: kinematics model keyword arguments :return: list of name, measurement, measurement errors, model prediction, model prediction error """ sigma_v_name_list = [] sigma_v_measurement_list = [] sigma_v_measurement_error_list = [] sigma_v_model_list = [] sigma_v_model_error_list = [] for i, kwargs_likelihood in enumerate(self._kwargs_likelihood_list): name = kwargs_likelihood.get('name', 'lens ' + str(i)) likelihood = self._sample_likelihood._lens_list[i] sigma_v_measurement, cov_error_measurement, sigma_v_predict_mean, cov_error_predict = likelihood.sigma_v_measured_vs_predict( cosmo, kwargs_lens=kwargs_lens, kwargs_kin=kwargs_kin) if sigma_v_measurement is not None: num = len(sigma_v_measurement) for k in range(num): sigma_v = sigma_v_measurement[k] sigma_v_sigma = np.sqrt(cov_error_measurement[k, k]) sigma_v_predict = sigma_v_predict_mean[k] sigma_v_sigma_model = np.sqrt(cov_error_predict[k, k]) sigma_v_name_list.append(name) sigma_v_measurement_list.append(sigma_v) sigma_v_measurement_error_list.append(sigma_v_sigma) sigma_v_model_list.append(sigma_v_predict) sigma_v_model_error_list.append(sigma_v_sigma_model) return sigma_v_name_list, sigma_v_measurement_list, sigma_v_measurement_error_list, sigma_v_model_list, sigma_v_model_error_list def plot_kin_fit(self, cosmo, kwargs_lens, kwargs_kin, color_measurement=None, color_prediction=None): """ plots the prediction and the uncorrelated error bars on the individual lenses currently works for likelihood classes 'TDKinGaussian', 'KinGaussian' :param cosmo: astropy.cosmology instance :param kwargs_lens: lens model parameter keyword arguments :param kwargs_kin: kinematics model keyword arguments :param color_measurement: color of measurement :param color_prediction: color of model prediction :return: fig, axes of matplotlib instance """ logL = self._sample_likelihood.log_likelihood(cosmo, kwargs_lens, kwargs_kin) print(logL, 'log likelihood') sigma_v_name_list, sigma_v_measurement_list, sigma_v_measurement_error_list, sigma_v_model_list, sigma_v_model_error_list = self.kin_fit( cosmo, kwargs_lens, kwargs_kin) f, ax = plt.subplots(1, 1, figsize=(int(len(sigma_v_name_list) / 2), 4)) ax.errorbar(np.arange(len(sigma_v_name_list)), sigma_v_measurement_list, yerr=sigma_v_measurement_error_list, xerr=None, fmt='o', ecolor=None, elinewidth=None, color=color_measurement, capsize=5, barsabove=False, lolims=False, uplims=False, xlolims=False, xuplims=False, errorevery=1, capthick=None, data=None, label='measurement') ax.errorbar(np.arange(len(sigma_v_name_list)), sigma_v_model_list, color=color_prediction, yerr=sigma_v_model_error_list, xerr=None, fmt='o', ecolor=None, elinewidth=None, label='prediction', capsize=5) ax.set_xticks(ticks=np.arange(len(sigma_v_name_list))) ax.set_xticklabels(labels=sigma_v_name_list, rotation='vertical') ax.set_ylabel(r'$\sigma^{\rm P}$ [km/s]', fontsize=15) ax.legend() return f, ax def plot_ifu_fit(self, ax, cosmo, kwargs_lens, kwargs_kin, lens_index, radial_bin_size, show_legend=True, color_measurement=None, color_prediction=None): """ plot an individual IFU data goodness of fit :param ax: matplotlib axes instance :param cosmo: astropy.cosmology instance :param kwargs_lens: lens model parameter keyword arguments :param kwargs_kin: kinematics model keyword arguments :param lens_index: int, index in kwargs_lens to be plotted (needs to by of type 'IFUKinCov') :param radial_bin_size: radial bin size in arc seconds :param show_legend: bool, to show legend :param color_measurement: color of measurement :param color_prediction: color of model prediction :return: figure as axes instance """ kwargs_likelihood = self._kwargs_likelihood_list[lens_index] name = kwargs_likelihood.get('name', 'lens ' + str(lens_index)) likelihood = self._sample_likelihood._lens_list[lens_index] if not likelihood.likelihood_type == 'IFUKinCov': raise ValueError( 'likelihood type of lens %s is %s. Must be "IFUKinCov"' % (name, likelihood.likelihood_type)) sigma_v_measurement, cov_error_measurement, sigma_v_predict_mean, cov_error_predict = likelihood.sigma_v_measured_vs_predict( cosmo, kwargs_lens=kwargs_lens, kwargs_kin=kwargs_kin) r_bins = radial_bin_size / 2. + np.arange(len(sigma_v_measurement)) ax.errorbar(r_bins, sigma_v_measurement, yerr=np.sqrt(np.diag(cov_error_measurement)), xerr=radial_bin_size / 2., fmt='o', label='data', capsize=5, color=color_measurement) ax.errorbar(r_bins, sigma_v_predict_mean, yerr=np.sqrt(np.diag(cov_error_predict)), xerr=radial_bin_size / 2., fmt='o', label='model', capsize=5, color=color_prediction) if show_legend is True: ax.legend(fontsize=20) ax.set_title(name, fontsize=20) ax.set_ylabel(r'$\sigma^{\rm P}$[km/s]', fontsize=20) ax.set_xlabel('radial bin [arcsec]', fontsize=20) return ax
class CosmoLikelihood(object): """ this class contains the likelihood function of the Strong lensing analysis """ def __init__(self, kwargs_likelihood_list, cosmology, kwargs_bounds, sne_likelihood=None, ppn_sampling=False, lambda_mst_sampling=False, lambda_mst_distribution='delta', anisotropy_sampling=False, kappa_ext_sampling=False, kappa_ext_distribution='NONE', alpha_lambda_sampling=False, lambda_ifu_sampling=False, lambda_ifu_distribution='NONE', sigma_v_systematics=False, sne_sampling=False, sne_distribution='GAUSSIAN', log_scatter=False, anisotropy_model='OM', anisotropy_distribution='NONE', custom_prior=None, interpolate_cosmo=True, num_redshift_interp=100, cosmo_fixed=None): """ :param kwargs_likelihood_list: keyword argument list specifying the arguments of the LensLikelihood class :param cosmology: string describing cosmological model :param kwargs_bounds: keyword arguments of the lower and upper bounds and parameters that are held fixed. Includes: 'kwargs_lower_lens', 'kwargs_upper_lens', 'kwargs_fixed_lens', 'kwargs_lower_kin', 'kwargs_upper_kin', 'kwargs_fixed_kin' 'kwargs_lower_cosmo', 'kwargs_upper_cosmo', 'kwargs_fixed_cosmo' :param sne_likelihood: (string), optional. Sampling supernovae relative expansion history likelihood, see SneLikelihood module for options :param ppn_sampling:post-newtonian parameter sampling :param lambda_mst_sampling: bool, if True adds a global mass-sheet transform parameter in the sampling :param lambda_mst_distribution: string, defines the distribution function of lambda_mst :param lambda_ifu_sampling: bool, if True samples a separate lambda_mst for a second (e.g. IFU) data set independently :param lambda_ifu_distribution: string, distribution function of the lambda_ifu parameter :param alpha_lambda_sampling: bool, if True samples a parameter alpha_lambda, which scales lambda_mst linearly according to a predefined quantity of the lens :param kappa_ext_sampling: bool, if True samples a global external convergence parameter :param kappa_ext_distribution: string, distribution function of the kappa_ext parameter :param anisotropy_sampling: bool, if True adds a global stellar anisotropy parameter that alters the single lens kinematic prediction :param anisotropy_model: string, specifies the stellar anisotropy model :param anisotropy_distribution: string, distribution of the anisotropy parameters :param sigma_v_systematics: bool, if True samples paramaters relative to systematics in the velocity dispersion measurement :param sne_sampling: boolean, if True, samples/queries SNe unlensed magnitude distribution (not intrinsic magnitudes but apparent!) :param sne_distribution: string, apparent non-lensed brightness distribution (in linear space). Currently supports: 'GAUSSIAN': Gaussian distribution :param log_scatter: boolean, if True, samples the Gaussian scatter amplitude in log space (and thus flat prior in log) :param custom_prior: None or a definition that takes the keywords from the CosmoParam conventions and returns a log likelihood value (e.g. prior) :param interpolate_cosmo: bool, if True, uses interpolated comoving distance in the calculation for speed-up :param num_redshift_interp: int, number of redshift interpolation steps :param cosmo_fixed: astropy.cosmology instance to be used and held fixed throughout the sampling """ self._cosmology = cosmology self._kwargs_lens_list = kwargs_likelihood_list self._likelihoodLensSample = LensSampleLikelihood( kwargs_likelihood_list) self.param = ParamManager( cosmology, ppn_sampling=ppn_sampling, lambda_mst_sampling=lambda_mst_sampling, lambda_mst_distribution=lambda_mst_distribution, lambda_ifu_sampling=lambda_ifu_sampling, lambda_ifu_distribution=lambda_ifu_distribution, alpha_lambda_sampling=alpha_lambda_sampling, sne_sampling=sne_sampling, sne_distribution=sne_distribution, sigma_v_systematics=sigma_v_systematics, kappa_ext_sampling=kappa_ext_sampling, kappa_ext_distribution=kappa_ext_distribution, anisotropy_sampling=anisotropy_sampling, anisotropy_model=anisotropy_model, anisotropy_distribution=anisotropy_distribution, log_scatter=log_scatter, **kwargs_bounds) self._lower_limit, self._upper_limit = self.param.param_bounds self._prior_add = False if custom_prior is not None: self._prior_add = True self._custom_prior = custom_prior self._interpolate_cosmo = interpolate_cosmo self._num_redshift_interp = num_redshift_interp self._cosmo_fixed = cosmo_fixed z_max = 0 if sne_likelihood is not None: self._sne_likelihood = SneLikelihood(sample_name=sne_likelihood) z_max = np.max(self._sne_likelihood.zcmb) self._sne_evaluate = True else: self._sne_evaluate = False for kwargs_lens in kwargs_likelihood_list: if kwargs_lens['z_source'] > z_max: z_max = kwargs_lens['z_source'] self._z_max = z_max def likelihood(self, args): """ :param args: list of sampled parameters :return: log likelihood of the combined lenses """ for i in range(0, len(args)): if args[i] < self._lower_limit[i] or args[i] > self._upper_limit[i]: return -np.inf kwargs_cosmo, kwargs_lens, kwargs_kin, kwargs_source = self.param.args2kwargs( args) if self._cosmology == "oLCDM": # assert we are not in a crazy cosmological situation that prevents computing the angular distance integral h0, ok, om = kwargs_cosmo['h0'], kwargs_cosmo['ok'], kwargs_cosmo[ 'om'] if np.any([ ok * (1.0 + lens['z_source'])**2 + om * (1.0 + lens['z_source'])**3 + (1.0 - om - ok) <= 0 for lens in self._kwargs_lens_list ]): return -np.inf # make sure that Omega_DE is not negative... if 1.0 - om - ok <= 0: return -np.inf cosmo = self.cosmo_instance(kwargs_cosmo) logL = self._likelihoodLensSample.log_likelihood( cosmo=cosmo, kwargs_lens=kwargs_lens, kwargs_kin=kwargs_kin, kwargs_source=kwargs_source) if self._sne_evaluate is True: logL += self._sne_likelihood.log_likelihood(cosmo=cosmo) if self._prior_add is True: logL += self._custom_prior(kwargs_cosmo, kwargs_lens, kwargs_kin) return logL def cosmo_instance(self, kwargs_cosmo): """ :param kwargs_cosmo: cosmology parameter keyword argument list :return: astropy.cosmology (or equivalent interpolation scheme class) """ if self._cosmo_fixed is None: cosmo = self.param.cosmo(kwargs_cosmo) if self._interpolate_cosmo is True: cosmo = CosmoInterp(cosmo=cosmo, z_stop=self._z_max, num_interp=self._num_redshift_interp) else: if self._interpolate_cosmo is True: if not hasattr(self, '_cosmo_fixed_interp'): self._cosmo_fixed_interp = CosmoInterp( cosmo=self._cosmo_fixed, z_stop=self._z_max, num_interp=self._num_redshift_interp) cosmo = self._cosmo_fixed_interp else: cosmo = self._cosmo_fixed return cosmo
def __init__(self, kwargs_likelihood_list, cosmology, kwargs_bounds, sne_likelihood=None, ppn_sampling=False, lambda_mst_sampling=False, lambda_mst_distribution='delta', anisotropy_sampling=False, kappa_ext_sampling=False, kappa_ext_distribution='NONE', alpha_lambda_sampling=False, lambda_ifu_sampling=False, lambda_ifu_distribution='NONE', sigma_v_systematics=False, sne_sampling=False, sne_distribution='GAUSSIAN', log_scatter=False, anisotropy_model='OM', anisotropy_distribution='NONE', custom_prior=None, interpolate_cosmo=True, num_redshift_interp=100, cosmo_fixed=None): """ :param kwargs_likelihood_list: keyword argument list specifying the arguments of the LensLikelihood class :param cosmology: string describing cosmological model :param kwargs_bounds: keyword arguments of the lower and upper bounds and parameters that are held fixed. Includes: 'kwargs_lower_lens', 'kwargs_upper_lens', 'kwargs_fixed_lens', 'kwargs_lower_kin', 'kwargs_upper_kin', 'kwargs_fixed_kin' 'kwargs_lower_cosmo', 'kwargs_upper_cosmo', 'kwargs_fixed_cosmo' :param sne_likelihood: (string), optional. Sampling supernovae relative expansion history likelihood, see SneLikelihood module for options :param ppn_sampling:post-newtonian parameter sampling :param lambda_mst_sampling: bool, if True adds a global mass-sheet transform parameter in the sampling :param lambda_mst_distribution: string, defines the distribution function of lambda_mst :param lambda_ifu_sampling: bool, if True samples a separate lambda_mst for a second (e.g. IFU) data set independently :param lambda_ifu_distribution: string, distribution function of the lambda_ifu parameter :param alpha_lambda_sampling: bool, if True samples a parameter alpha_lambda, which scales lambda_mst linearly according to a predefined quantity of the lens :param kappa_ext_sampling: bool, if True samples a global external convergence parameter :param kappa_ext_distribution: string, distribution function of the kappa_ext parameter :param anisotropy_sampling: bool, if True adds a global stellar anisotropy parameter that alters the single lens kinematic prediction :param anisotropy_model: string, specifies the stellar anisotropy model :param anisotropy_distribution: string, distribution of the anisotropy parameters :param sigma_v_systematics: bool, if True samples paramaters relative to systematics in the velocity dispersion measurement :param sne_sampling: boolean, if True, samples/queries SNe unlensed magnitude distribution (not intrinsic magnitudes but apparent!) :param sne_distribution: string, apparent non-lensed brightness distribution (in linear space). Currently supports: 'GAUSSIAN': Gaussian distribution :param log_scatter: boolean, if True, samples the Gaussian scatter amplitude in log space (and thus flat prior in log) :param custom_prior: None or a definition that takes the keywords from the CosmoParam conventions and returns a log likelihood value (e.g. prior) :param interpolate_cosmo: bool, if True, uses interpolated comoving distance in the calculation for speed-up :param num_redshift_interp: int, number of redshift interpolation steps :param cosmo_fixed: astropy.cosmology instance to be used and held fixed throughout the sampling """ self._cosmology = cosmology self._kwargs_lens_list = kwargs_likelihood_list self._likelihoodLensSample = LensSampleLikelihood( kwargs_likelihood_list) self.param = ParamManager( cosmology, ppn_sampling=ppn_sampling, lambda_mst_sampling=lambda_mst_sampling, lambda_mst_distribution=lambda_mst_distribution, lambda_ifu_sampling=lambda_ifu_sampling, lambda_ifu_distribution=lambda_ifu_distribution, alpha_lambda_sampling=alpha_lambda_sampling, sne_sampling=sne_sampling, sne_distribution=sne_distribution, sigma_v_systematics=sigma_v_systematics, kappa_ext_sampling=kappa_ext_sampling, kappa_ext_distribution=kappa_ext_distribution, anisotropy_sampling=anisotropy_sampling, anisotropy_model=anisotropy_model, anisotropy_distribution=anisotropy_distribution, log_scatter=log_scatter, **kwargs_bounds) self._lower_limit, self._upper_limit = self.param.param_bounds self._prior_add = False if custom_prior is not None: self._prior_add = True self._custom_prior = custom_prior self._interpolate_cosmo = interpolate_cosmo self._num_redshift_interp = num_redshift_interp self._cosmo_fixed = cosmo_fixed z_max = 0 if sne_likelihood is not None: self._sne_likelihood = SneLikelihood(sample_name=sne_likelihood) z_max = np.max(self._sne_likelihood.zcmb) self._sne_evaluate = True else: self._sne_evaluate = False for kwargs_lens in kwargs_likelihood_list: if kwargs_lens['z_source'] > z_max: z_max = kwargs_lens['z_source'] self._z_max = z_max