Example #1
0
def test_multiscaler_update_for_minimisation():
    """Test the multiscaler update_for_minimisation method."""

    p, e = (generated_param(), generated_exp(2))
    p.reflection_selection.method = "use_all"
    r1 = generated_refl(id_=0)
    r1["intensity.sum.value"] = r1["intensity"]
    r1["intensity.sum.variance"] = r1["variance"]
    r2 = generated_refl(id_=1)
    r2["intensity.sum.value"] = r2["intensity"]
    r2["intensity.sum.variance"] = r2["variance"]
    p.scaling_options.nproc = 2
    p.model = "physical"
    exp = create_scaling_model(p, e, [r1, r2])
    singlescaler1 = create_scaler(p, [exp[0]], [r1])
    singlescaler2 = create_scaler(p, [exp[1]], [r2])

    multiscaler = MultiScaler([singlescaler1, singlescaler2])
    pmg = ScalingParameterManagerGenerator(
        multiscaler.active_scalers,
        ScalingTarget,
        multiscaler.params.scaling_refinery.refinement_order,
    )
    multiscaler.single_scalers[0].components["scale"].parameters /= 2.0
    multiscaler.single_scalers[1].components["scale"].parameters *= 1.5
    apm = pmg.parameter_managers()[0]
    multiscaler.update_for_minimisation(apm, 0)
    multiscaler.update_for_minimisation(apm, 1)
    # bf[0], bf[1] should be list of scales and derivatives
    s1, d1 = RefinerCalculator.calculate_scales_and_derivatives(
        apm.apm_list[0], 0)
    s2, d2 = RefinerCalculator.calculate_scales_and_derivatives(
        apm.apm_list[1], 0)
    s3, d3 = RefinerCalculator.calculate_scales_and_derivatives(
        apm.apm_list[0], 1)
    s4, d4 = RefinerCalculator.calculate_scales_and_derivatives(
        apm.apm_list[1], 1)
    expected_scales_for_block_1 = s1
    expected_scales_for_block_1.extend(s2)
    expected_scales_for_block_2 = s3
    expected_scales_for_block_2.extend(s4)

    expected_derivatives_for_block_1 = sparse.matrix(
        expected_scales_for_block_1.size(), apm.n_active_params)
    expected_derivatives_for_block_2 = sparse.matrix(
        expected_scales_for_block_2.size(), apm.n_active_params)

    expected_derivatives_for_block_1.assign_block(d1, 0, 0)
    expected_derivatives_for_block_1.assign_block(d2, d1.n_rows,
                                                  apm.apm_data[1]["start_idx"])
    expected_derivatives_for_block_2.assign_block(d3, 0, 0)
    expected_derivatives_for_block_2.assign_block(d4, d3.n_rows,
                                                  apm.apm_data[1]["start_idx"])

    block_list = multiscaler.Ih_table.blocked_data_list

    assert block_list[0].inverse_scale_factors == expected_scales_for_block_1
    assert block_list[1].inverse_scale_factors == expected_scales_for_block_2
    assert block_list[1].derivatives == expected_derivatives_for_block_2
    assert block_list[0].derivatives == expected_derivatives_for_block_1
Example #2
0
def test_SingleScaler_update_for_minimisation():
    """Test the update_for_minimisation method of the singlescaler."""
    # test_params.scaling_options.nproc = 1
    p, e, r = (generated_param(), generated_exp(), generated_refl_2())
    exp = create_scaling_model(p, e, r)
    p.reflection_selection.method = "use_all"
    single_scaler = SingleScaler(p, exp[0], r)
    pmg = ScalingParameterManagerGenerator(
        single_scaler.active_scalers,
        ScalingTarget(),
        single_scaler.params.scaling_refinery.refinement_order,
    )
    single_scaler.components["scale"].parameters /= 2.0
    apm = pmg.parameter_managers()[0]

    Ih_table = single_scaler.Ih_table.blocked_data_list[0]
    Ih_table.calc_Ih()
    assert list(Ih_table.inverse_scale_factors) == [1.0, 1.0]
    assert list(Ih_table.Ih_values) == [10.0, 1.0]
    single_scaler.update_for_minimisation(apm, 0)
    # Should set new scale factors, and calculate Ih and weights.
    bf = RefinerCalculator.calculate_scales_and_derivatives(apm.apm_list[0], 0)
    assert list(Ih_table.inverse_scale_factors) == list(bf[0])
    assert list(Ih_table.Ih_values) != [1.0, 10.0]
    assert list(Ih_table.Ih_values) == pytest.approx(
        list(Ih_table.intensities / bf[0]))
    for i in range(Ih_table.derivatives.n_rows):
        for j in range(Ih_table.derivatives.n_cols):
            assert Ih_table.derivatives[i, j] == pytest.approx(bf[1][i, j])
    assert Ih_table.derivatives.non_zeroes == bf[1].non_zeroes
Example #3
0
def test_RefinerCalculator(small_reflection_table):
    """Test for the RefinerCalculator class. This calculates scale factors and
    derivatives for reflections based on the model components."""

    # To test the basis function, need a scaling active parameter manager - to set
    # this up we need a components dictionary with some reflection data.

    # Let's use KB model components for simplicity - and have an extra fake 'abs'
    # component.
    rt = small_reflection_table
    components = {
        "scale": SingleScaleFactor(flex.double([1.0])),
        "decay": SingleBScaleFactor(flex.double([0.0])),
        "abs": SingleScaleFactor(flex.double([1.0])),
    }  # Create empty components.
    components["scale"].data = {"id": rt["id"]}
    components["decay"].data = {"d": rt["d"]}
    components["abs"].data = {"id": rt["id"]}
    for component in components.values():
        component.update_reflection_data()  # Add some data to components.

    apm = scaling_active_parameter_manager(components, ["decay", "scale"])

    # First test that scale factors can be successfully updated.
    # Manually change the parameters in the apm.
    decay = components["decay"]  # Define alias
    _ = components["scale"]  # Define alias
    # Note, order of params in apm.x depends on order in scaling model components.
    new_B = 1.0
    new_S = 2.0
    apm.set_param_vals(flex.double([new_S, new_B]))
    s, d = RefinerCalculator.calculate_scales_and_derivatives(apm, 0)
    slist, dlist = RefinerCalculator._calc_component_scales_derivatives(apm, 0)
    # Now test that the inverse scale factor is correctly calculated.
    calculated_sfs = s
    assert list(calculated_sfs) == pytest.approx(
        list(new_S * flex.exp(new_B / (2.0 * flex.pow2(decay.d_values[0])))))

    # Now check that the derivative matrix is correctly calculated.
    calc_derivs = d
    assert calc_derivs[0, 0] == dlist[0][0, 0] * slist[1][0]
    assert calc_derivs[1, 0] == dlist[0][1, 0] * slist[1][1]
    assert calc_derivs[2, 0] == dlist[0][2, 0] * slist[1][2]
    assert calc_derivs[0, 1] == dlist[1][0, 0] * slist[0][0]
    assert calc_derivs[1, 1] == dlist[1][1, 0] * slist[0][1]
    assert calc_derivs[2, 1] == dlist[1][2, 0] * slist[0][2]

    # Repeat the test when there is only one active parameter.
    # First reset the parameters
    components["decay"].parameters = flex.double([0.0])
    components["scale"].parameters = flex.double([1.0])
    components["abs"].parameters = flex.double([1.0])
    components["decay"].calculate_scales_and_derivatives()
    components["scale"].calculate_scales_and_derivatives()
    components["abs"].calculate_scales_and_derivatives()

    # Now generate a parameter manager for a single component.
    apm = scaling_active_parameter_manager(components, ["scale"])
    new_S = 2.0
    apm.set_param_vals(flex.double(components["scale"].n_params, new_S))
    s, d = RefinerCalculator.calculate_scales_and_derivatives(apm, 0)
    slist, dlist = RefinerCalculator._calc_component_scales_derivatives(apm, 0)
    # Test that the scales and derivatives were correctly calculated
    assert list(s) == list([new_S] * slist[0].size())
    assert d[0, 0] == dlist[0][0, 0]
    assert d[1, 0] == dlist[0][1, 0]
    assert d[2, 0] == dlist[0][2, 0]

    # Test again for two components.
    components["decay"].parameters = flex.double([0.0])
    components["scale"].parameters = flex.double([1.0])
    components["abs"].parameters = flex.double([1.0])
    components["decay"].calculate_scales_and_derivatives()
    components["scale"].calculate_scales_and_derivatives()
    components["abs"].calculate_scales_and_derivatives()

    apm = scaling_active_parameter_manager(components, ["scale", "decay"])
    _, __ = RefinerCalculator.calculate_scales_and_derivatives(apm, 0)

    # Test for no components
    apm = scaling_active_parameter_manager(components, [])
    _, d = RefinerCalculator.calculate_scales_and_derivatives(apm, 0)
    assert d.n_cols == 0 and d.n_rows == 0