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 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231
|
# fmt: off
import re
import tempfile
import numpy as np
import numpy.testing as npt
from ase import Atoms
from ase.io.cube import ATOMS, DATA, read_cube, read_cube_data, write_cube
from ase.units import Bohr
# Have some real data to write to a file
file_content = """Generated by octopus maya
git: 5b62360b6ec96e210d8ebbbd817bea74da18dfa8 build: \
Fri Oct 8 14:58:44 CEST 2021
5 -3.779452 -1.889726 -3.779452
5 1.889726 0.000000 0.000000
3 0.000000 1.889726 0.000000
5 0.000000 0.000000 0.000000
6 0.000000 0.000000 0.000000 0.000000
1 0.000000 0.000000 0.000000 2.057912
1 0.000000 1.940220 0.000000 -0.685971
1 0.000000 -0.970110 -1.680269 -0.685971
1 0.000000 -0.970110 1.680269 -0.685971
0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00
0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00
0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00
0.000000E+00 0.284545E-01 0.706656E-01 0.000000E+00 0.000000E+00
0.000000E+00 0.000000E+00 0.391115E-01 0.000000E+00 0.000000E+00
0.000000E+00 0.284545E-01 0.706656E-01 0.000000E+00 0.000000E+00
0.000000E+00 0.399121E-01 0.926179E-01 0.000000E+00 0.000000E+00
0.000000E+00 0.325065E-01 0.272831E+00 0.173787E+00 0.149557E-01
0.000000E+00 0.399121E-01 0.926179E-01 0.000000E+00 0.000000E+00
0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00
0.000000E+00 0.506939E-01 0.138292E+00 0.000000E+00 0.000000E+00
0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00
0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00
0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00
0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00"""
def test_cube_writing():
d = 1.104 # N2 bondlength
at = Atoms("N2", [(0, 0, 0), (0, 0, d * Bohr)])
dummydata = np.arange(8).reshape((2, 2, 2))
origin_in = (42 * Bohr, 0, 0)
comment_regex = r"(Cube file from ASE, written on )([a-zA-Z ])*([0-9: ])*"
# create output
with tempfile.NamedTemporaryFile(mode="r+") as outfil:
write_cube(outfil, at, data=dummydata, origin=origin_in)
# reset read head
outfil.seek(0)
# Check default comment
comment_line = outfil.readline()
assert re.match(comment_regex, comment_line)
# Check constant string
assert outfil.readline() == ("OUTER LOOP: X, MIDDLE LOOP: Y, "
"INNER LOOP: Z\n")
# Check origin
origin_from_file = outfil.readline().split()[1:]
origin_from_file = tuple(
map(lambda p: float(p) * Bohr, origin_from_file))
assert origin_from_file == origin_in
# skip three lines
outfil.readline()
outfil.readline()
outfil.readline()
# check Atoms and positions
atom1 = outfil.readline().split()
assert atom1 == ["7", "0.000000", "0.000000", "0.000000", "0.000000"]
atom2 = outfil.readline().split()
assert atom2 == ["7", "0.000000", "0.000000",
"0.000000", f"{d:.6f}"]
# Check data
data_lines = list(
map(lambda l: float(l.rstrip("\n")), outfil.readlines()))
for idx, line in enumerate(data_lines):
assert float(idx) == line
def test_cube_reading():
with tempfile.NamedTemporaryFile(mode="r+") as cubefil:
# Write data to a file
cubefil.write(file_content)
cubefil.seek(0)
# read data using cube reading
result = read_cube(cubefil)
npt.assert_equal(
result[ATOMS].get_atomic_numbers(), np.array([6, 1, 1, 1, 1])
)
assert isinstance(result, dict)
# check data
assert result[DATA].shape == (5, 3, 5)
# check spacing
assert result["spacing"].shape == (3, 3)
# check that values are on the diagonal (correctness of order in
# reading)
npt.assert_almost_equal(
result["spacing"].diagonal() / Bohr,
np.array([1.889726, 1.889726, 0.000000]),
)
# check that sum is only 1.889726 for every column (correctness of
# value)
npt.assert_almost_equal(
result["spacing"].sum(axis=0) / Bohr,
np.array([1.889726, 1.889726, 0.000000]),
)
# check origin
assert result["origin"].shape == (3,)
npt.assert_almost_equal(
result["origin"], np.array([-3.779452, -1.889726, -3.779452]) * Bohr
)
# check PBC
assert (result[ATOMS].get_pbc() == (True, True, False)).all()
file_content_multiple = """ Benzene_Opt_Freq_B3LYP_6_31G_d_p_ MO=HOMO,LUMO
MO coefficients
-12 -8.797610 -9.151024 -6.512752 2
3 8.063676 0.000000 0.000000
3 0.000000 8.063676 0.000000
3 0.000000 0.000000 8.063676
6 6.000000 -2.284858 -1.319192 0.000000
6 6.000000 -2.284825 1.319137 0.000000
6 6.000000 0.000000 -2.638272 0.000000
6 6.000000 2.284845 -1.319103 0.000000
6 6.000000 -0.000008 2.638273 0.000000
6 6.000000 2.284870 1.319165 0.000000
1 1.000000 -4.062255 -2.345299 0.000000
1 1.000000 -0.000025 -4.690600 0.000000
1 1.000000 -4.062297 2.345119 0.000000
1 1.000000 0.000075 4.690601 0.000000
1 1.000000 4.062174 2.345444 0.000000
1 1.000000 4.062187 -2.345312 0.000000
2 21 22
-2.74760E-12 -8.90988E-12 5.59016E-10 1.81277E-09 8.76453E-16 2.84215E-15
-1.43957E-07 -2.02610E-07 2.92889E-05 4.12223E-05 4.59206E-11 6.46303E-11
-6.71453E-10 9.41323E-10 1.36612E-07 -1.91518E-07 2.14186E-13 -3.00272E-13
5.12861E-08 6.37111E-08 -1.04345E-05 -1.29624E-05 -1.63597E-11 -2.03231E-11
-3.53200E-05 -7.80160E-05 1.33966E-02 3.06849E-02 1.12667E-08 2.48862E-08
-3.26637E-06 4.17535E-06 6.66354E-04 -8.51133E-04 1.04193E-09 -1.33189E-09
8.90476E-11 1.24804E-10 -1.81173E-08 -2.53921E-08 -2.84052E-14 -3.98110E-14
3.14350E-06 1.73228E-06 -6.39634E-04 -3.52493E-04 -1.00274E-09 -5.52577E-10
6.74853E-09 -2.18944E-08 -1.37303E-06 4.45455E-06 -2.15271E-12 6.98406E-12
"""
def test_cube_reading_multiple():
with tempfile.NamedTemporaryFile(mode="r+") as cubefil:
# Write data to a file
cubefil.write(file_content_multiple)
cubefil.seek(0)
# read data using cube reading
result = read_cube(cubefil)
npt.assert_equal(
result[ATOMS].get_atomic_numbers(),
[6, 6, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1]
)
assert isinstance(result, dict)
# check data
assert result[DATA].shape == (3, 3, 3)
# and datas
assert len(result["datas"]) == 2
assert (
result[DATA].shape
== result["datas"][0].shape
== result["datas"][1].shape
)
# check labels
assert result["labels"] == [21, 22]
# check spacing
assert result["spacing"].shape == (3, 3)
# check that values are on the diagonal
# (correctness of order in reading)
npt.assert_almost_equal(
result["spacing"].diagonal() / Bohr,
np.array([8.063676, 8.063676, 8.063676]),
)
# check that sum is only 8.063676 for every column
# (correctness of value)
npt.assert_almost_equal(
result["spacing"].sum(axis=0) / Bohr,
np.array([8.063676, 8.063676, 8.063676]),
)
# check origin
assert result["origin"].shape == (3,)
npt.assert_almost_equal(
result["origin"], np.array([-8.797610, -9.151024, -6.512752]) * Bohr
)
# check PBC
# I don't know what this does so please check...
assert (result[ATOMS].get_pbc() == (True, True, True)).all()
def test_reading_using_io():
with tempfile.NamedTemporaryFile(mode="r+") as cubefil:
# Write data to a file
cubefil.write(file_content)
cubefil.seek(0)
result = read_cube_data(cubefil)
assert isinstance(result, tuple)
assert len(result) == 2
assert result[0].shape == (5, 3, 5)
assert isinstance(result[1], Atoms)
npt.assert_equal(result[1].get_atomic_numbers(),
np.array([6, 1, 1, 1, 1]))
|