stjames 0.0.42__py3-none-any.whl → 0.0.43__py3-none-any.whl

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/atom.py CHANGED
@@ -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)
stjames/molecule.py CHANGED
@@ -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 Exception as e:
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)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: stjames
3
- Version: 0.0.42
3
+ Version: 0.0.43
4
4
  Summary: standardized JSON atom/molecule encoding scheme
5
5
  Author-email: Corin Wagen <corin@rowansci.com>
6
6
  Project-URL: Homepage, https://github.com/rowansci/stjames
@@ -1,6 +1,6 @@
1
1
  stjames/__init__.py,sha256=LkWCylP4VeXyQL0iu5w6yeYK1UHjcUH55hwWXTy4mQQ,576
2
2
  stjames/_deprecated_solvent_settings.py,sha256=gj5j9p3zakIwSTK5_ndqBXJx--IzjZNxZ75z-wipLOo,450
3
- stjames/atom.py,sha256=2NZ-tyWk6uPrn_rsANFFultNHS0CvgYYXwj8rud991M,2056
3
+ stjames/atom.py,sha256=w7q-x9xpBw4sJ1WGrWt65WAaStxhz-m7dugXCYEOpq4,2064
4
4
  stjames/base.py,sha256=9PvUjBeVSkmA3TaruaB0uvjFMbWYTGKXECISNGAj_AU,1201
5
5
  stjames/basis_set.py,sha256=wI3M2q9uPf9jhKpAi4E2DrsyKzloDGLRjAlk7krdYgc,949
6
6
  stjames/calculation.py,sha256=O2LwwQ_cOLmDOGXTHA9J71YbUZXigUSbvbLA-fSVm3w,915
@@ -12,7 +12,7 @@ stjames/int_settings.py,sha256=5HXp8opt5ZyY1UpmfaK7NVloWVLM5jkG0elEEqpVLUo,896
12
12
  stjames/message.py,sha256=Rq6QqmHZKecWxYH8fVyXmuoCCPZv8YinvgykSeorXSU,216
13
13
  stjames/method.py,sha256=xnfphxyiWZotxQcmgvpFMJDmGEM2B-_5cbPkgYZBIws,1245
14
14
  stjames/mode.py,sha256=xw46Cc7f3eTS8i35qECi-8DocAlANhayK3w4akD4HBU,496
15
- stjames/molecule.py,sha256=XJdfEJndl4DqY_mg5scWH9xWQU8gNcXN74Qb4n2TN1c,6798
15
+ stjames/molecule.py,sha256=ZyqerT0p0CIykdn0vWfvy2UbU4LsVPCUQ7mSUeILkUI,10524
16
16
  stjames/opt_settings.py,sha256=gxXGtjy9l-Q5Wen9eO6T6HHRCuS8rfOofdVQIJj0JcI,550
17
17
  stjames/periodic_cell.py,sha256=JDCyynpamggTNi_HnTnnotRbeSMBfYc-srhD-IwUnrg,996
18
18
  stjames/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -45,8 +45,8 @@ stjames/workflows/scan.py,sha256=hL4Hco3Ns0dntjh2G2HhhWmED1mbt0gA_hsglPQ5Vjg,814
45
45
  stjames/workflows/spin_states.py,sha256=hzGbYfG4KGYYQPV4cF0ufCndDMoIVnZt2ZZt7LqvJgc,4854
46
46
  stjames/workflows/tautomer.py,sha256=kZSCHo2Q7LzqtQjF_WyyxjECkndG49T9QOM12hsUkx8,421
47
47
  stjames/workflows/workflow.py,sha256=t5Yz-d5WgSQEiHbiZfc4NQ653mEnydiGZ-lEkkPYAKw,994
48
- stjames-0.0.42.dist-info/LICENSE,sha256=i7ehYBS-6gGmbTcgU4mgk28pyOx2kScJ0kcx8n7bWLM,1084
49
- stjames-0.0.42.dist-info/METADATA,sha256=mIKojGiwySNE8F0-7hulBNJv2WFORfn08rwCUghPbWM,1628
50
- stjames-0.0.42.dist-info/WHEEL,sha256=cVxcB9AmuTcXqmwrtPhNK88dr7IR_b6qagTj0UvIEbY,91
51
- stjames-0.0.42.dist-info/top_level.txt,sha256=FYCwxl6quhYOAgG-mnPQcCK8vsVM7B8rIUrO-WrQ_PI,8
52
- stjames-0.0.42.dist-info/RECORD,,
48
+ stjames-0.0.43.dist-info/LICENSE,sha256=i7ehYBS-6gGmbTcgU4mgk28pyOx2kScJ0kcx8n7bWLM,1084
49
+ stjames-0.0.43.dist-info/METADATA,sha256=9gZNt8YmerGV47ExAhb0Cie2toEDtPt2SkhgeWf7Yjc,1628
50
+ stjames-0.0.43.dist-info/WHEEL,sha256=cVxcB9AmuTcXqmwrtPhNK88dr7IR_b6qagTj0UvIEbY,91
51
+ stjames-0.0.43.dist-info/top_level.txt,sha256=FYCwxl6quhYOAgG-mnPQcCK8vsVM7B8rIUrO-WrQ_PI,8
52
+ stjames-0.0.43.dist-info/RECORD,,