File: test_delta_cchalf_algorithm.py

package info (click to toggle)
dials 3.25.0%2Bdfsg3-3
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 20,112 kB
  • sloc: python: 134,740; cpp: 34,526; makefile: 160; sh: 142
file content (124 lines) | stat: -rw-r--r-- 4,254 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
"""Tests for ΔCC½ algorithms."""

from __future__ import annotations

from unittest import mock

from dxtbx.model import Crystal, Experiment, ExperimentList, Scan

from dials.algorithms.statistics.cc_half_algorithm import CCHalfFromDials
from dials.array_family import flex
from dials.command_line.compute_delta_cchalf import phil_scope


def generated_exp(n=1):
    """Generate an experiment list with two experiments."""
    experiments = ExperimentList()
    exp_dict = {
        "__id__": "crystal",
        "real_space_a": [1.0, 0.0, 0.0],
        "real_space_b": [0.0, 1.0, 0.0],
        "real_space_c": [0.0, 0.0, 2.0],
        "space_group_hall_symbol": " C 2y",
    }
    for i in range(n):
        experiments.append(
            Experiment(
                scan=Scan(image_range=[1, 25], oscillation=[0.0, 1.0]),
                crystal=Crystal.from_dict(exp_dict),
                identifier=str(i),
            )
        )
    return experiments


def generated_refl():
    """Generate test data."""
    refls = flex.reflection_table()
    refls["intensity.scale.value"] = flex.double(range(50))
    refls["intensity.scale.variance"] = flex.double(range(50))
    refls["inverse_scale_factor"] = flex.double(50, 1.0)
    refls["id"] = flex.int([0] * 25 + [1] * 25)
    refls["xyzobs.px.value"] = flex.vec3_double(
        [(0, 0, i + 0.5) for i in range(25)] * 2
    )
    vals = [0, 1, 2, 3, 48, 49]
    # set first two of first sweep, and last two of last sweep as outliers
    outliers = flex.bool(50, False)
    for v in vals:
        outliers[v] = True
    refls.set_flags(outliers, refls.flags.outlier_in_scaling)
    refls.experiment_identifiers()[0] = "0"
    refls.experiment_identifiers()[1] = "1"
    return refls


def test_setup_of_CCHalfFromDials():
    """Test the correct setup in image group mode.

    Test for the case of outliers at the end of images, and image ranges not
    equaling a multiple of the grouping."""

    params = phil_scope.extract()
    params.mode = "image_group"
    expts = generated_exp(n=2)
    refls = generated_refl()

    # Expected behaviour is that the outliers will not be included in the
    # image range, and that all groups will have at least 10 images in.
    script = CCHalfFromDials(params, expts, refls)
    assert script.group_to_datasetid_and_range == {
        0: ("0", (5, 14)),
        1: ("0", (15, 25)),
        2: ("1", (1, 10)),
        3: ("1", (11, 23)),
    }
    assert script.datasetid_to_groups == {"0": [0, 1], "1": [2, 3]}


def test_exclusion_in_CCHalfFromDials():
    """Test the exclusion of image groups."""
    # Same input as above, but mock DeltaCCHalf algorithm to just test
    # interpretation of results and setting of excluded regions. With the
    # input, test that outlier edges are correctly removed.

    params = phil_scope.extract()
    params.mode = "image_group"
    expts = generated_exp(n=2)
    refls = generated_refl()

    def mock_algorithm(*_):
        """Mock a result from DeltaCCHalf"""
        algo = mock.Mock()
        algo.run.return_value = None
        algo.results_summary = {
            "per_dataset_delta_cc_half_values": {
                "delta_cc_half_values": [-5.0, -2.0, 4.0, -5.0],
                "datasets": [0, 1, 2, 3],
            },
            "dataset_removal": {"cutoff_value": -1.0},
        }
        algo.cchalf_i = {0: 80.0, 1: 85.0, 2: 78.0, 3: 79.0}
        algo.delta_cchalf_i = {0: 0.0, 1: 5.0, 2: -2.0, 3: -1.0}
        return algo

    with mock.patch(
        "dials.algorithms.statistics.cc_half_algorithm.DeltaCCHalf",
        side_effect=mock_algorithm,
    ):
        script = CCHalfFromDials(params, expts, refls)
        script.run()
        table = script.get_table(True)
        assert table

        assert script.datasetid_to_groups == {"0": [], "1": [2]}  # all but 3 removed
        expts = script.experiments

        assert list(expts.identifiers()) == ["1"]
        assert expts[0].scan.get_valid_image_ranges(expts.identifiers()[0]) == [(1, 10)]
        assert script.results_summary["dataset_removal"][
            "experiment_ids_fully_removed"
        ] == [0]
        assert script.results_summary["dataset_removal"][
            "experiments_fully_removed"
        ] == ["0"]