def test_physical_model_from_data(mock_physical_params, mock_exp, test_reflections): """Test that it passes the correct dict to physical model.""" physicalmodel = PhysicalScalingModel.from_data( mock_physical_params, mock_exp, test_reflections ) assert physicalmodel.configdict["lmax"] == (mock_physical_params.physical.lmax) assert physicalmodel.components["absorption"].n_params == 24 assert list(physicalmodel.components["absorption"].parameters) == [0.0] * 24
def test_model_creation_from_data(default_params, mock_exp, test_reflections): """Test the factory creation of the three standard scaling models with the default params.""" _ = KBScalingModel.from_data(default_params, [], []) _ = PhysicalScalingModel.from_data(default_params, mock_exp, test_reflections) _ = ArrayScalingModel.from_data(default_params, mock_exp, test_reflections)
def plot_scaling_models(scaling_model_dict): d = OrderedDict() if scaling_model_dict["__id__"] == "physical": model = PhysicalScalingModel.from_dict(scaling_model_dict) d.update(_plot_smooth_scales(model)) if "absorption" in model.components: d.update(plot_absorption_parameters(model)) d.update(plot_absorption_surface(model)) return d
def test_physical_model_from_data(mock_physical_params, mock_exp, test_reflections): """Test that it passes the correct dict to physical model.""" physicalmodel = PhysicalScalingModel.from_data(mock_physical_params, mock_exp, test_reflections) assert physicalmodel.configdict["lmax"] == ( mock_physical_params.physical.lmax) assert physicalmodel.components["absorption"].n_params == 24 assert list( physicalmodel.components["absorption"].parameters) == [0.0] * 24 # test updating the absorption parameters mock_physical_params.physical.absorption_level = "high" physicalmodel.update(mock_physical_params) assert len(physicalmodel.components["absorption"].parameters) == 48 assert physicalmodel.configdict["abs_surface_weight"] == 5e3 mock_physical_params.physical.absorption_level = "medium" physicalmodel.update(mock_physical_params) assert len(physicalmodel.components["absorption"].parameters) == 48 assert physicalmodel.configdict["abs_surface_weight"] == 5e4 mock_physical_params.physical.absorption_level = None mock_physical_params.physical.lmax = 4 physicalmodel.update(mock_physical_params) assert len(physicalmodel.components["absorption"].parameters) == 24 assert physicalmodel.configdict["abs_surface_weight"] == 5e4 mock_physical_params.physical.surface_weight = 1e5 physicalmodel.update(mock_physical_params) assert len(physicalmodel.components["absorption"].parameters) == 24 assert physicalmodel.configdict["abs_surface_weight"] == 1e5 # try fixing a parameter mock_physical_params.physical.correction.fix = ["decay"] physicalmodel = PhysicalScalingModel.from_data(mock_physical_params, mock_exp, test_reflections) assert physicalmodel.configdict["lmax"] == ( mock_physical_params.physical.lmax) assert physicalmodel.components["absorption"].n_params == 24 assert list( physicalmodel.components["absorption"].parameters) == [0.0] * 24 assert physicalmodel.fixed_components == ["decay"]
def test_create_scaling_model(): """Test the create scaling model function.""" # Test that one can create the correct scaling model with the phil param. for m in ["physical", "array", "KB"]: params = generated_param() exp = generated_exp() rt = generated_refl() params.model = m new_exp = create_scaling_model(params, exp, [rt]) assert new_exp[0].scaling_model.id_ == m # If a scaling model already exists, then nothing else should happen. params = generated_param() exp = generated_exp() rt = generated_refl() exp[0].scaling_model = PhysicalScalingModel.from_data(params, exp[0], rt) old_scaling_model = exp[0].scaling_model params.model = "KB" new_exp = create_scaling_model(params, exp, [rt]) new_scaling_model = new_exp[0].scaling_model assert new_scaling_model is old_scaling_model # Should not modify original. # Test multiple datasets, where one already has a scaling model. exp = generated_exp(3) params = generated_param() rt = generated_refl() rt_2 = generated_refl() rt_3 = generated_refl() exp[0].scaling_model = PhysicalScalingModel.from_data(params, exp[0], rt) params.model = "KB" new_exp = create_scaling_model(params, exp, [rt, rt_2, rt_3]) assert new_exp[0].scaling_model is exp[0].scaling_model assert isinstance(new_exp[1].scaling_model, KBScalingModel) assert isinstance(new_exp[2].scaling_model, KBScalingModel) # Now test overwrite_existing_models option params.overwrite_existing_models = True params.model = "physical" newer_exp = create_scaling_model(params, new_exp, [rt, rt_2, rt_3]) for exp in newer_exp: assert isinstance(exp.scaling_model, PhysicalScalingModel)
def test_target_gradient_calculation_finite_difference(small_reflection_table, single_exp, physical_param): """Test the calculated gradients against a finite difference calculation.""" model = PhysicalScalingModel.from_data(physical_param, single_exp, small_reflection_table) # need to 'add_data' model.configure_components(small_reflection_table, single_exp, physical_param) model.components["scale"].update_reflection_data() model.components["decay"].update_reflection_data() apm = multi_active_parameter_manager( ScalingTarget(), [model.components], [["scale", "decay"]], scaling_active_parameter_manager, ) model.components["scale"].inverse_scales = flex.double([2.0, 1.0, 2.0]) model.components["decay"].inverse_scales = flex.double([1.0, 1.0, 0.4]) Ih_table = IhTable([small_reflection_table], single_exp.crystal.get_space_group()) with patch.object(SingleScaler, "__init__", lambda x, y, z, k: None): scaler = SingleScaler(None, None, None) scaler._Ih_table = Ih_table # Now do finite difference check. target = ScalingTarget() scaler.update_for_minimisation(apm, 0) grad = target.calculate_gradients(scaler.Ih_table.blocked_data_list[0]) res = target.calculate_residuals(scaler.Ih_table.blocked_data_list[0]) assert (res > 1e-8), """residual should not be zero, or the gradient test below will not really be working!""" # Now compare to finite difference f_d_grad = calculate_gradient_fd(target, scaler, apm) print(list(f_d_grad)) print(list(grad)) assert list(grad) == pytest.approx(list(f_d_grad)) sel = f_d_grad > 1e-8 assert sel, """assert sel has some elements, as finite difference grad should
def test_target_jacobian_calculation_finite_difference(physical_param, single_exp, large_reflection_table): """Test the calculated jacobian against a finite difference calculation.""" physical_param.physical.decay_correction = False model = PhysicalScalingModel.from_data(physical_param, single_exp, large_reflection_table) # need to 'add_data' model.configure_components(large_reflection_table, single_exp, physical_param) model.components["scale"].update_reflection_data() apm = multi_active_parameter_manager( ScalingTarget(), [model.components], [["scale"]], scaling_active_parameter_manager, ) Ih_table = IhTable([large_reflection_table], single_exp.crystal.get_space_group()) with patch.object(SingleScaler, "__init__", lambda x, y, z, k: None): scaler = SingleScaler(None, None, None) scaler._Ih_table = Ih_table target = ScalingTarget() scaler.update_for_minimisation(apm, 0) fd_jacobian = calculate_jacobian_fd(target, scaler, apm) r, jacobian, w = target.compute_residuals_and_gradients( scaler.Ih_table.blocked_data_list[0]) assert r == pytest.approx( [-50.0 / 3.0, 70.0 / 3.0, -20.0 / 3.0, 12.5, -2.5] + [-25.0, 0.0, -75.0, 0.0, 200.0]) assert w == pytest.approx( [0.1, 0.1, 0.1, 0.02, 0.1, 0.02, 0.01, 0.02, 0.01, 0.01]) n_rows = jacobian.n_rows n_cols = jacobian.n_cols print(jacobian) print(fd_jacobian) for i in range(0, n_rows): for j in range(0, n_cols): assert jacobian[i, j] == pytest.approx(fd_jacobian[i, j], abs=1e-4)
def test_plot_scaling_models(): physical_dict = { "__id__": "physical", "is_scaled": True, "scale": { "n_parameters": 2, "parameters": [0.5, 1.0], "est_standard_devs": [0.05, 0.1], }, "configuration_parameters": { "corrections": ["scale", "decay", "absorption"], "s_norm_fac": 0.1, "d_norm_fac": 0.1, "scale_rot_interval": 10.0, "decay_rot_interval": 10.0, "decay_restaint": 1e-1, "valid_osc_range": [0.0, 2.0], }, "decay": { "n_parameters": 2, "parameters": [0.5, 1.0], "est_standard_devs": [0.05, 0.1], }, "absorption": { "n_parameters": 4, "parameters": [0.1, -0.1, 0.05, -0.05], "est_standard_devs": [0.005, 0.005, 0.005, 0.005], }, } d = plot_scaling_models(PhysicalScalingModel.from_dict(physical_dict)) assert "smooth_scale_model" in d assert "absorption_surface" in d assert "absorption_parameters" in d assert d["smooth_scale_model"]["data"][0] != [] assert d["absorption_parameters"]["data"][0] != []
def test_PhysicalScalingModel(test_reflections, mock_exp): """Test the PhysicalScalingModel class.""" configdict = { "corrections": ["scale", "decay", "absorption"], "s_norm_fac": 1.0, "scale_rot_interval": 2.0, "d_norm_fac": 1.0, "decay_rot_interval": 2.0, "lmax": 1, "abs_surface_weight": 1e6, } parameters_dict = { "scale": { "parameters": flex.double([1.2, 1.1]), "parameter_esds": None }, "decay": { "parameters": flex.double([0.1, 0.2]), "parameter_esds": None }, "absorption": { "parameters": flex.double([0.01, 0.01, 0.01]), "parameter_esds": None, }, } # Test standard factory initialisation physicalmodel = PhysicalScalingModel(parameters_dict, configdict) assert physicalmodel.id_ == "physical" assert "Absorption component" in str(physicalmodel) comps = physicalmodel.components assert "scale" in comps assert "absorption" in comps assert "decay" in comps assert list(comps["scale"].parameters) == [1.2, 1.1] assert list(comps["decay"].parameters) == [0.1, 0.2] assert list(comps["absorption"].parameters) == [0.01, 0.01, 0.01] # Test configure reflection table mock_params = Mock() mock_params.physical.decay_restraint = 0.0 physicalmodel.configure_components(test_reflections, mock_exp, mock_params) # Test from_dict initialisation method. physical_dict = { "__id__": "physical", "is_scaled": True, "scale": { "n_parameters": 2, "parameters": [0.5, 1.0], "est_standard_devs": [0.05, 0.1], "null_parameter_value": 1, }, "configuration_parameters": { "corrections": ["scale"], "s_norm_fac": 0.1, "scale_rot_interval": 10.0, "decay_restaint": 1e-1, }, } physicalmodel = PhysicalScalingModel.from_dict(physical_dict) assert physicalmodel.id_ == "physical" assert "scale" in physicalmodel.components assert "absorption" not in physicalmodel.components assert "decay" not in physicalmodel.components assert list(physicalmodel.components["scale"].parameters) == [0.5, 1.0] assert list( physicalmodel.components["scale"].parameter_esds) == [0.05, 0.1] new_dict = physicalmodel.to_dict() assert new_dict == physical_dict # Test from_dict initialisation method for all components. physical_dict = { "__id__": "physical", "is_scaled": True, "scale": { "n_parameters": 2, "parameters": [0.5, 1.0], "est_standard_devs": [0.05, 0.1], "null_parameter_value": 1, }, "decay": { "n_parameters": 2, "parameters": [0.1, 0.2], "est_standard_devs": [0.01, 0.01], "null_parameter_value": 0, }, "absorption": { "n_parameters": 3, "parameters": [0.0, 0.1, 0.2], "est_standard_devs": [0.01, 0.02, 0.03], "null_parameter_value": 0, }, "configuration_parameters": { "corrections": ["scale", "decay", "absorption"], "s_norm_fac": 0.1, "scale_rot_interval": 10.0, "d_norm_fac": 0.2, "decay_rot_interval": 20.0, "lmax": 1, "abs_surface_weight": 1e6, }, } physicalmodel = PhysicalScalingModel.from_dict(physical_dict) assert physicalmodel.id_ == "physical" assert "scale" in physicalmodel.components assert "absorption" in physicalmodel.components assert "decay" in physicalmodel.components assert list(physicalmodel.components["scale"].parameters) == [0.5, 1.0] assert list( physicalmodel.components["scale"].parameter_esds) == [0.05, 0.1] assert list(physicalmodel.components["decay"].parameters) == [0.1, 0.2] assert list( physicalmodel.components["decay"].parameter_esds) == [0.01, 0.01] assert list( physicalmodel.components["absorption"].parameters) == [0.0, 0.1, 0.2] assert list(physicalmodel.components["absorption"].parameter_esds) == [ 0.01, 0.02, 0.03, ] new_dict = physicalmodel.to_dict() assert new_dict == physical_dict with pytest.raises(RuntimeError): physical_dict["__id__"] = "array" physicalmodel = PhysicalScalingModel.from_dict(physical_dict) assert len(physicalmodel.consecutive_refinement_order) == 2 assert "Absorption component:" in str(physicalmodel) # test limit batch range parameters_dict = { "scale": { "n_parameters": 11, "parameters": [0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 5.5], "parameter_esds": None, }, "decay": { "n_parameters": 11, "parameters": [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1], "parameter_esds": None, }, } configdict = { "corrections": ["scale", "decay"], "s_norm_fac": 0.1, "scale_rot_interval": 10.0, "d_norm_fac": 0.1, "decay_rot_interval": 10.0, "valid_image_range": (1, 90), "valid_osc_range": (0, 90), } physical = PhysicalScalingModel(parameters_dict, configdict) physical.limit_image_range((1, 50)) assert list(physical.components["scale"].parameters) == [ 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, ] assert list(physical.components["decay"].parameters) == [ 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, ] assert physical.configdict["valid_osc_range"] == (0, 50) assert physical.configdict["valid_image_range"] == (1, 50) # try edge cases # if restricted by > rot int, then reduce number of params and shift offset # if necessary physical = PhysicalScalingModel(copy.deepcopy(parameters_dict), copy.deepcopy(configdict)) physical.limit_image_range((7, 45)) assert list(physical.components["scale"].parameters) == [ 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, ] assert list(physical.components["decay"].parameters) == [ 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, ] assert physical.configdict["valid_osc_range"] == (6, 45) assert physical.configdict["valid_image_range"] == (7, 45) # if not restricted by > rot int, then should 'squeeze' the parameters closer # in rotation angle, leaving the same number of params (as reducing number of # params would give parameter spacing greater than initially specified rot int) physical = PhysicalScalingModel(copy.deepcopy(parameters_dict), copy.deepcopy(configdict)) physical.limit_image_range((5, 45)) assert list(physical.components["scale"].parameters) == [ 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, ] assert list(physical.components["decay"].parameters) == [ 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, ] assert physical.configdict["valid_osc_range"] == (4, 45) assert physical.configdict["valid_image_range"] == (5, 45)
def from_dict(d): """creates a scaling model from a dict""" from dials.algorithms.scaling.model.model import PhysicalScalingModel return PhysicalScalingModel.from_dict(d)