• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

materialsproject / pymatgen / 4075885785

pending completion
4075885785

push

github

Shyue Ping Ong
Merge branch 'master' of github.com:materialsproject/pymatgen

96 of 96 new or added lines in 27 files covered. (100.0%)

81013 of 102710 relevant lines covered (78.88%)

0.79 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

98.53
/pymatgen/core/tests/test_operations.py
1
# Copyright (c) Pymatgen Development Team.
2
# Distributed under the terms of the MIT License.
3

4

5
from __future__ import annotations
1✔
6

7
import numpy as np
1✔
8

9
from pymatgen.core.operations import MagSymmOp, SymmOp
1✔
10
from pymatgen.electronic_structure.core import Magmom
1✔
11
from pymatgen.util.testing import PymatgenTest
1✔
12

13

14
class SymmOpTestCase(PymatgenTest):
1✔
15
    def setUp(self):
1✔
16
        self.op = SymmOp.from_axis_angle_and_translation([0, 0, 1], 30, False, [0, 0, 1])
1✔
17

18
    def test_properties(self):
1✔
19
        rot = self.op.rotation_matrix
1✔
20
        vec = self.op.translation_vector
1✔
21
        self.assertArrayAlmostEqual(rot, [[0.8660254, -0.5, 0.0], [0.5, 0.8660254, 0.0], [0.0, 0.0, 1.0]], 2)
1✔
22
        self.assertArrayAlmostEqual(vec, [0, 0, 1], 2)
1✔
23

24
    def test_operate(self):
1✔
25
        point = np.array([1, 2, 3])
1✔
26
        newcoord = self.op.operate(point)
1✔
27
        self.assertArrayAlmostEqual(newcoord, [-0.1339746, 2.23205081, 4.0], 2)
1✔
28

29
    def test_operate_multi(self):
1✔
30
        point = np.array([1, 2, 3])
1✔
31
        newcoords = self.op.operate_multi([point, point])
1✔
32
        self.assertArrayAlmostEqual(newcoords, [[-0.1339746, 2.23205081, 4.0]] * 2, 2)
1✔
33
        newcoords = self.op.operate_multi([[point, point]] * 2)
1✔
34
        self.assertArrayAlmostEqual(newcoords, [[[-0.1339746, 2.23205081, 4.0]] * 2] * 2, 2)
1✔
35

36
    def test_inverse(self):
1✔
37
        point = np.random.rand(3)
1✔
38
        newcoord = self.op.operate(point)
1✔
39
        self.assertArrayAlmostEqual(self.op.inverse.operate(newcoord), point, 2)
1✔
40

41
    def test_reflection(self):
1✔
42
        normal = np.random.rand(3)
1✔
43
        origin = np.random.rand(3)
1✔
44
        refl = SymmOp.reflection(normal, origin)
1✔
45
        point = np.random.rand(3)
1✔
46
        newcoord = refl.operate(point)
1✔
47
        # Distance to the plane should be negatives of each other.
48
        assert round(abs(np.dot(newcoord - origin, normal) - -np.dot(point - origin, normal)), 7) == 0
1✔
49

50
    def test_apply_rotation_only(self):
1✔
51
        point = np.random.rand(3)
1✔
52
        newcoord = self.op.operate(point)
1✔
53
        rotate_only = self.op.apply_rotation_only(point)
1✔
54
        self.assertArrayAlmostEqual(rotate_only + self.op.translation_vector, newcoord, 2)
1✔
55

56
    def test_transform_tensor(self):
1✔
57
        # Rank 2
58
        tensor = np.arange(0, 9).reshape(3, 3)
1✔
59
        new_tensor = self.op.transform_tensor(tensor)
1✔
60
        self.assertArrayAlmostEqual(
1✔
61
            new_tensor,
62
            [
63
                [-0.73205, -1.73205, -0.76794],
64
                [0.26795, 4.73205, 5.33013],
65
                [1.69615, 9.06218, 8.0],
66
            ],
67
            5,
68
        )
69

70
        # Rank 3
71
        tensor = np.arange(0, 27).reshape(3, 3, 3)
1✔
72
        new_tensor = self.op.transform_tensor(tensor)
1✔
73
        self.assertArrayAlmostEqual(
1✔
74
            new_tensor,
75
            [
76
                [
77
                    [-0.871, -2.884, -1.928],
78
                    [-2.152, -6.665, -4.196],
79
                    [-1.026, -2.830, -1.572],
80
                ],
81
                [
82
                    [0.044, 1.531, 1.804],
83
                    [4.263, 21.008, 17.928],
84
                    [5.170, 23.026, 18.722],
85
                ],
86
                [
87
                    [1.679, 7.268, 5.821],
88
                    [9.268, 38.321, 29.919],
89
                    [8.285, 33.651, 26.000],
90
                ],
91
            ],
92
            3,
93
        )
94
        # Rank 4
95
        tensor = np.arange(0, 81).reshape(3, 3, 3, 3)
1✔
96
        new_tensor = self.op.transform_tensor(tensor)
1✔
97
        self.assertArrayAlmostEqual(
1✔
98
            new_tensor,
99
            [
100
                [
101
                    [
102
                        [-0.981, -3.526, -2.514],
103
                        [-3.258, -11.660, -8.286],
104
                        [-2.184, -7.786, -5.517],
105
                    ],
106
                    [
107
                        [-2.454, -8.660, -6.090],
108
                        [-7.660, -26.722, -18.629],
109
                        [-4.858, -16.763, -11.588],
110
                    ],
111
                    [
112
                        [-1.194, -4.090, -2.811],
113
                        [-3.358, -11.165, -7.490],
114
                        [-1.909, -6.124, -3.983],
115
                    ],
116
                ],
117
                [
118
                    [
119
                        [-0.043, 0.340, 0.499],
120
                        [1.340, 6.866, 5.959],
121
                        [1.731, 7.825, 6.412],
122
                    ],
123
                    [
124
                        [4.340, 18.062, 14.155],
125
                        [21.794, 88.301, 68.123],
126
                        [18.754, 75.087, 57.517],
127
                    ],
128
                    [
129
                        [5.427, 21.620, 16.510],
130
                        [24.352, 95.979, 72.811],
131
                        [19.876, 77.909, 58.899],
132
                    ],
133
                ],
134
                [
135
                    [
136
                        [1.777, 6.999, 5.306],
137
                        [7.731, 30.218, 22.804],
138
                        [6.208, 24.170, 18.194],
139
                    ],
140
                    [
141
                        [9.927, 38.414, 28.804],
142
                        [41.146, 158.656, 118.694],
143
                        [32.170, 123.792, 92.488],
144
                    ],
145
                    [
146
                        [8.914, 34.268, 25.586],
147
                        [36.268, 139.086, 103.684],
148
                        [28.050, 107.416, 80.000],
149
                    ],
150
                ],
151
            ],
152
            3,
153
        )
154

155
    def test_are_symmetrically_related(self):
1✔
156
        point = np.random.rand(3)
1✔
157
        newcoord = self.op.operate(point)
1✔
158
        assert self.op.are_symmetrically_related(point, newcoord)
1✔
159
        assert self.op.are_symmetrically_related(newcoord, point)
1✔
160

161
    def test_are_symmetrically_related_vectors(self):
1✔
162
        tol = 0.001
1✔
163
        from_a = np.random.rand(3)
1✔
164
        to_a = np.random.rand(3)
1✔
165
        r_a = np.random.randint(0, 10, 3)
1✔
166
        from_b = self.op.operate(from_a)
1✔
167
        to_b = self.op.operate(to_a)
1✔
168
        floored = np.floor([from_b, to_b])
1✔
169
        is_too_close = np.abs([from_b, to_b] - floored) > 1 - tol
1✔
170
        floored[is_too_close] += 1
1✔
171
        r_b = self.op.apply_rotation_only(r_a) - floored[0] + floored[1]
1✔
172
        from_b = from_b % 1
1✔
173
        to_b = to_b % 1
1✔
174
        assert self.op.are_symmetrically_related_vectors(from_a, to_a, r_a, from_b, to_b, r_b)[0]
1✔
175
        assert not self.op.are_symmetrically_related_vectors(from_a, to_a, r_a, from_b, to_b, r_b)[1]
1✔
176
        assert self.op.are_symmetrically_related_vectors(to_a, from_a, -r_a, from_b, to_b, r_b)[0]
1✔
177
        assert self.op.are_symmetrically_related_vectors(to_a, from_a, -r_a, from_b, to_b, r_b)[1]
1✔
178

179
    def test_to_from_dict(self):
1✔
180
        d = self.op.as_dict()
1✔
181
        op = SymmOp.from_dict(d)
1✔
182
        point = np.random.rand(3)
1✔
183
        newcoord = self.op.operate(point)
1✔
184
        assert op.are_symmetrically_related(point, newcoord)
1✔
185

186
    def test_inversion(self):
1✔
187
        origin = np.random.rand(3)
1✔
188
        op = SymmOp.inversion(origin)
1✔
189
        pt = np.random.rand(3)
1✔
190
        inv_pt = op.operate(pt)
1✔
191
        self.assertArrayAlmostEqual(pt - origin, origin - inv_pt)
1✔
192

193
    def test_xyz(self):
1✔
194
        op = SymmOp([[1, -1, 0, 0], [0, -1, 0, 0], [0, 0, -1, 0], [0, 0, 0, 1]])
1✔
195
        s = op.as_xyz_string()
1✔
196
        assert s == "x-y, -y, -z"
1✔
197
        assert op == SymmOp.from_xyz_string(s)
1✔
198

199
        op2 = SymmOp([[0, -1, 0, 0.5], [1, 0, 0, 0.5], [0, 0, 1, 0.5 + 1e-7], [0, 0, 0, 1]])
1✔
200
        s2 = op2.as_xyz_string()
1✔
201
        assert s2 == "-y+1/2, x+1/2, z+1/2"
1✔
202
        assert op2 == SymmOp.from_xyz_string(s2)
1✔
203

204
        op2 = SymmOp(
1✔
205
            [
206
                [3, -2, -1, 0.5],
207
                [-1, 0, 0, 12.0 / 13],
208
                [0, 0, 1, 0.5 + 1e-7],
209
                [0, 0, 0, 1],
210
            ]
211
        )
212
        s2 = op2.as_xyz_string()
1✔
213
        assert s2 == "3x-2y-z+1/2, -x+12/13, z+1/2"
1✔
214
        assert op2 == SymmOp.from_xyz_string(s2)
1✔
215

216
        op3 = SymmOp.from_xyz_string("3x - 2y - z+1 /2 , -x+12/ 13, z+1/2")
1✔
217
        assert op2 == op3
1✔
218

219
        # Ensure strings can be read in any order
220
        op4 = SymmOp.from_xyz_string("1 /2 + 3X - 2y - z , 12/ 13-x, z+1/2")
1✔
221
        op5 = SymmOp.from_xyz_string("+1 /2 + 3x - 2y - z , 12/ 13-x, +1/2+z")
1✔
222
        assert op4 == op3
1✔
223
        assert op4 == op5
1✔
224
        assert op3 == op5
1✔
225

226
        # TODO: assertWarns not in Python 2.x unittest
227
        # update PymatgenTest for unittest2?
228
        # self.assertWarns(UserWarning, self.op.as_xyz_string)
229

230
        o = SymmOp.from_xyz_string("0.5+x, 0.25+y, 0.75+z")
1✔
231
        self.assertArrayAlmostEqual(o.translation_vector, [0.5, 0.25, 0.75])
1✔
232
        o = SymmOp.from_xyz_string("x + 0.5, y + 0.25, z + 0.75")
1✔
233
        self.assertArrayAlmostEqual(o.translation_vector, [0.5, 0.25, 0.75])
1✔
234

235

236
class MagSymmOpTestCase(PymatgenTest):
1✔
237
    def test_xyzt_string(self):
1✔
238
        xyzt_strings = ["x, y, z, +1", "x, y, z, -1", "-y+1/2, x+1/2, x+1/2, +1"]
1✔
239

240
        for xyzt_string in xyzt_strings:
1✔
241
            op = MagSymmOp.from_xyzt_string(xyzt_string)
1✔
242
            xyzt_string_out = op.as_xyzt_string()
1✔
243
            assert xyzt_string == xyzt_string_out
1✔
244

245
        op = SymmOp(
1✔
246
            [
247
                [3, -2, -1, 0.5],
248
                [-1, 0, 0, 12.0 / 13],
249
                [0, 0, 1, 0.5 + 1e-7],
250
                [0, 0, 0, 1],
251
            ]
252
        )
253

254
        magop = MagSymmOp.from_symmop(op, -1)
1✔
255
        magop_str = magop.as_xyzt_string()
1✔
256
        assert magop.time_reversal == -1
1✔
257
        assert magop_str == "3x-2y-z+1/2, -x+12/13, z+1/2, -1"
1✔
258

259
    def test_to_from_dict(self):
1✔
260
        op = SymmOp(
1✔
261
            [
262
                [3, -2, -1, 0.5],
263
                [-1, 0, 0, 12.0 / 13],
264
                [0, 0, 1, 0.5 + 1e-7],
265
                [0, 0, 0, 1],
266
            ]
267
        )
268
        magop = MagSymmOp.from_symmop(op, -1)
1✔
269
        magop2 = MagSymmOp.from_dict(magop.as_dict())
1✔
270
        assert magop2.time_reversal == -1
1✔
271
        assert magop2.as_xyzt_string() == "3x-2y-z+1/2, -x+12/13, z+1/2, -1"
1✔
272

273
    def test_operate_magmom(self):
1✔
274
        # all test magmoms are the same
275
        magmoms = [
1✔
276
            Magmom([1, 2, 3]),  # as Magmom
277
            [1, 2, 3],  # as list
278
            Magmom([-3, 2, 1], saxis=[1, 0, 0]),
279
        ]  # as Magmom with non-default saxis
280

281
        xyzt_strings = ["x, y, z, +1", "x, y, z, -1", "x, -y, z, -1", "-x, -y, z, -1"]
1✔
282

283
        transformed_magmoms = [[1, 2, 3], [-1, -2, -3], [1, -2, 3], [1, 2, -3]]
1✔
284

285
        for xyzt_string, transformed_magmom in zip(xyzt_strings, transformed_magmoms):
1✔
286
            for magmom in magmoms:
1✔
287
                op = MagSymmOp.from_xyzt_string(xyzt_string)
1✔
288
                assert np.allclose(transformed_magmom, op.operate_magmom(magmom).global_moment)
1✔
289

290

291
if __name__ == "__main__":
1✔
292
    import unittest
×
293

294
    unittest.main()
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc