def test_multinest(self): # Nested sampler tests # further decrease the parameter space for nested samplers to run faster fittingSequence = FittingSequence(self.kwargs_data_joint, self.kwargs_model, self.kwargs_constraints, self.kwargs_likelihood, self.kwargs_params) fitting_list = [] kwargs_update = { 'ps_add_fixed': [[0, ['ra_source', 'dec_source'], [0, 0]]], 'lens_light_add_fixed': [[ 0, ['n_sersic', 'R_sersic', 'center_x', 'center_y'], [4, .1, 0, 0] ]], 'source_add_fixed': [[ 0, ['R_sersic', 'e1', 'e2', 'center_x', 'center_y'], [.6, .1, .1, 0, 0] ]], 'lens_add_fixed': [[ 0, ['gamma', 'theta_E', 'e1', 'e2', 'center_x', 'center_y'], [1.8, 1., .1, .1, 0, 0] ], [1, ['gamma1', 'gamma2'], [0.01, 0.01]]], 'change_source_lower_limit': [[0, ['n_sersic'], [2.9]]], 'change_source_upper_limit': [[0, ['n_sersic'], [3.1]]] } fitting_list.append(['update_settings', kwargs_update]) kwargs_multinest = { 'sampler_type': 'MULTINEST', 'kwargs_run': { 'n_live_points': 10, 'evidence_tolerance': 0.5, 'sampling_efficiency': 0.8, # 1 for posterior-only, 0 for evidence-only 'importance_nested_sampling': False, 'multimodal': True, 'const_efficiency_mode': False, # reduce sampling_efficiency to 5% when True }, 'remove_output_dir': True, } fitting_list.append(['nested_sampling', kwargs_multinest]) chain_list2 = fittingSequence.fit_sequence(fitting_list) kwargs_fixed = fittingSequence._updateManager.fixed_kwargs npt.assert_almost_equal(kwargs_fixed[0][1]['gamma1'], 0.01, decimal=2) assert fittingSequence._updateManager._lower_kwargs[1][0][ 'n_sersic'] == 2.9 assert fittingSequence._updateManager._upper_kwargs[1][0][ 'n_sersic'] == 3.1 kwargs_test = {'kwargs_lens': 1} fittingSequence.update_state(kwargs_test) kwargs_out = fittingSequence.best_fit(bijective=True) assert kwargs_out['kwargs_lens'] == 1
def test_fitting_sequence(self): # kwargs_init = [self.kwargs_lens, self.kwargs_source, self.kwargs_lens_light, self.kwargs_ps] lens_sigma = [{ 'theta_E': 0.1, 'gamma': 0.1, 'e1': 0.1, 'e2': 0.1, 'center_x': 0.1, 'center_y': 0.1 }, { 'e1': 0.1, 'e2': 0.1 }] lens_lower = [{ 'theta_E': 0., 'gamma': 1.5, 'center_x': -2, 'center_y': -2, 'e1': -0.4, 'e2': -0.4 }, { 'e1': -0.3, 'e2': -0.3 }] lens_upper = [{ 'theta_E': 10., 'gamma': 2.5, 'center_x': 2, 'center_y': 2, 'e1': 0.4, 'e2': 0.4 }, { 'e1': 0.3, 'e2': 0.3 }] source_sigma = [{ 'R_sersic': 0.05, 'n_sersic': 0.5, 'center_x': 0.1, 'center_y': 0.1, 'e1': 0.1, 'e2': 0.1 }] source_lower = [{ 'R_sersic': 0.01, 'n_sersic': 0.5, 'center_x': -2, 'center_y': -2, 'e1': -0.4, 'e2': -0.4 }] source_upper = [{ 'R_sersic': 10, 'n_sersic': 5.5, 'center_x': 2, 'center_y': 2, 'e1': 0.4, 'e2': 0.4 }] lens_light_sigma = [{ 'R_sersic': 0.05, 'n_sersic': 0.5, 'center_x': 0.1, 'center_y': 0.1 }] lens_light_lower = [{ 'R_sersic': 0.01, 'n_sersic': 0.5, 'center_x': -2, 'center_y': -2 }] lens_light_upper = [{ 'R_sersic': 10, 'n_sersic': 5.5, 'center_x': 2, 'center_y': 2 }] ps_sigma = [{'ra_source': 1, 'dec_source': 1, 'point_amp': 1}] lens_param = self.kwargs_lens, lens_sigma, [{}, { 'ra_0': 0, 'dec_0': 0 }], lens_lower, lens_upper source_param = self.kwargs_source, source_sigma, [ {} ], source_lower, source_upper lens_light_param = self.kwargs_lens_light, lens_light_sigma, [{ 'center_x': 0 }], lens_light_lower, lens_light_upper ps_param = self.kwargs_ps, ps_sigma, [{} ], self.kwargs_ps, self.kwargs_ps kwargs_params = { 'lens_model': lens_param, 'source_model': source_param, 'lens_light_model': lens_light_param, 'point_source_model': ps_param, # 'cosmography': cosmo_param } # kwargs_params = [kwargs_init, kwargs_sigma, kwargs_fixed, kwargs_init, kwargs_init] image_band = [self.kwargs_data, self.kwargs_psf, self.kwargs_numerics] multi_band_list = [image_band] kwargs_data_joint = { 'multi_band_list': multi_band_list, 'multi_band_type': 'multi-linear' } fittingSequence = FittingSequence(kwargs_data_joint, self.kwargs_model, self.kwargs_constraints, self.kwargs_likelihood, kwargs_params) kwargs_result = fittingSequence.best_fit(bijective=False) lens_temp = kwargs_result['kwargs_lens'] npt.assert_almost_equal(lens_temp[0]['theta_E'], self.kwargs_lens[0]['theta_E'], decimal=2) logL = fittingSequence.best_fit_likelihood print(logL, 'test') #print(lens_temp, source_temp, lens_light_temp, ps_temp, cosmo_temp) assert logL < 0 bic = fittingSequence.bic assert bic > 0 #npt.assert_almost_equal(bic, 20000000220.29376, decimal=-4) #npt.assert_almost_equal(logL, -10000000061.792593, decimal=-4) n_p = 2 n_i = 2 fitting_list = [] kwargs_pso = { 'sigma_scale': 1, 'n_particles': n_p, 'n_iterations': n_i } fitting_list.append(['PSO', kwargs_pso]) kwargs_mcmc = { 'sigma_scale': 0.1, 'n_burn': 1, 'n_run': 1, 'walkerRatio': 2 } fitting_list.append(['MCMC', kwargs_mcmc]) kwargs_mcmc['re_use_samples'] = True fitting_list.append(['MCMC', kwargs_mcmc]) kwargs_mcmc['sampler_type'] = 'EMCEE' fitting_list.append(['MCMC', kwargs_mcmc]) kwargs_align = { 'lowerLimit': -0.1, 'upperLimit': 0.1, 'n_particles': 2, 'n_iterations': 2 } fitting_list.append(['align_images', kwargs_align]) kwargs_psf_iter = { 'num_iter': 2, 'psf_iter_factor': 0.5, 'stacking_method': 'mean' } fitting_list.append(['psf_iteration', kwargs_psf_iter]) fitting_list.append(['restart', None]) fitting_list.append(['fix_not_computed', {'free_bands': [True]}]) n_sersic_overwrite = 4 kwargs_update = { 'lens_light_add_fixed': [[0, ['n_sersic'], [n_sersic_overwrite]]], 'lens_light_remove_fixed': [[0, ['center_x']]], 'change_source_lower_limit': [[0, ['n_sersic'], [0.1]]], 'change_source_upper_limit': [[0, ['n_sersic'], [10]]] } fitting_list.append(['update_settings', kwargs_update]) #kwargs_model = {}, kwargs_constraints = {}, kwargs_likelihood = {}, lens_add_fixed = [], #source_add_fixed = [], lens_light_add_fixed = [], ps_add_fixed = [], cosmo_add_fixed = [], lens_remove_fixed = [], #source_remove_fixed = [], lens_light_remove_fixed = [], ps_remove_fixed = [], cosmo_remove_fixed = [] chain_list = fittingSequence.fit_sequence(fitting_list) lens_fixed, source_fixed, lens_light_fixed, ps_fixed, special_fixed, extinction_fixed = fittingSequence._updateManager._fixed_kwargs kwargs_result = fittingSequence.best_fit(bijective=False) npt.assert_almost_equal(kwargs_result['kwargs_lens'][0]['theta_E'], self.kwargs_lens[0]['theta_E'], decimal=1) npt.assert_almost_equal( fittingSequence._updateManager._lens_light_fixed[0]['n_sersic'], n_sersic_overwrite, decimal=8) npt.assert_almost_equal(lens_light_fixed[0]['n_sersic'], 4, decimal=-1) assert fittingSequence._updateManager._lower_kwargs[1][0][ 'n_sersic'] == 0.1 assert fittingSequence._updateManager._upper_kwargs[1][0][ 'n_sersic'] == 10 # Nested sampler tests # further decrease the parameter space for nested samplers to run faster fitting_list2 = [] kwargs_update2 = { 'ps_add_fixed': [[0, ['ra_source', 'dec_source'], [0, 0]]], 'lens_light_add_fixed': [[ 0, ['n_sersic', 'R_sersic', 'center_x', 'center_y'], [4, .1, 0, 0] ]], 'source_add_fixed': [[ 0, ['R_sersic', 'e1', 'e2', 'center_x', 'center_y'], [.6, .1, .1, 0, 0] ]], 'lens_add_fixed': [[ 0, ['gamma', 'theta_E', 'e1', 'e2', 'center_x', 'center_y'], [1.8, 1., .1, .1, 0, 0] ], [1, ['e1', 'e2'], [0.01, 0.01]]], 'change_source_lower_limit': [[0, ['n_sersic'], [2.9]]], 'change_source_upper_limit': [[0, ['n_sersic'], [3.1]]] } fitting_list2.append(['update_settings', kwargs_update2]) kwargs_multinest = { 'sampler_type': 'MULTINEST', 'kwargs_run': { 'n_live_points': 10, 'evidence_tolerance': 0.5, 'sampling_efficiency': 0.8, # 1 for posterior-only, 0 for evidence-only 'importance_nested_sampling': False, 'multimodal': True, 'const_efficiency_mode': False, # reduce sampling_efficiency to 5% when True }, 'remove_output_dir': True, } fitting_list2.append(['nested_sampling', kwargs_multinest]) kwargs_dynesty = { 'sampler_type': 'DYNESTY', 'kwargs_run': { 'dlogz_init': 0.01, 'nlive_init': 3, 'nlive_batch': 3, 'maxbatch': 1, }, } fitting_list2.append(['nested_sampling', kwargs_dynesty]) kwargs_dypolychord = { 'sampler_type': 'DYPOLYCHORD', 'kwargs_run': { 'ninit': 8, 'nlive_const': 10, #'seed_increment': 1, 'resume_dyn_run': False, #'init_step': 10, }, 'polychord_settings': { 'seed': 1, #'num_repeats': 20 }, 'dypolychord_dynamic_goal': 0.8, # 1 for posterior-only, 0 for evidence-only 'remove_output_dir': True, } fitting_list2.append(['nested_sampling', kwargs_dypolychord]) chain_list2 = fittingSequence.fit_sequence(fitting_list2) kwargs_fixed = fittingSequence._updateManager._fixed_kwargs npt.assert_almost_equal(kwargs_fixed[0][1]['e1'], 0.01, decimal=2) assert fittingSequence._updateManager._lower_kwargs[1][0][ 'n_sersic'] == 2.9 assert fittingSequence._updateManager._upper_kwargs[1][0][ 'n_sersic'] == 3.1 kwargs_test = {'kwargs_lens': 1} fittingSequence.update_state(kwargs_test) kwargs_out = fittingSequence.best_fit(bijective=True) assert kwargs_out['kwargs_lens'] == 1
class ClsrWorkflow(object): def __init__(self, kwargs_data_joint, kwargs_model,lens_params,source_params, lenslight_params=None, kwargs_constraints=None, kwargs_likelihood=None): """ class to manage cluster source reconstruction. This class inherited the FittingSequence class in Workflow module of lenstronomy. :param kwargs_data_joint: keywords arguments of [data, psf, numericals] in lenstronomy convention. :param kwargs_model: name of model list :param lens_params: lens model keywords arguments [kwargs_lens_init, kwargs_lens_sigma, kwargs_fixed_lens, kwargs_lower_lens, kwargs_upper_lens] :param source_params: source model keywords arguments [kwargs_source_init, kwargs_source_sigma, kwargs_fixed_source, kwargs_lower_source, kwargs_upper_source] :param kwargs_constraints: contraints on models :param kwargs_likelihood: options of calculating likelihood, see more: LikelihoodModule class in Sampling module of lenstronomy. """ self.kwargs_data_joint =kwargs_data_joint self.multi_band_list = kwargs_data_joint.get('multi_band_list', []) self.kwargs_model =kwargs_model kwargs_params = {'lens_model': lens_params, 'source_model': source_params, 'lens_light_model': lenslight_params} self.kwargs_params= kwargs_params if kwargs_constraints is None: kwargs_constraints ={} if kwargs_likelihood is None: kwargs_likelihood = {'source_marg': False, 'check_positive_flux': True} self.fitting_seq_src = FittingSequence(kwargs_data_joint, kwargs_model, kwargs_constraints, kwargs_likelihood, kwargs_params) def run_fit_sequence(self,fitting_kwargs_list): """ :param fitting_kwargs_list: list of [['string', {kwargs}], ..] with 'string being the specific fitting option and kwargs being the arguments passed to this option :return: fitting results """ chain_list = self.fitting_seq_src.fit_sequence(fitting_kwargs_list) kwargs_result = self.fitting_seq_src.best_fit(bijective=False) bic_model = self.fitting_seq_src.bic return bic_model,chain_list, kwargs_result def lensmodel_comp(self, num_img, n_particles,n_iterations,sigma_scale, num_lens_model,fixed_index =0,flexion_option=True): """ function to figure out the necessary of increasing lens model complexity. Currently, we only consider up to flexion term. :param n_particles: particles numbers of PSO :param n_iterations: iteration numbers of PSO :param sigma_scale: sigma scale for PSO :param num_img: int, numbers of lensed image :param fixed_index: int, index of fixed lensed image :param num_lens_model: numbers of strings contained in lens model list :param flexion_option: bool, default is taking flexion into consideration :return: pso results, fitting results of necessary lens model complexity, bic values """ lens_remove_fixed_list = [] lens_add_fixed_list = [] for i in range(num_img): if i == fixed_index: print ("lens model keep fixed in frame:", i+1) else: lens_flexion_index = (i + 1) * num_lens_model - 1 lens_remove_fixed_list.append([lens_flexion_index, ['G1', 'G2', 'F1', 'F2'], [0, 0, 0, 0]]) G1_fix = self.kwargs_params['lens_model'][2][lens_flexion_index]['G1'] G2_fix = self.kwargs_params['lens_model'][2][lens_flexion_index]['G2'] F1_fix = self.kwargs_params['lens_model'][2][lens_flexion_index]['F1'] F2_fix = self.kwargs_params['lens_model'][2][lens_flexion_index]['F2'] lens_add_fixed_list.append([lens_flexion_index, ['G1', 'G2', 'F1', 'F2'], [G1_fix, G2_fix, F1_fix, F2_fix]]) flexion_add_fixed = [['update_settings', {'lens_add_fixed': lens_add_fixed_list}]] print("flexion_fixed:", flexion_add_fixed) kwargs_pso = [['PSO', {'sigma_scale': sigma_scale, 'n_particles': n_particles, 'n_iterations': n_iterations}]] fitting_kwargs_fix = flexion_add_fixed+ kwargs_pso bic_model_fix, chain_list_fix, kwargs_result_fix = self.run_fit_sequence(fitting_kwargs_fix) if flexion_option: flexion_remove_fixed = [['update_settings', {'lens_remove_fixed': lens_remove_fixed_list}]] print ("flexion_remove_fixed:", flexion_remove_fixed) fitting_kwargs_free = flexion_remove_fixed + kwargs_pso bic_model_free, chain_list_free, kwargs_result_free = self.run_fit_sequence(fitting_kwargs_free) else: bic_model_free = 10000000 if bic_model_free > bic_model_fix: print ("No necessary to add flexion!") bic_list = [bic_model_fix] chain_list = [chain_list_fix] kwargs_result_list = [kwargs_result_fix] self._update_kwargs(kwargs_result_fix) _, _, _ = self.run_fit_sequence(flexion_add_fixed) elif bic_model_free < bic_model_fix: print("Flexion is needed!") bic_list = [bic_model_fix, bic_model_free] chain_list = [chain_list_fix] kwargs_result_list = [kwargs_result_fix] return chain_list, kwargs_result_list, bic_list def sourcemodel_comp(self, n_max_range=[0], sr = 0, n_particles=10, n_iterations=10,sigma_scale =1.0, bic_model_in = [100000], chain_list_in = [0], kwargs_results_in = [0], bic_option=True) : """ function to found the best fitting results among source models related to numbers of shapelets basis :param n_max_range: shapelets basis selection range :param sr: typical scale (") in source plane :param n_particles: particles numbers of PSO :param n_iterations: iteration numbers of PSO :param sigma_scale: sigma scale for PSO :param bic_model_in: BIC value of models before adding shapelets to source model :param chain_list_in: PSO chain results of models before adding shapelets to source model :param kwargs_results_in: fitting results of models before adding shapelets to source model :return: best-fit PSO results, best-fits results, PSO results for n_max_range, fitting results for n_max_range, bic values for all models """ bic_model_list = bic_model_in chain_list_list = chain_list_in kwargs_result_list = kwargs_results_in bic_in_len = len(bic_model_in) bic_run = True beta0 = sr kwargs_pso = [['PSO', {'sigma_scale': sigma_scale, 'n_particles': n_particles, 'n_iterations': n_iterations}]] for nmax in n_max_range: if nmax < 0: raise ValueError("nmax can not be negative!",nmax) else: if nmax == n_max_range[0]: start_kwargs_shapelet = [['update_settings', {'source_remove_fixed': [ [1, ['beta'], [beta0]] ]}]] else: start_kwargs_shapelet = [] beta_nmax = ((nmax + 1)) ** 0.5 * beta0 fit_kwargs_shapelet = [['update_settings', {'source_add_fixed': [[1, ['n_max'], [nmax]]], 'change_source_lower_limit': [[1, ['beta'], [beta_nmax]]] } ]] fitting_kwargs = start_kwargs_shapelet + fit_kwargs_shapelet + kwargs_pso if bic_run: print ("nmax",nmax,"fitting_kwargs",fitting_kwargs) bic_model,chain_list, kwargs_result = self.run_fit_sequence(fitting_kwargs) if bic_model > bic_model_list[-1]: if bic_option: bic_run = False if bic_model > bic_model_in[bic_in_len-1]: print ("bic_model_in",bic_model_in) print ("no necessary to add SHAPELETS !") fix_kwargs_shapelet=[['update_settings', {'source_add_fixed': [[1, ['beta'], [sr]]]}]] _, _, _ = self.run_fit_sequence(fix_kwargs_shapelet) elif not bic_option: chain_list_list.append(chain_list) kwargs_result_list.append(kwargs_result) bic_model_list.append(bic_model) print ("no necessary to increase model complexity!") elif bic_model < bic_model_list[-1]: chain_list_list.append(chain_list) kwargs_result_list.append(kwargs_result) bic_model_list.append(bic_model) print (bic_model, "currently is the lowest BIC value in bic_model_list=", bic_model_list) bic_sourcemodel = bic_model_list[bic_in_len:] if bic_sourcemodel ==[]: chain_list_lowest = chain_list_in[-1] kwargs_result_lowest = kwargs_results_in[-1] else: index_bic_minima = np.where(bic_model_list == np.min(bic_model_list))[0][0] chain_list_lowest = chain_list_list[index_bic_minima] kwargs_result_lowest = kwargs_result_list[index_bic_minima] return chain_list_lowest, kwargs_result_lowest, chain_list_list, kwargs_result_list, bic_model_list def _update_kwargs(self,kwargs_result): """ :param kwargs_result: fitting results of a specific state :return: go back to a specific state """ self.fitting_seq_src.update_state(kwargs_result)