stjames 0.0.42__tar.gz → 0.0.43__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of stjames might be problematic. Click here for more details.
- {stjames-0.0.42/stjames.egg-info → stjames-0.0.43}/PKG-INFO +1 -1
- {stjames-0.0.42 → stjames-0.0.43}/pyproject.toml +1 -1
- {stjames-0.0.42 → stjames-0.0.43}/stjames/atom.py +1 -1
- {stjames-0.0.42 → stjames-0.0.43}/stjames/molecule.py +87 -2
- {stjames-0.0.42 → stjames-0.0.43/stjames.egg-info}/PKG-INFO +1 -1
- {stjames-0.0.42 → stjames-0.0.43}/stjames.egg-info/SOURCES.txt +1 -0
- stjames-0.0.43/tests/test_from_extxyz.py +231 -0
- {stjames-0.0.42 → stjames-0.0.43}/LICENSE +0 -0
- {stjames-0.0.42 → stjames-0.0.43}/README.md +0 -0
- {stjames-0.0.42 → stjames-0.0.43}/setup.cfg +0 -0
- {stjames-0.0.42 → stjames-0.0.43}/stjames/__init__.py +0 -0
- {stjames-0.0.42 → stjames-0.0.43}/stjames/_deprecated_solvent_settings.py +0 -0
- {stjames-0.0.42 → stjames-0.0.43}/stjames/base.py +0 -0
- {stjames-0.0.42 → stjames-0.0.43}/stjames/basis_set.py +0 -0
- {stjames-0.0.42 → stjames-0.0.43}/stjames/calculation.py +0 -0
- {stjames-0.0.42 → stjames-0.0.43}/stjames/constraint.py +0 -0
- {stjames-0.0.42 → stjames-0.0.43}/stjames/correction.py +0 -0
- {stjames-0.0.42 → stjames-0.0.43}/stjames/data/__init__.py +0 -0
- {stjames-0.0.42 → stjames-0.0.43}/stjames/data/bragg_radii.json +0 -0
- {stjames-0.0.42 → stjames-0.0.43}/stjames/data/elements.py +0 -0
- {stjames-0.0.42 → stjames-0.0.43}/stjames/data/isotopes.json +0 -0
- {stjames-0.0.42 → stjames-0.0.43}/stjames/data/nist_isotopes.json +0 -0
- {stjames-0.0.42 → stjames-0.0.43}/stjames/data/read_nist_isotopes.py +0 -0
- {stjames-0.0.42 → stjames-0.0.43}/stjames/data/symbol_element.json +0 -0
- {stjames-0.0.42 → stjames-0.0.43}/stjames/diis_settings.py +0 -0
- {stjames-0.0.42 → stjames-0.0.43}/stjames/grid_settings.py +0 -0
- {stjames-0.0.42 → stjames-0.0.43}/stjames/int_settings.py +0 -0
- {stjames-0.0.42 → stjames-0.0.43}/stjames/message.py +0 -0
- {stjames-0.0.42 → stjames-0.0.43}/stjames/method.py +0 -0
- {stjames-0.0.42 → stjames-0.0.43}/stjames/mode.py +0 -0
- {stjames-0.0.42 → stjames-0.0.43}/stjames/opt_settings.py +0 -0
- {stjames-0.0.42 → stjames-0.0.43}/stjames/periodic_cell.py +0 -0
- {stjames-0.0.42 → stjames-0.0.43}/stjames/py.typed +0 -0
- {stjames-0.0.42 → stjames-0.0.43}/stjames/scf_settings.py +0 -0
- {stjames-0.0.42 → stjames-0.0.43}/stjames/settings.py +0 -0
- {stjames-0.0.42 → stjames-0.0.43}/stjames/solvent.py +0 -0
- {stjames-0.0.42 → stjames-0.0.43}/stjames/status.py +0 -0
- {stjames-0.0.42 → stjames-0.0.43}/stjames/task.py +0 -0
- {stjames-0.0.42 → stjames-0.0.43}/stjames/thermochem_settings.py +0 -0
- {stjames-0.0.42 → stjames-0.0.43}/stjames/types.py +0 -0
- {stjames-0.0.42 → stjames-0.0.43}/stjames/workflows/__init__.py +0 -0
- {stjames-0.0.42 → stjames-0.0.43}/stjames/workflows/admet.py +0 -0
- {stjames-0.0.42 → stjames-0.0.43}/stjames/workflows/basic_calculation.py +0 -0
- {stjames-0.0.42 → stjames-0.0.43}/stjames/workflows/bde.py +0 -0
- {stjames-0.0.42 → stjames-0.0.43}/stjames/workflows/conformer.py +0 -0
- {stjames-0.0.42 → stjames-0.0.43}/stjames/workflows/descriptors.py +0 -0
- {stjames-0.0.42 → stjames-0.0.43}/stjames/workflows/fukui.py +0 -0
- {stjames-0.0.42 → stjames-0.0.43}/stjames/workflows/molecular_dynamics.py +0 -0
- {stjames-0.0.42 → stjames-0.0.43}/stjames/workflows/multistage_opt.py +0 -0
- {stjames-0.0.42 → stjames-0.0.43}/stjames/workflows/pka.py +0 -0
- {stjames-0.0.42 → stjames-0.0.43}/stjames/workflows/redox_potential.py +0 -0
- {stjames-0.0.42 → stjames-0.0.43}/stjames/workflows/scan.py +0 -0
- {stjames-0.0.42 → stjames-0.0.43}/stjames/workflows/spin_states.py +0 -0
- {stjames-0.0.42 → stjames-0.0.43}/stjames/workflows/tautomer.py +0 -0
- {stjames-0.0.42 → stjames-0.0.43}/stjames/workflows/workflow.py +0 -0
- {stjames-0.0.42 → stjames-0.0.43}/stjames.egg-info/dependency_links.txt +0 -0
- {stjames-0.0.42 → stjames-0.0.43}/stjames.egg-info/requires.txt +0 -0
- {stjames-0.0.42 → stjames-0.0.43}/stjames.egg-info/top_level.txt +0 -0
- {stjames-0.0.42 → stjames-0.0.43}/tests/test_molecule.py +0 -0
|
@@ -60,7 +60,7 @@ class Atom(Base):
|
|
|
60
60
|
Atom(1, [0.00000, 0.00000, 0.00000])
|
|
61
61
|
"""
|
|
62
62
|
name, *xyz = xyz_line.split()
|
|
63
|
-
symbol = int(name) if name.isdigit() else SYMBOL_ELEMENT[name]
|
|
63
|
+
symbol = int(name) if name.isdigit() else SYMBOL_ELEMENT[name.title()]
|
|
64
64
|
if not len(xyz) == 3:
|
|
65
65
|
raise ValueError("XYZ file should have 3 coordinates per atom")
|
|
66
66
|
return cls(atomic_number=symbol, position=xyz)
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import re
|
|
1
2
|
from pathlib import Path
|
|
2
3
|
from typing import Iterable, Optional, Self
|
|
3
4
|
|
|
4
5
|
import pydantic
|
|
5
|
-
from pydantic import NonNegativeInt, PositiveInt
|
|
6
|
+
from pydantic import NonNegativeInt, PositiveInt, ValidationError
|
|
6
7
|
|
|
7
8
|
from .atom import Atom
|
|
8
9
|
from .base import Base
|
|
@@ -135,6 +136,8 @@ class Molecule(Base):
|
|
|
135
136
|
match format:
|
|
136
137
|
case "xyz":
|
|
137
138
|
return cls.from_xyz_lines(f.readlines(), charge=charge, multiplicity=multiplicity)
|
|
139
|
+
case "extxyz":
|
|
140
|
+
return cls.from_extxyz_lines(f.readlines(), charge=charge, multiplicity=multiplicity)
|
|
138
141
|
case _:
|
|
139
142
|
raise ValueError(f"Unsupported {format=}")
|
|
140
143
|
|
|
@@ -161,7 +164,7 @@ class Molecule(Base):
|
|
|
161
164
|
|
|
162
165
|
try:
|
|
163
166
|
return cls(atoms=[Atom.from_xyz(line) for line in lines], charge=charge, multiplicity=multiplicity)
|
|
164
|
-
except
|
|
167
|
+
except (ValueError, ValidationError) as e:
|
|
165
168
|
raise MoleculeReadError("Error reading molecule from xyz") from e
|
|
166
169
|
|
|
167
170
|
def to_xyz(self, comment: str = "", out_file: Path | str | None = None) -> str:
|
|
@@ -190,3 +193,85 @@ class Molecule(Base):
|
|
|
190
193
|
f.write(out)
|
|
191
194
|
|
|
192
195
|
return out
|
|
196
|
+
|
|
197
|
+
@classmethod
|
|
198
|
+
def from_extxyz(cls: type[Self], extxyz: str, charge: int = 0, multiplicity: PositiveInt = 1) -> Self:
|
|
199
|
+
r"""
|
|
200
|
+
Generate a Molecule from a EXTXYZ string. Currently only supporting Lattice and Properties fields.
|
|
201
|
+
|
|
202
|
+
>>> Molecule.from_extxyz('''
|
|
203
|
+
... 2
|
|
204
|
+
... Lattice="6.0 0.0 0.0 6.0 0.0 0.0 6.0 0.0 0.0"Properties=species:S:1:pos:R:3
|
|
205
|
+
... H 0 0 0
|
|
206
|
+
... H 0 0 1
|
|
207
|
+
... ''').cell.lattice_vectors
|
|
208
|
+
((6.0, 0.0, 0.0), (6.0, 0.0, 0.0), (6.0, 0.0, 0.0))
|
|
209
|
+
"""
|
|
210
|
+
|
|
211
|
+
return cls.from_extxyz_lines(extxyz.strip().splitlines(), charge=charge, multiplicity=multiplicity)
|
|
212
|
+
|
|
213
|
+
@classmethod
|
|
214
|
+
def from_extxyz_lines(cls: type[Self], lines: Iterable[str], charge: int = 0, multiplicity: PositiveInt = 1) -> Self:
|
|
215
|
+
# ensure first line is number of atoms
|
|
216
|
+
lines = list(lines)
|
|
217
|
+
if len(lines[0].split()) == 1:
|
|
218
|
+
natoms = lines[0].strip()
|
|
219
|
+
if not natoms.isdigit() or (int(lines[0]) != len(lines) - 2):
|
|
220
|
+
raise MoleculeReadError(f"First line of EXTXYZ file should be the number of atoms, got: {lines[0]} != {len(lines) - 2}")
|
|
221
|
+
lines = lines[1:]
|
|
222
|
+
else:
|
|
223
|
+
raise MoleculeReadError(f"First line of EXTXYZ should be only an int denoting number of atoms. Got {lines[0].split()}")
|
|
224
|
+
|
|
225
|
+
# ensure second line contains key-value pairs
|
|
226
|
+
if "=" not in lines[0]:
|
|
227
|
+
raise MoleculeReadError(f"Invalid property line, got {lines[0]}")
|
|
228
|
+
|
|
229
|
+
cell = parse_comment_line(lines[0])
|
|
230
|
+
lines = lines[1:]
|
|
231
|
+
|
|
232
|
+
try:
|
|
233
|
+
return cls(atoms=[Atom.from_xyz(line) for line in lines], cell=cell, charge=charge, multiplicity=multiplicity)
|
|
234
|
+
except (ValueError, ValidationError) as e:
|
|
235
|
+
raise MoleculeReadError("Error reading molecule from extxyz") from e
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
def parse_comment_line(line: str) -> PeriodicCell:
|
|
239
|
+
"""
|
|
240
|
+
currently only supporting lattice and porperites fields from comment line
|
|
241
|
+
modify in future to support other fields from comment from_xyz_lines
|
|
242
|
+
ex: name, mulitplicity, charge, etc.
|
|
243
|
+
"""
|
|
244
|
+
cell = None
|
|
245
|
+
# Regular expression to match key="value", key='value', or key=value
|
|
246
|
+
pattern = r"(\S+?=(?:\".*?\"|\'.*?\'|\S+))"
|
|
247
|
+
pairs = re.findall(pattern, line)
|
|
248
|
+
|
|
249
|
+
prop_dict = {}
|
|
250
|
+
for pair in pairs:
|
|
251
|
+
key, value = pair.split("=", 1)
|
|
252
|
+
if key.lower() == "lattice":
|
|
253
|
+
value = value.strip("'\"").split()
|
|
254
|
+
if len(value) != 9:
|
|
255
|
+
raise MoleculeReadError(f"Lattice should have 9 entries got {len(value)}")
|
|
256
|
+
|
|
257
|
+
# Convert the value to a 3x3 tuple of tuples of floats
|
|
258
|
+
try:
|
|
259
|
+
cell = tuple(tuple(map(float, value[i : i + 3])) for i in range(0, 9, 3))
|
|
260
|
+
except ValueError:
|
|
261
|
+
raise MoleculeReadError(f"Lattice should be floats, got {value}")
|
|
262
|
+
|
|
263
|
+
prop_dict[key] = value
|
|
264
|
+
|
|
265
|
+
elif key.lower() == "properties":
|
|
266
|
+
if value.lower() != "species:s:1:pos:r:3":
|
|
267
|
+
raise MoleculeReadError(f"Only accepting properties of form species:S:1:pos:R:3, got {value}")
|
|
268
|
+
prop_dict[key] = value
|
|
269
|
+
else:
|
|
270
|
+
raise MoleculeReadError(f"Currently only accepting lattice and propery keys. Got {key}")
|
|
271
|
+
|
|
272
|
+
if cell is None:
|
|
273
|
+
raise MoleculeReadError("Lattice field is required but missing.")
|
|
274
|
+
|
|
275
|
+
if "properties" not in [key.lower() for key in prop_dict.keys()]:
|
|
276
|
+
raise MoleculeReadError(f"Property field is required, got keys {prop_dict.keys()}")
|
|
277
|
+
return PeriodicCell(lattice_vectors=cell)
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
|
|
3
|
+
from stjames import Atom, Molecule, MoleculeReadError, PeriodicCell
|
|
4
|
+
|
|
5
|
+
valid_extxyz = """
|
|
6
|
+
5
|
|
7
|
+
Lattice="6.0 0.0 0.0 0.0 6.0 0.0 0.0 0.0 6.0" Properties=species:S:1:pos:R:3
|
|
8
|
+
C 0.0 0.0 0.0
|
|
9
|
+
H 0.0 0.0 1.0
|
|
10
|
+
H 1.0 0.0 0.0
|
|
11
|
+
H 0.0 1.0 0.0
|
|
12
|
+
H 1.0 1.0 1.0
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
incorrect_num_atoms = """
|
|
16
|
+
6
|
|
17
|
+
Lattice="6.0 0.0 0.0 0.0 6.0 0.0 0.0 0.0 6.0" Properties=species:S:1:pos:R:3
|
|
18
|
+
C 0.0 0.0 0.0
|
|
19
|
+
H 0.0 0.0 1.0
|
|
20
|
+
H 1.0 0.0 0.0
|
|
21
|
+
H 0.0 1.0 0.0
|
|
22
|
+
H 1.0 1.0 1.0
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
not_digit_num_atoms = """
|
|
26
|
+
v
|
|
27
|
+
Lattice="6.0 0.0 0.0 0.0 6.0 0.0 0.0 0.0 6.0" Properties=species:S:1:pos:R:3
|
|
28
|
+
C 0.0 0.0 0.0
|
|
29
|
+
H 0.0 0.0 1.0
|
|
30
|
+
H 1.0 0.0 0.0
|
|
31
|
+
H 0.0 1.0 0.0
|
|
32
|
+
H 1.0 1.0 1.0
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
many_num_atoms = """
|
|
36
|
+
6 9
|
|
37
|
+
Lattice="6.0 0.0 0.0 0.0 6.0 0.0 0.0 0.0 6.0" Properties=species:S:1:pos:R:3
|
|
38
|
+
C 0.0 0.0 0.0
|
|
39
|
+
H 0.0 0.0 1.0
|
|
40
|
+
H 1.0 0.0 0.0
|
|
41
|
+
H 0.0 1.0 0.0
|
|
42
|
+
H 1.0 1.0 1.0
|
|
43
|
+
"""
|
|
44
|
+
no_num_atoms = """
|
|
45
|
+
Lattice="6.0 0.0 0.0 0.0 6.0 0.0 0.0 0.0 6.0" Properties=species:S:1:pos:R:3
|
|
46
|
+
C 0.0 0.0 0.0
|
|
47
|
+
H 0.0 0.0 1.0
|
|
48
|
+
H 1.0 0.0 0.0
|
|
49
|
+
H 0.0 1.0 0.0
|
|
50
|
+
H 1.0 1.0 1.0
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
xyz_style = """
|
|
54
|
+
5
|
|
55
|
+
Comment
|
|
56
|
+
C 0.0 0.0 0.0
|
|
57
|
+
H 0.0 0.0 1.0
|
|
58
|
+
H 1.0 0.0 0.0
|
|
59
|
+
H 0.0 1.0 0.0
|
|
60
|
+
H 1.0 1.0 1.0
|
|
61
|
+
"""
|
|
62
|
+
|
|
63
|
+
missing_lattice = """
|
|
64
|
+
5
|
|
65
|
+
Properties=species:S:1:pos:R:3
|
|
66
|
+
C 0.0 0.0 0.0
|
|
67
|
+
H 0.0 0.0 1.0
|
|
68
|
+
H 1.0 0.0 0.0
|
|
69
|
+
H 0.0 1.0 0.0
|
|
70
|
+
H 1.0 1.0 1.0
|
|
71
|
+
"""
|
|
72
|
+
|
|
73
|
+
missing_properties = """
|
|
74
|
+
5
|
|
75
|
+
Lattice="6.0 0.0 0.0 0.0 6.0 0.0 0.0 0.0 6.0"
|
|
76
|
+
C 0.0 0.0 0.0
|
|
77
|
+
H 0.0 0.0 1.0
|
|
78
|
+
H 1.0 0.0 0.0
|
|
79
|
+
H 0.0 1.0 0.0
|
|
80
|
+
H 1.0 1.0 1.0
|
|
81
|
+
"""
|
|
82
|
+
|
|
83
|
+
incorrect_properites = """
|
|
84
|
+
5
|
|
85
|
+
Lattice="6.0 0.0 0.0 0.0 6.0 0.0 0.0 0.0 6.0" Properties=species:S:1:pos:R:3foo:1
|
|
86
|
+
C 0.0 0.0 0.0
|
|
87
|
+
H 0.0 0.0 1.0
|
|
88
|
+
H 1.0 0.0 0.0
|
|
89
|
+
H 0.0 1.0 0.0
|
|
90
|
+
H 1.0 1.0 1.0
|
|
91
|
+
"""
|
|
92
|
+
|
|
93
|
+
incorrect_lattice_extra = """
|
|
94
|
+
5
|
|
95
|
+
Lattice="6.0 0.0 0.0 0.0 6.0 0.0 0.0 0.0 6.0 3.14" Properties=species:S:1:pos:R:3
|
|
96
|
+
C 0.0 0.0 0.0
|
|
97
|
+
H 0.0 0.0 1.0
|
|
98
|
+
H 1.0 0.0 0.0
|
|
99
|
+
H 0.0 1.0 0.0
|
|
100
|
+
H 1.0 1.0 1.0
|
|
101
|
+
"""
|
|
102
|
+
|
|
103
|
+
incorrect_lattice_equals = """
|
|
104
|
+
5
|
|
105
|
+
Lattice="6.0 0.0 =0.0 0.0 6.0 0.0 0.0 0.0 6.0" Properties=species:S:1:pos:R:3
|
|
106
|
+
C 0.0 0.0 0.0
|
|
107
|
+
H 0.0 0.0 1.0
|
|
108
|
+
H 1.0 0.0 0.0
|
|
109
|
+
H 0.0 1.0 0.0
|
|
110
|
+
H 1.0 1.0 1.0
|
|
111
|
+
"""
|
|
112
|
+
|
|
113
|
+
incorrect_lattice_str = """
|
|
114
|
+
5
|
|
115
|
+
Lattice="6.0 0.0 0.0 hi 6.0 0.0 0.0 0.0 6.0" Properties=species:S:1:pos:R:3
|
|
116
|
+
C 0.0 0.0 0.0
|
|
117
|
+
H 0.0 0.0 1.0
|
|
118
|
+
H 1.0 0.0 0.0
|
|
119
|
+
H 0.0 1.0 0.0
|
|
120
|
+
H 1.0 1.0 1.0
|
|
121
|
+
"""
|
|
122
|
+
|
|
123
|
+
incorrect_lattice_extra_string = """
|
|
124
|
+
5
|
|
125
|
+
Lattice="6.0 0.0 0.0 0.0 sup 6.0 0.0 0.0 0.0 6.0" Properties=species:S:1:pos:R:3
|
|
126
|
+
C 0.0 0.0 0.0
|
|
127
|
+
H 0.0 0.0 1.0
|
|
128
|
+
H 1.0 0.0 0.0
|
|
129
|
+
H 0.0 1.0 0.0
|
|
130
|
+
H 1.0 1.0 1.0
|
|
131
|
+
"""
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
incorrect_lattice_single_quote = """
|
|
135
|
+
5
|
|
136
|
+
Lattice="6.0 0.0 0.0 0.0 6.0 '0.0 0.0 0.0 6.0" Properties=species:S:1:pos:R:3
|
|
137
|
+
C 0.0 0.0 0.0
|
|
138
|
+
H 0.0 0.0 1.0
|
|
139
|
+
H 1.0 0.0 0.0
|
|
140
|
+
H 0.0 1.0 0.0
|
|
141
|
+
H 1.0 1.0 1.0
|
|
142
|
+
"""
|
|
143
|
+
|
|
144
|
+
incorrect_lattice_double_quote = """
|
|
145
|
+
5
|
|
146
|
+
Lattice="6.0 0.0 0.0 0.0 "6.0 0.0 0.0 0.0 6.0" Properties=species:S:1:pos:R:3
|
|
147
|
+
C 0.0 0.0 0.0
|
|
148
|
+
H 0.0 0.0 1.0
|
|
149
|
+
H 1.0 0.0 0.0
|
|
150
|
+
H 0.0 1.0 0.0
|
|
151
|
+
H 1.0 1.0 1.0
|
|
152
|
+
"""
|
|
153
|
+
|
|
154
|
+
incorrect_lattice_double_single_quote = """
|
|
155
|
+
5
|
|
156
|
+
Lattice="6.0 0.0 0.0 0.0 '6.0 0.0 0.0 '0.0 6.0" Properties=species:S:1:pos:R:3
|
|
157
|
+
C 0.0 0.0 0.0
|
|
158
|
+
H 0.0 0.0 1.0
|
|
159
|
+
H 1.0 0.0 0.0
|
|
160
|
+
H 0.0 1.0 0.0
|
|
161
|
+
H 1.0 1.0 1.0
|
|
162
|
+
"""
|
|
163
|
+
|
|
164
|
+
incorrect_lattice_double_double_quote = """
|
|
165
|
+
5
|
|
166
|
+
Lattice="6.0 0.0 "0.0 0.0 6.0 0.0 0.0 "0.0 6.0" Properties=species:S:1:pos:R:3
|
|
167
|
+
C 0.0 0.0 0.0
|
|
168
|
+
H 0.0 0.0 1.0
|
|
169
|
+
H 1.0 0.0 0.0
|
|
170
|
+
H 0.0 1.0 0.0
|
|
171
|
+
H 1.0 1.0 1.0
|
|
172
|
+
"""
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
expected_cell = (
|
|
176
|
+
(6.0, 0.0, 0.0),
|
|
177
|
+
(0.0, 6.0, 0.0),
|
|
178
|
+
(0.0, 0.0, 6.0),
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
expected_atoms = [
|
|
182
|
+
Atom(atomic_number=6, position=(0.0, 0.0, 0.0)), # C
|
|
183
|
+
Atom(atomic_number=1, position=(0.0, 0.0, 1.0)), # H
|
|
184
|
+
Atom(atomic_number=1, position=(1.0, 0.0, 0.0)), # H
|
|
185
|
+
Atom(atomic_number=1, position=(0.0, 1.0, 0.0)), # H
|
|
186
|
+
Atom(atomic_number=1, position=(1.0, 1.0, 1.0)), # H
|
|
187
|
+
]
|
|
188
|
+
|
|
189
|
+
expected_molecule = Molecule(
|
|
190
|
+
charge=0,
|
|
191
|
+
multiplicity=1,
|
|
192
|
+
atoms=expected_atoms,
|
|
193
|
+
cell=PeriodicCell(lattice_vectors=expected_cell),
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
def test_molecule_from_extxyz_valid() -> None:
|
|
198
|
+
"""
|
|
199
|
+
Test case for valid extxyz string.
|
|
200
|
+
"""
|
|
201
|
+
molecule = Molecule.from_extxyz(valid_extxyz)
|
|
202
|
+
assert molecule == expected_molecule, f"Valid case failed: got {molecule}, expected {expected_molecule}"
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
@pytest.mark.parametrize(
|
|
206
|
+
"invalid_extxyz",
|
|
207
|
+
[
|
|
208
|
+
incorrect_num_atoms,
|
|
209
|
+
no_num_atoms,
|
|
210
|
+
not_digit_num_atoms,
|
|
211
|
+
many_num_atoms,
|
|
212
|
+
xyz_style,
|
|
213
|
+
missing_lattice,
|
|
214
|
+
missing_properties,
|
|
215
|
+
incorrect_properites,
|
|
216
|
+
incorrect_lattice_extra,
|
|
217
|
+
incorrect_lattice_equals,
|
|
218
|
+
incorrect_lattice_str,
|
|
219
|
+
incorrect_lattice_extra_string,
|
|
220
|
+
incorrect_lattice_single_quote,
|
|
221
|
+
incorrect_lattice_double_quote,
|
|
222
|
+
incorrect_lattice_double_single_quote,
|
|
223
|
+
incorrect_lattice_double_double_quote,
|
|
224
|
+
],
|
|
225
|
+
)
|
|
226
|
+
def test_molecule_from_extxyz_invalid(invalid_extxyz: str) -> None:
|
|
227
|
+
"""
|
|
228
|
+
Test case for invalid extxyz strings, ensuring they raise MoleculeReadError.
|
|
229
|
+
"""
|
|
230
|
+
with pytest.raises(MoleculeReadError):
|
|
231
|
+
Molecule.from_extxyz(invalid_extxyz)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|