예제 #1
0
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
예제 #2
0
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
예제 #3
0
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
예제 #4
0
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)
예제 #5
0
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
예제 #6
0
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
예제 #7
0
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
예제 #8
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]
예제 #9
0
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))
예제 #10
0
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
예제 #11
0
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
예제 #12
0
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