File: test_resolution_analysis.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,046 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
from __future__ import annotations

import pytest

import iotbx.merging_statistics
from cctbx import uctbx
from scitbx.array_family import flex
from scitbx.math import curve_fitting

from dials.util import resolution_analysis


def test_polynomial_fit():
    x = flex.double(range(-50, 50))
    p = (2, 3, 5)
    yo = flex.double(x.size())
    for i in range(len(p)):
        yo += p[i] * flex.pow(x, i)
    yf = resolution_analysis.polynomial_fit(x, yo, degree=2)
    assert yo == pytest.approx(yf)


def test_log_fit():
    x = flex.double(range(0, 100)) * 0.01
    p = (1, 2)
    yo = flex.double(x.size())
    for i in range(len(p)):
        yo += flex.exp(p[i] * flex.pow(x, i))
    yf = resolution_analysis.log_fit(x, yo, degree=2)
    assert yo == pytest.approx(yf, abs=1e-2)


def test_log_inv_fit():
    x = flex.double(range(0, 100)) * 0.01
    p = (1, 2)
    yo = flex.double(x.size())
    for i in range(len(p)):
        yo += 1 / flex.exp(p[i] * flex.pow(x, i))
    yf = resolution_analysis.log_inv_fit(x, yo, degree=2)
    assert yo == pytest.approx(yf, abs=1e-2)


def test_tanh_fit():
    x = flex.double(range(0, 100)) * 0.01
    f = curve_fitting.tanh(0.5, 1.5)
    n_obs = flex.double(100, 100)
    yo = f(x)
    yf = resolution_analysis.tanh_fit(x, yo, n_obs=n_obs)
    assert yo == pytest.approx(yf, abs=1e-5)


@pytest.fixture
def merging_stats(dials_data):
    mtz = str(
        dials_data("x4wide_processed", pathlib=True)
        / "AUTOMATIC_DEFAULT_scaled_unmerged.mtz"
    )
    i_obs, _ = resolution_analysis.miller_array_from_mtz(mtz)
    return iotbx.merging_statistics.dataset_statistics(
        i_obs=i_obs,
        n_bins=20,
        binning_method="counting_sorted",
        use_internal_variance=False,
        eliminate_sys_absent=False,
        assert_is_not_unique_set_under_symmetry=False,
        cc_one_half_significance_level=0.1,
    )


def test_resolution_fit(merging_stats):
    d_star_sq = flex.double(uctbx.d_as_d_star_sq(b.d_min) for b in merging_stats.bins)
    y_obs = flex.double(b.r_merge for b in merging_stats.bins)
    result = resolution_analysis.resolution_fit(
        d_star_sq, y_obs, resolution_analysis.log_inv_fit, 0.6, n_obs=None
    )
    assert result.d_min == pytest.approx(1.278, abs=1e-3)
    assert flex.max(flex.abs(result.y_obs - result.y_fit)) < 0.05


def test_resolution_cc_half(merging_stats):
    result = resolution_analysis.resolution_cc_half(merging_stats, limit=0.82)
    assert result.d_min == pytest.approx(1.242, abs=1e-3)
    result = resolution_analysis.resolution_cc_half(
        merging_stats,
        limit=0.82,
        cc_half_method="sigma_tau",
        model=resolution_analysis.polynomial_fit,
    )
    assert result.d_min == pytest.approx(1.233, abs=1e-3)
    assert flex.max(flex.abs(result.y_obs - result.y_fit)) < 0.04
    assert result.critical_values is not None
    assert len(result.critical_values) == len(result.d_star_sq)


def test_resolution_fit_from_merging_stats(merging_stats):
    result = resolution_analysis.resolution_fit_from_merging_stats(
        merging_stats, "i_over_sigma_mean", resolution_analysis.log_fit, limit=1.5
    )
    assert result.d_min == pytest.approx(1.295, abs=1e-3)
    assert flex.max(flex.abs(result.y_obs - result.y_fit)) < 1


def test_resolution_fit_interpolation_error(merging_stats):
    result = resolution_analysis.resolution_fit_from_merging_stats(
        merging_stats, "i_over_sigma_mean", resolution_analysis.log_fit, limit=25
    )
    assert result.d_min is None


def test_plot_result(merging_stats):
    result = resolution_analysis.resolution_cc_half(merging_stats, limit=0.82)
    d = resolution_analysis.plot_result("cc_half", result)
    assert "data" in d
    assert "layout" in d

    result = resolution_analysis.resolution_fit_from_merging_stats(
        merging_stats,
        "unmerged_i_over_sigma_mean",
        resolution_analysis.log_fit,
        limit=0.82,
    )
    d = resolution_analysis.plot_result("isigma", result)
    assert "data" in d
    assert "layout" in d