def test_target_function_methods(): """Test for the target methods required for the refinement engine.""" target = ScalingTarget() r, w = target.compute_residuals(mock_single_Ih_table()) assert r.size() == w.size() assert r == pytest.approx([-1.0, 0.0, 1.0]) assert w == pytest.approx([1.0, 1.0, 1.0]) f, g = target.compute_functional_gradients(mock_single_Ih_table()) assert f == pytest.approx(2.0) assert g == pytest.approx([-19.04072398]) r2, j, w2 = target.compute_residuals_and_gradients(mock_single_Ih_table()) assert r == r2 assert w == w2 assert j.n_cols == 1 and j.n_rows == 3
def test_target_rmsd_calculation(mock_apm_restrained, mock_apm_unrestrained): """Test the RMSD calculation, with and without restraints.""" target = ScalingTarget() assert target.param_restraints is True # with input, expect residuals of [-1, 0, 1], weights of [1, 1, 1], # restraints of [1, 2, 3], so expect residual of sqrt((2+6)/3) rmsds = target.rmsds(mock_Ih_table(), mock_apm_restrained) assert len(rmsds) == 1 assert rmsds[0] == pytest.approx((8.0 / 3.0)**0.5, abs=1e-6) assert target.param_restraints is True # test rmsd calculation without restraints rmsds = target.rmsds(mock_Ih_table(), mock_apm_unrestrained) assert len(rmsds) == 1 assert rmsds[0] == pytest.approx((2.0 / 3.0)**0.5, abs=1e-6) assert target.param_restraints is False
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_target_gradient_calculation_finite_difference(small_reflection_table, single_exp, physical_param): """Test the calculated gradients against a finite difference calculation.""" (test_reflections, test_experiments, params) = ( small_reflection_table, single_exp, physical_param, ) assert len(test_experiments) == 1 assert len(test_reflections) == 1 experiments = create_scaling_model(params, test_experiments, test_reflections) scaler = create_scaler(params, experiments, test_reflections) assert scaler.experiment.scaling_model.id_ == "physical" # Initialise the parameters and create an apm scaler.components["scale"].inverse_scales = flex.double([2.0, 1.0, 2.0]) scaler.components["decay"].inverse_scales = flex.double([1.0, 1.0, 0.4]) apm = multi_active_parameter_manager([scaler.components], [["scale", "decay"]], scaling_active_parameter_manager) # 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 approx_equal(list(grad), 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_function_restraints_methods(mock_apm_restrained, mock_apm_unrestrained): """Test for the target restraints methods required for the refinement engine.""" target = ScalingTarget() restraints = target.compute_restraints_residuals_and_gradients( mock_apm_restrained) assert len(restraints) == 3 assert target.param_restraints is True assert list(restraints[0]) == [1.0, 1.1, 1.2] assert list(restraints[2]) == [1.0, 2.0, 3.0] restraints = target.compute_restraints_functional_gradients( mock_apm_restrained) assert len(restraints) == 2 assert restraints[0] == 6.0 assert list(restraints[1]) == [0.1, 0.2, 0.3] achieved = target.achieved() assert isinstance(achieved, bool) restraints = target.compute_restraints_residuals_and_gradients( mock_apm_unrestrained) assert restraints is None assert target.param_restraints is False # Check that if called again, returns None without doing calculations restraints = target.compute_restraints_residuals_and_gradients([]) assert restraints is None target = ScalingTarget( ) # Need to make new instance or won't calc restr as # param_restraints is set to False assert target.param_restraints is True restraints = target.compute_restraints_functional_gradients( mock_apm_unrestrained) assert restraints is None assert target.param_restraints is False
def test_multi_apm(): """Test for the general multi_active_parameter_manage class.""" components_1 = { "scale": mock_component(), "decay": mock_component(), "absorption": mock_component(), } components_2 = {"scale": mock_component(), "decay": mock_component()} multi_apm = multi_active_parameter_manager( ScalingTarget(), [components_1, components_2], [["scale", "decay"], ["scale"]], active_parameter_manager, ) # Test correct setup of apm_list attribute. for apm in multi_apm.apm_list: assert isinstance(apm, active_parameter_manager) assert len(multi_apm.apm_list) == 2 assert multi_apm.components_list == ["scale", "decay", "scale"] assert multi_apm.n_active_params == 3 assert multi_apm.apm_data[0] == {"start_idx": 0, "end_idx": 2} assert multi_apm.apm_data[1] == {"start_idx": 2, "end_idx": 3} # Test parameter selection. multi_apm.set_param_vals(flex.double([3.0, 2.5, 2.0])) assert multi_apm.get_param_vals() == flex.double([3.0, 2.5, 2.0]) assert multi_apm.select_parameters(0) == flex.double([3.0, 2.5]) assert multi_apm.select_parameters(1) == flex.double([2.0]) # Test setting parameter esds. multi_apm.set_param_esds(flex.double([0.1, 0.2, 0.3])) assert components_1["scale"].free_parameter_esds == flex.double([0.1]) assert components_1["decay"].free_parameter_esds == flex.double([0.2]) assert components_2["scale"].free_parameter_esds == flex.double([0.3]) # Test setting var_cov matrices for each component. var_cov = flex.double([1.0, 0.5, 0.5, 0.5, 2.0, 0.5, 0.5, 0.5, 3.0]) var_cov.reshape(flex.grid(3, 3)) multi_apm.calculate_model_state_uncertainties(var_cov) assert components_1["scale"].var_cov_matrix[0, 0] == 1.0 assert components_1["decay"].var_cov_matrix[0, 0] == 2.0 assert components_2["scale"].var_cov_matrix[0, 0] == 3.0
def test_shared_apm(): components_1 = { "scale": mock_component(), "decay": mock_component(), "absorption": mock_component(), } components_2 = {"scale": mock_component(), "decay": mock_component()} multi_apm = shared_active_parameter_manager( ScalingTarget(), [components_1, components_2], [["scale", "decay"], ["scale", "decay"]], active_parameter_manager, shared="decay", ) # Test correct setup of apm_list attribute. for apm in multi_apm.apm_list: assert isinstance(apm, active_parameter_manager) assert len(multi_apm.apm_list) == 2 assert multi_apm.components_list == ["scale", "decay", "scale", "decay"] assert multi_apm.n_active_params == 4 # assert multi_apm.apm_data[0] == {"start_idx": 0, "end_idx": 2} # assert multi_apm.apm_data[1] == {"start_idx": 2, "end_idx": 4} assert list(multi_apm.reducing_matrix.as_dense_matrix()) == [ 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, ] assert multi_apm.apm_data[0]["start_idx"] == 0 assert multi_apm.apm_data[0]["end_idx"] == 2 assert multi_apm.apm_data[1]["start_idx"] == 2 assert multi_apm.apm_data[1]["end_idx"] == 4 assert list(multi_apm.apm_data[0]["apm_sel"]) == [0, 1] assert list(multi_apm.apm_data[1]["apm_sel"]) == [2, 1]
def test_scaling_active_parameter_manager(): """Test the scaling-specific parameter manager.""" components_2 = { "1": mock_scaling_component(2), "2": mock_scaling_component(2) } scaling_apm = scaling_active_parameter_manager(components_2, ["1"]) assert list(scaling_apm.constant_g_values[0]) == list( components_2["2"].calculate_scales()) assert len(scaling_apm.constant_g_values) == 1 assert scaling_apm.n_obs == [2] # Test that no constant_g_values if both components selected scaling_apm = scaling_active_parameter_manager(components_2, ["1", "2"]) assert scaling_apm.constant_g_values is None # Check that one can't initialise with an unequal number of reflections, # either within the selection or overall. with pytest.raises(AssertionError): components_2 = { "1": mock_scaling_component(2), "2": mock_scaling_component(1) } scaling_apm = scaling_active_parameter_manager(components_2, ["1", "2"]) with pytest.raises(AssertionError): components_2 = { "1": mock_scaling_component(2), "2": mock_scaling_component(1) } scaling_apm = scaling_active_parameter_manager(components_2, ["1"]) data_manager = mock_data_manager(components_2) pmg = ScalingParameterManagerGenerator([data_manager], target=ScalingTarget(), mode="concurrent") assert isinstance(pmg.apm_type, type(scaling_active_parameter_manager))
def test_ParameterManagerGenerator_consecutive(): """Test the apm factory for consecutive refinement.""" components_1 = { "scale": mock_component(), "decay": mock_component(), "absorption": mock_component(), } data_manager = mock_data_manager(components_1) data_manager.consecutive_refinement_order = [["scale", "decay"], ["absorption"]] # Test single dataset case. pmg = ParameterManagerGenerator( [data_manager], apm_type=active_parameter_manager, target=ScalingTarget(), mode="consecutive", ) apms = list(pmg.parameter_managers()) assert len(apms) == 2 apm = apms[0] assert isinstance(apm, multi_active_parameter_manager) assert "scale" in apm.components_list assert "decay" in apm.components_list assert "absorption" not in apm.components_list apm = apms[1] assert isinstance(apm, multi_active_parameter_manager) assert "scale" not in apm.components_list assert "decay" not in apm.components_list assert "absorption" in apm.components_list # Test multi dataset case. components_2 = {"1": mock_component(), "2": mock_component()} data_manager_2 = mock_data_manager(components_2) data_manager_2.consecutive_refinement_order = [["1"], ["2"]] pmg = ParameterManagerGenerator( [data_manager, data_manager_2], apm_type=active_parameter_manager, target=ScalingTarget(), mode="consecutive", ) apms = list(pmg.parameter_managers()) assert len(apms) == 2 multi_apm = apms[0] assert isinstance(multi_apm, multi_active_parameter_manager) apm_1 = multi_apm.apm_list[0] assert "scale" in apm_1.components_list assert "decay" in apm_1.components_list assert "absorption" not in apm_1.components_list assert multi_apm.apm_list[1].components_list == ["1"] multi_apm = apms[1] assert isinstance(multi_apm, multi_active_parameter_manager) assert multi_apm.apm_list[0].components_list == ["absorption"] assert multi_apm.apm_list[1].components_list == ["2"] # Test multi dataset case with different number of cycles for each data_manager. components_2 = {"1": mock_component()} data_manager_2 = mock_data_manager(components_2) data_manager_2.consecutive_refinement_order = [["1"], ["2"]] pmg = ParameterManagerGenerator( [data_manager, data_manager_2], apm_type=active_parameter_manager, target=ScalingTarget(), mode="consecutive", ) assert pmg.param_lists[0] == [["scale", "decay"], ["absorption"]] assert pmg.param_lists[1] == [["1"]] apms = list(pmg.parameter_managers()) assert len(apms) == 2 multi_apm = apms[0] assert isinstance(multi_apm, multi_active_parameter_manager) apm_1 = multi_apm.apm_list[0] assert "scale" in apm_1.components_list assert "decay" in apm_1.components_list assert "absorption" not in apm_1.components_list assert multi_apm.apm_list[1].components_list == ["1"] multi_apm = apms[1] assert isinstance(multi_apm, multi_active_parameter_manager) assert multi_apm.apm_list[0].components_list == ["absorption"] # Only change relative to previous test case. assert multi_apm.apm_list[1].components_list == [] # Test fixing the decay parameter. data_manager.fixed_components = ["decay"] pmg = ParameterManagerGenerator( [data_manager], apm_type=active_parameter_manager, target=ScalingTarget(), mode="consecutive", ) apms = list(pmg.parameter_managers()) assert len(apms) == 2 apm = apms[0] assert isinstance(apm, multi_active_parameter_manager) assert "scale" in apm.components_list assert "decay" not in apm.components_list assert "absorption" not in apm.components_list apm = apms[1] assert isinstance(apm, multi_active_parameter_manager) assert "scale" not in apm.components_list assert "decay" not in apm.components_list assert "absorption" in apm.components_list
def test_ParameterManagerGenerator_concurrent(): """Test the apm factory for concurrent refinement.""" components_1 = { "scale": mock_component(), "decay": mock_component(), "absorption": mock_component(), } data_manager = mock_data_manager(components_1) pmg = ParameterManagerGenerator( [data_manager], apm_type=active_parameter_manager, target=ScalingTarget(), mode="concurrent", ) apms = pmg.parameter_managers() assert len(apms) == 1 apm = apms[0] assert isinstance(apm, multi_active_parameter_manager) assert "scale" in apm.components_list assert "decay" in apm.components_list assert "absorption" in apm.components_list components_1 = { "scale": mock_component(), "decay": mock_component(), "absorption": mock_component(), } components_2 = {"1": mock_component(), "2": mock_component()} data_manager_1 = mock_data_manager(components_1) data_manager_2 = mock_data_manager(components_2) pmg = ParameterManagerGenerator( [data_manager_1, data_manager_2], apm_type=active_parameter_manager, target=ScalingTarget(), mode="concurrent", ) multi_apms = pmg.parameter_managers() assert len(multi_apms) == 1 multi_apm = multi_apms[0] assert isinstance(multi_apm, multi_active_parameter_manager) for apm in multi_apm.apm_list: assert isinstance(apm, active_parameter_manager) assert "scale" in multi_apm.apm_list[0].components_list assert "decay" in multi_apm.apm_list[0].components_list assert "absorption" in multi_apm.apm_list[0].components_list assert "1" in multi_apm.apm_list[1].components_list assert "2" in multi_apm.apm_list[1].components_list # now try fixing a component data_manager.fixed_components = ["absorption"] pmg = ParameterManagerGenerator( [data_manager], apm_type=active_parameter_manager, target=ScalingTarget(), mode="concurrent", ) apms = pmg.parameter_managers() assert len(apms) == 1 apm = apms[0] assert isinstance(apm, multi_active_parameter_manager) assert "scale" in apm.components_list assert "decay" in apm.components_list assert "absorption" not in apm.components_list
def test_target_function( mock_single_Ih_table, mock_multi_apm_withrestraints, mock_multi_apm_withoutrestraints, ): """Test for the ScalingTarget class.""" # Create a scaling target and check gradients target = ScalingTarget() apm_restr = mock_multi_apm_withrestraints apm_norestr = mock_multi_apm_withoutrestraints # Below methods needed for refinement engine calls r, w = target.compute_residuals(mock_single_Ih_table) assert r.size() == w.size() f, g = target.compute_functional_gradients(mock_single_Ih_table) assert isinstance(f, float) assert g.size( ) == 1 # Number of parameters as determined by deriv matrix cols r, j, w = target.compute_residuals_and_gradients(mock_single_Ih_table) assert r.size() == w.size() assert j.n_cols == 1 # Number of parameters as determined by jacob matrix. assert j.n_rows == r.size() with pytest.raises(AssertionError): _ = target.compute_functional_gradients_and_curvatures( mock_single_Ih_table) restraints = target.compute_restraints_residuals_and_gradients(apm_restr) assert len(restraints) == 3 assert target.param_restraints is True restraints = target.compute_restraints_functional_gradients_and_curvatures( apm_restr) assert len(restraints) == 3 achieved = target.achieved() assert isinstance(achieved, bool) restraints = target.compute_restraints_residuals_and_gradients(apm_norestr) assert restraints is None assert target.param_restraints is False target = ScalingTarget( ) # Need to make new instance or won't calc restr as # param_restraints is set to False assert target.param_restraints is True restraints = target.compute_restraints_functional_gradients_and_curvatures( apm_norestr) assert restraints is None assert target.param_restraints is False