File: test_utils.py

package info (click to toggle)
cclib 1.8.1-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 55,412 kB
  • sloc: python: 23,605; makefile: 75; sh: 31
file content (143 lines) | stat: -rw-r--r-- 5,605 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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# Copyright (c) 2024, the cclib development team
#
# This file is part of cclib (http://cclib.github.io) and is distributed under
# the terms of the BSD 3-Clause License.

"""Unit tests for utilities."""

from cclib.parser import utils

import numpy
import scipy.spatial.transform


class FloatTest:
    def test_float_basic(self) -> None:
        """Are floats converted from strings correctly?"""
        assert utils.float("0.0") == 0.0
        assert utils.float("1.0") == 1.0
        assert utils.float("-1.0") == -1.0

    def test_float_numeric_format(self) -> None:
        """Does numeric formatting get converted correctly?"""
        assert utils.float("1.2345E+02") == 123.45
        assert utils.float("1.2345D+02") == 123.45

    def test_float_stars(self) -> None:
        """Does the function return nan for stars?"""
        assert numpy.isnan(utils.float("*"))
        assert numpy.isnan(utils.float("*****"))


class ConvertorTest:
    def test_convertor(self) -> None:
        assert f"{utils.convertor(8.0, 'eV', 'wavenumber'):.3f}" == "64524.354"


class GetRotationTest:
    delta = 1e-14

    @classmethod
    def setup_class(cls) -> None:
        cls.r = scipy.spatial.transform.Rotation.from_euler("xyz", [15, 25, 35], degrees=True)
        cls.t = numpy.array([-1, 0, 2])
        cls.a = numpy.array([[1.0, 1.0, 1.0], [0.0, 1.0, 2.0], [0.0, 0.0, 0.0], [0.0, 0.0, 4.0]])
        cls.b = cls.r.apply(cls.a + cls.t)

    def test_default(self) -> None:
        """Is the rotation is correct?"""
        _r = utils.get_rotation(self.a, self.b)
        # as_dcm is renamed to from_matrix in scipy 1.4.0 and will be removed in sicpy 1.6.0
        if hasattr(self.r, "as_matrix"):
            numpy.testing.assert_allclose(self.r.as_matrix(), _r.as_matrix(), atol=self.delta)
        else:
            numpy.testing.assert_allclose(self.r.as_dcm(), _r.as_dcm(), atol=self.delta)

    def test_two_atoms(self) -> None:
        """Is the rotation is correct for 2 atoms?"""
        a2 = self.a[:2]
        b2 = self.b[:2]
        rotated_diff = self.r.apply(a2) - utils.get_rotation(a2, b2).apply(a2)
        # rotated_diff should be translation
        numpy.testing.assert_allclose(rotated_diff[0], rotated_diff[1], atol=self.delta)

    def test_one_atom(self) -> None:
        """Is the rotation is identity for 1 atom?"""
        a1 = self.a[:1]
        b1 = self.b[:1]
        if hasattr(self.r, "as_matrix"):
            numpy.testing.assert_allclose(
                numpy.eye(3), utils.get_rotation(a1, b1).as_matrix(), atol=self.delta
            )
        else:
            numpy.testing.assert_allclose(
                numpy.eye(3), utils.get_rotation(a1, b1).as_dcm(), atol=self.delta
            )


class PeriodicTableTest:
    def test_periodictable(self) -> None:
        t = utils.PeriodicTable()
        assert t.element[6] == "C"
        assert t.number["C"] == 6
        assert t.element[44] == "Ru"
        assert t.number["Au"] == 79


class WidthSplitterTest:
    def test_default(self) -> None:
        """Does the splitter remove empty fields by default properly?"""
        fixed_splitter = utils.WidthSplitter((4, 3, 5, 6, 10, 10, 10, 10, 10, 10))
        line_full = "  60  H 10  s        0.14639   0.00000   0.00000  -0.00000  -0.00000   0.00000"
        line_truncated = "   1  C 1   s       -0.00000  -0.00000   0.00000"
        ref_full = [
            "60",
            "H",
            "10",
            "s",
            "0.14639",
            "0.00000",
            "0.00000",
            "-0.00000",
            "-0.00000",
            "0.00000",
        ]
        ref_truncated = ["1", "C", "1", "s", "-0.00000", "-0.00000", "0.00000"]
        tokens_full = fixed_splitter.split(line_full)
        tokens_truncated = fixed_splitter.split(line_truncated)
        assert ref_full == tokens_full
        assert ref_truncated == tokens_truncated

    def test_no_truncation(self) -> None:
        """Does the splitter return even the empty fields when asked?"""
        fixed_splitter = utils.WidthSplitter((4, 3, 5, 6, 10, 10, 10, 10, 10, 10))
        line = "   1  C 1   s       -0.00000  -0.00000   0.00000"
        ref_not_truncated = ["1", "C", "1", "s", "-0.00000", "-0.00000", "0.00000", "", "", ""]
        tokens_not_truncated = fixed_splitter.split(line, truncate=False)
        assert ref_not_truncated == tokens_not_truncated


class SymmetrizeTest:
    def test_dim_from_tblock_size(self) -> None:
        assert utils._dim_from_tblock_size(1) == 1
        # This isn't possible until we fully move to pytest.
        # with pytest.raises(
        #     RuntimeError,
        #     match="The number of elements (2) isn't possible for a matrix triangle"
        # ):
        #     assert utils._dim_from_tblock_size(2)
        assert utils._dim_from_tblock_size(3) == 2
        assert utils._dim_from_tblock_size(6) == 3
        assert utils._dim_from_tblock_size(10) == 4

    def test_block_to_matrix(self) -> None:
        inp = numpy.array([1, 2, 3, 4, 5, 6], dtype=int)
        ref = numpy.array([[1, 2, 4], [2, 3, 5], [4, 5, 6]], dtype=int)
        numpy.testing.assert_equal(utils.block_to_matrix(inp), ref)

    def test_symmetrize(self) -> None:
        inp = numpy.array([[1, 9, 7], [4, 8, 3], [6, 2, 5]], dtype=int)
        ref_lower = numpy.array([[1, 4, 6], [4, 8, 2], [6, 2, 5]], dtype=int)
        ref_upper = numpy.array([[1, 9, 7], [9, 8, 3], [7, 3, 5]], dtype=int)
        numpy.testing.assert_equal(utils.symmetrize(inp, "lower"), ref_lower)
        numpy.testing.assert_equal(utils.symmetrize(inp, "upper"), ref_upper)