pymdkit 1.6.2__tar.gz → 1.6.3__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.
- {pymdkit-1.6.2 → pymdkit-1.6.3}/PKG-INFO +9 -3
- {pymdkit-1.6.2 → pymdkit-1.6.3}/README.md +8 -2
- {pymdkit-1.6.2 → pymdkit-1.6.3}/pyproject.toml +1 -1
- {pymdkit-1.6.2 → pymdkit-1.6.3}/src/pymdkit/__init__.py +1 -1
- {pymdkit-1.6.2 → pymdkit-1.6.3}/src/pymdkit/commands/_cifio.py +19 -0
- {pymdkit-1.6.2 → pymdkit-1.6.3}/src/pymdkit/commands/_symmetry.py +1 -3
- {pymdkit-1.6.2 → pymdkit-1.6.3}/src/pymdkit/commands/_vaspset.py +3 -5
- {pymdkit-1.6.2 → pymdkit-1.6.3}/src/pymdkit/commands/compute_rmsd.py +3 -4
- {pymdkit-1.6.2 → pymdkit-1.6.3}/src/pymdkit/commands/convert.py +2 -5
- {pymdkit-1.6.2 → pymdkit-1.6.3}/src/pymdkit/commands/ewald.py +6 -3
- {pymdkit-1.6.2 → pymdkit-1.6.3}/src/pymdkit/commands/realloc_occ.py +1 -3
- {pymdkit-1.6.2 → pymdkit-1.6.3}/src/pymdkit/commands/substitute.py +1 -3
- {pymdkit-1.6.2 → pymdkit-1.6.3}/src/pymdkit.egg-info/PKG-INFO +9 -3
- {pymdkit-1.6.2 → pymdkit-1.6.3}/tests/test_lattice_symmetry.py +34 -0
- {pymdkit-1.6.2 → pymdkit-1.6.3}/LICENSE +0 -0
- {pymdkit-1.6.2 → pymdkit-1.6.3}/setup.cfg +0 -0
- {pymdkit-1.6.2 → pymdkit-1.6.3}/src/pymdkit/commands/__init__.py +0 -0
- {pymdkit-1.6.2 → pymdkit-1.6.3}/src/pymdkit/commands/_extxyz.py +0 -0
- {pymdkit-1.6.2 → pymdkit-1.6.3}/src/pymdkit/commands/_fileio.py +0 -0
- {pymdkit-1.6.2 → pymdkit-1.6.3}/src/pymdkit/commands/_geometry.py +0 -0
- {pymdkit-1.6.2 → pymdkit-1.6.3}/src/pymdkit/commands/_gpumd.py +0 -0
- {pymdkit-1.6.2 → pymdkit-1.6.3}/src/pymdkit/commands/_lattice.py +0 -0
- {pymdkit-1.6.2 → pymdkit-1.6.3}/src/pymdkit/commands/_oxidation.py +0 -0
- {pymdkit-1.6.2 → pymdkit-1.6.3}/src/pymdkit/commands/_precision.py +0 -0
- {pymdkit-1.6.2 → pymdkit-1.6.3}/src/pymdkit/commands/_reduction.py +0 -0
- {pymdkit-1.6.2 → pymdkit-1.6.3}/src/pymdkit/commands/_supercell.py +0 -0
- {pymdkit-1.6.2 → pymdkit-1.6.3}/src/pymdkit/commands/_vasp_output.py +0 -0
- {pymdkit-1.6.2 → pymdkit-1.6.3}/src/pymdkit/commands/add_config_type.py +0 -0
- {pymdkit-1.6.2 → pymdkit-1.6.3}/src/pymdkit/commands/chemsys_entry.py +0 -0
- {pymdkit-1.6.2 → pymdkit-1.6.3}/src/pymdkit/commands/compute_ehull.py +0 -0
- {pymdkit-1.6.2 → pymdkit-1.6.3}/src/pymdkit/commands/gather_fs.py +0 -0
- {pymdkit-1.6.2 → pymdkit-1.6.3}/src/pymdkit/commands/gpumd_group.py +0 -0
- {pymdkit-1.6.2 → pymdkit-1.6.3}/src/pymdkit/commands/gpumd_msd.py +0 -0
- {pymdkit-1.6.2 → pymdkit-1.6.3}/src/pymdkit/commands/gpumd_relax.py +0 -0
- {pymdkit-1.6.2 → pymdkit-1.6.3}/src/pymdkit/commands/gpumd_thermo.py +0 -0
- {pymdkit-1.6.2 → pymdkit-1.6.3}/src/pymdkit/commands/gpumd_trjcat.py +0 -0
- {pymdkit-1.6.2 → pymdkit-1.6.3}/src/pymdkit/commands/nep_rmse.py +0 -0
- {pymdkit-1.6.2 → pymdkit-1.6.3}/src/pymdkit/commands/pca.py +0 -0
- {pymdkit-1.6.2 → pymdkit-1.6.3}/src/pymdkit/commands/perturb.py +0 -0
- {pymdkit-1.6.2 → pymdkit-1.6.3}/src/pymdkit/commands/submit_vasp.py +0 -0
- {pymdkit-1.6.2 → pymdkit-1.6.3}/src/pymdkit/commands/supercell.py +0 -0
- {pymdkit-1.6.2 → pymdkit-1.6.3}/src/pymdkit/commands/trj_extract.py +0 -0
- {pymdkit-1.6.2 → pymdkit-1.6.3}/src/pymdkit/commands/trj_sparse.py +0 -0
- {pymdkit-1.6.2 → pymdkit-1.6.3}/src/pymdkit/commands/umap.py +0 -0
- {pymdkit-1.6.2 → pymdkit-1.6.3}/src/pymdkit/commands/vasp2xyz.py +0 -0
- {pymdkit-1.6.2 → pymdkit-1.6.3}/src/pymdkit/commands/vasp_fe.py +0 -0
- {pymdkit-1.6.2 → pymdkit-1.6.3}/src/pymdkit/commands/vasp_relax.py +0 -0
- {pymdkit-1.6.2 → pymdkit-1.6.3}/src/pymdkit/commands/vasp_static.py +0 -0
- {pymdkit-1.6.2 → pymdkit-1.6.3}/src/pymdkit/pymdkit_main.py +0 -0
- {pymdkit-1.6.2 → pymdkit-1.6.3}/src/pymdkit.egg-info/SOURCES.txt +0 -0
- {pymdkit-1.6.2 → pymdkit-1.6.3}/src/pymdkit.egg-info/dependency_links.txt +0 -0
- {pymdkit-1.6.2 → pymdkit-1.6.3}/src/pymdkit.egg-info/entry_points.txt +0 -0
- {pymdkit-1.6.2 → pymdkit-1.6.3}/src/pymdkit.egg-info/requires.txt +0 -0
- {pymdkit-1.6.2 → pymdkit-1.6.3}/src/pymdkit.egg-info/top_level.txt +0 -0
- {pymdkit-1.6.2 → pymdkit-1.6.3}/tests/test_convert.py +0 -0
- {pymdkit-1.6.2 → pymdkit-1.6.3}/tests/test_realloc_occ.py +0 -0
- {pymdkit-1.6.2 → pymdkit-1.6.3}/tests/test_vaspset.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pymdkit
|
|
3
|
-
Version: 1.6.
|
|
3
|
+
Version: 1.6.3
|
|
4
4
|
Summary: A unified command-line toolkit for atomistic / MD structure workflows.
|
|
5
5
|
Author-email: Yueda Wang <ydwang0608@ustc.edu.cn>
|
|
6
6
|
License-Expression: GPL-3.0-or-later
|
|
@@ -336,8 +336,14 @@ CIF input with pymatgen rather than ASE. ASE interprets
|
|
|
336
336
|
`_space_group_crystal_system` as a setting hint only for rhombohedral groups
|
|
337
337
|
and emits a potentially misleading warning for other crystal systems. Using
|
|
338
338
|
pymatgen avoids that ambiguity while PMK continues to use ASE for non-CIF
|
|
339
|
-
formats.
|
|
340
|
-
|
|
339
|
+
formats. Pymatgen intentionally snaps fractional coordinates within its
|
|
340
|
+
default `1e-4` tolerance to ideal values before applying symmetry. PMK keeps
|
|
341
|
+
that corrective behavior but hides only its corresponding finite-precision
|
|
342
|
+
notice; composition, occupancy, malformed-CIF, and all other warnings remain
|
|
343
|
+
visible. See the
|
|
344
|
+
[pymatgen CifParser documentation](https://pymatgen.org/pymatgen.io.html#pymatgen.io.cif.CifParser).
|
|
345
|
+
A partially occupied CIF must first be ordered with `convert -d2o` before it
|
|
346
|
+
can be represented as an explicit atom list.
|
|
341
347
|
|
|
342
348
|
CIF `_atom_type_symbol` and `_atom_site_label` values use per-element
|
|
343
349
|
inequivalent-site identifiers such as `Li1`, `Y1`, `Cl1`, and `Cl2`.
|
|
@@ -309,8 +309,14 @@ CIF input with pymatgen rather than ASE. ASE interprets
|
|
|
309
309
|
`_space_group_crystal_system` as a setting hint only for rhombohedral groups
|
|
310
310
|
and emits a potentially misleading warning for other crystal systems. Using
|
|
311
311
|
pymatgen avoids that ambiguity while PMK continues to use ASE for non-CIF
|
|
312
|
-
formats.
|
|
313
|
-
|
|
312
|
+
formats. Pymatgen intentionally snaps fractional coordinates within its
|
|
313
|
+
default `1e-4` tolerance to ideal values before applying symmetry. PMK keeps
|
|
314
|
+
that corrective behavior but hides only its corresponding finite-precision
|
|
315
|
+
notice; composition, occupancy, malformed-CIF, and all other warnings remain
|
|
316
|
+
visible. See the
|
|
317
|
+
[pymatgen CifParser documentation](https://pymatgen.org/pymatgen.io.html#pymatgen.io.cif.CifParser).
|
|
318
|
+
A partially occupied CIF must first be ordered with `convert -d2o` before it
|
|
319
|
+
can be represented as an explicit atom list.
|
|
314
320
|
|
|
315
321
|
CIF `_atom_type_symbol` and `_atom_site_label` values use per-element
|
|
316
322
|
inequivalent-site identifiers such as `Li1`, `Y1`, `Cl1`, and `Cl2`.
|
|
@@ -41,12 +41,31 @@ CIF_FLOAT_TAGS = {
|
|
|
41
41
|
_CIF_DECIMAL_RE = re.compile(
|
|
42
42
|
r"[-+]?(?:(?:\d+\.\d*|\.\d+)(?:[eE][-+]?\d+)?|\d+[eE][-+]?\d+)"
|
|
43
43
|
)
|
|
44
|
+
_BENIGN_FRACTIONAL_ROUNDING_WARNING = (
|
|
45
|
+
r"Issues encountered while parsing CIF:\s*\d+ fractional coordinates? "
|
|
46
|
+
r"rounded to ideal values to avoid issues with finite precision\.\s*$"
|
|
47
|
+
)
|
|
44
48
|
|
|
45
49
|
|
|
46
50
|
def is_cif(path):
|
|
47
51
|
return Path(path).suffix.lower() == ".cif"
|
|
48
52
|
|
|
49
53
|
|
|
54
|
+
def read_structure(path):
|
|
55
|
+
"""Read with pymatgen, hiding only its benign CIF idealization notice."""
|
|
56
|
+
from pymatgen.core import Structure
|
|
57
|
+
|
|
58
|
+
if not is_cif(path):
|
|
59
|
+
return Structure.from_file(str(path))
|
|
60
|
+
with warnings.catch_warnings():
|
|
61
|
+
warnings.filterwarnings(
|
|
62
|
+
"ignore",
|
|
63
|
+
message=_BENIGN_FRACTIONAL_ROUNDING_WARNING,
|
|
64
|
+
category=UserWarning,
|
|
65
|
+
)
|
|
66
|
+
return Structure.from_file(str(path))
|
|
67
|
+
|
|
68
|
+
|
|
50
69
|
def as_pymatgen_structure(structure):
|
|
51
70
|
"""Return a periodic pymatgen Structure from pymatgen or ASE input."""
|
|
52
71
|
from pymatgen.core import Structure
|
|
@@ -36,11 +36,9 @@ DEFAULT_OXIDATION_STATES = {
|
|
|
36
36
|
|
|
37
37
|
|
|
38
38
|
def load_structure(path):
|
|
39
|
-
from pymatgen.core import Structure
|
|
40
|
-
|
|
41
39
|
path = Path(path)
|
|
42
40
|
try:
|
|
43
|
-
return
|
|
41
|
+
return _cifio.read_structure(path)
|
|
44
42
|
except Exception as pymatgen_error:
|
|
45
43
|
if _cifio.is_cif(path):
|
|
46
44
|
raise ValueError(
|
|
@@ -17,12 +17,12 @@ from __future__ import annotations
|
|
|
17
17
|
|
|
18
18
|
import argparse
|
|
19
19
|
import ast
|
|
20
|
-
import warnings
|
|
21
20
|
from pathlib import Path
|
|
22
21
|
|
|
23
22
|
try:
|
|
24
|
-
from . import _lattice, _precision, _supercell
|
|
23
|
+
from . import _cifio, _lattice, _precision, _supercell
|
|
25
24
|
except ImportError:
|
|
25
|
+
import _cifio
|
|
26
26
|
import _lattice
|
|
27
27
|
import _precision
|
|
28
28
|
import _supercell
|
|
@@ -216,8 +216,6 @@ def _run_trajectory(args, set_cls, settings):
|
|
|
216
216
|
def run_vasp_set(args, set_cls, default_settings):
|
|
217
217
|
"""Write *set_cls* input files for one structure (-i), a folder (-if), or a
|
|
218
218
|
trajectory (-it). Defaults can be overridden via ``-custom-setting FILE``."""
|
|
219
|
-
warnings.filterwarnings("ignore", category=UserWarning, module="pymatgen")
|
|
220
|
-
from pymatgen.core import Structure
|
|
221
219
|
|
|
222
220
|
settings = dict(default_settings)
|
|
223
221
|
if args.custom_setting:
|
|
@@ -244,7 +242,7 @@ def run_vasp_set(args, set_cls, default_settings):
|
|
|
244
242
|
written = 0
|
|
245
243
|
for struct_file, out_dir in jobs:
|
|
246
244
|
try:
|
|
247
|
-
structure =
|
|
245
|
+
structure = _cifio.read_structure(struct_file)
|
|
248
246
|
except Exception as e: # noqa: BLE001 - report and continue in batch
|
|
249
247
|
print(f"{struct_file}: cannot read ({e}) -> skipping")
|
|
250
248
|
continue
|
|
@@ -11,8 +11,9 @@ from itertools import combinations
|
|
|
11
11
|
from pathlib import Path
|
|
12
12
|
|
|
13
13
|
try:
|
|
14
|
-
from . import _fileio
|
|
14
|
+
from . import _cifio, _fileio
|
|
15
15
|
except ImportError:
|
|
16
|
+
import _cifio
|
|
16
17
|
import _fileio
|
|
17
18
|
|
|
18
19
|
COMMAND = "rmsd"
|
|
@@ -49,11 +50,9 @@ def create_matcher():
|
|
|
49
50
|
|
|
50
51
|
|
|
51
52
|
def load_structure(path):
|
|
52
|
-
from pymatgen.core import Structure
|
|
53
|
-
|
|
54
53
|
path = Path(path)
|
|
55
54
|
try:
|
|
56
|
-
return
|
|
55
|
+
return _cifio.read_structure(path)
|
|
57
56
|
except Exception as pymatgen_error:
|
|
58
57
|
if path.suffix.lower() == ".cif":
|
|
59
58
|
print(f" [warn] pymatgen could not read CIF {path}: {pymatgen_error}")
|
|
@@ -23,10 +23,9 @@ HELP = "Convert structures, refine CIF symmetry, or order disorder."
|
|
|
23
23
|
|
|
24
24
|
def _read_cif(path):
|
|
25
25
|
"""Read CIF with pymatgen, avoiding ASE's setting-name ambiguity."""
|
|
26
|
-
from pymatgen.core import Structure
|
|
27
26
|
from pymatgen.io.ase import AseAtomsAdaptor
|
|
28
27
|
|
|
29
|
-
structure =
|
|
28
|
+
structure = _cifio.read_structure(path)
|
|
30
29
|
if not structure.is_ordered:
|
|
31
30
|
raise ValueError(
|
|
32
31
|
"partially occupied CIF cannot be converted to an explicit atom "
|
|
@@ -149,9 +148,7 @@ def _write(
|
|
|
149
148
|
) from pmg_error
|
|
150
149
|
|
|
151
150
|
def _read_structure(path):
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
return Structure.from_file(str(path))
|
|
151
|
+
return _cifio.read_structure(path)
|
|
155
152
|
|
|
156
153
|
|
|
157
154
|
def _write_structure(
|
|
@@ -14,14 +14,17 @@ from __future__ import annotations
|
|
|
14
14
|
import argparse
|
|
15
15
|
from pathlib import Path
|
|
16
16
|
|
|
17
|
+
try:
|
|
18
|
+
from . import _cifio
|
|
19
|
+
except ImportError:
|
|
20
|
+
import _cifio
|
|
21
|
+
|
|
17
22
|
COMMAND = "ewald"
|
|
18
23
|
HELP = "Compute CIF electrostatic energy using pymatgen EwaldSummation."
|
|
19
24
|
|
|
20
25
|
|
|
21
26
|
def read_charged_structure(path):
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
structure = Structure.from_file(str(path))
|
|
27
|
+
structure = _cifio.read_structure(path)
|
|
25
28
|
missing = []
|
|
26
29
|
for site in structure:
|
|
27
30
|
for specie in site.species:
|
|
@@ -580,9 +580,7 @@ def _write_candidate(
|
|
|
580
580
|
temporary = output.with_name(f".{output.stem}.base.cif")
|
|
581
581
|
try:
|
|
582
582
|
render_candidate(parsed, occupancies, target, target_counts, z, temporary)
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
structure = Structure.from_file(temporary)
|
|
583
|
+
structure = _cifio.read_structure(temporary)
|
|
586
584
|
structure.make_supercell(list(matrix))
|
|
587
585
|
_cifio.write_cif(structure, output, data_name=output.stem, refine=False)
|
|
588
586
|
finally:
|
|
@@ -207,11 +207,9 @@ def read_cif_labels(path):
|
|
|
207
207
|
|
|
208
208
|
def read_structure(path):
|
|
209
209
|
"""Read any pymatgen-readable structure, falling back to ASE."""
|
|
210
|
-
from pymatgen.core import Structure
|
|
211
|
-
|
|
212
210
|
path = Path(path)
|
|
213
211
|
try:
|
|
214
|
-
return
|
|
212
|
+
return _cifio.read_structure(path)
|
|
215
213
|
except Exception as pymatgen_error:
|
|
216
214
|
if _cifio.is_cif(path):
|
|
217
215
|
raise ValueError(
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pymdkit
|
|
3
|
-
Version: 1.6.
|
|
3
|
+
Version: 1.6.3
|
|
4
4
|
Summary: A unified command-line toolkit for atomistic / MD structure workflows.
|
|
5
5
|
Author-email: Yueda Wang <ydwang0608@ustc.edu.cn>
|
|
6
6
|
License-Expression: GPL-3.0-or-later
|
|
@@ -336,8 +336,14 @@ CIF input with pymatgen rather than ASE. ASE interprets
|
|
|
336
336
|
`_space_group_crystal_system` as a setting hint only for rhombohedral groups
|
|
337
337
|
and emits a potentially misleading warning for other crystal systems. Using
|
|
338
338
|
pymatgen avoids that ambiguity while PMK continues to use ASE for non-CIF
|
|
339
|
-
formats.
|
|
340
|
-
|
|
339
|
+
formats. Pymatgen intentionally snaps fractional coordinates within its
|
|
340
|
+
default `1e-4` tolerance to ideal values before applying symmetry. PMK keeps
|
|
341
|
+
that corrective behavior but hides only its corresponding finite-precision
|
|
342
|
+
notice; composition, occupancy, malformed-CIF, and all other warnings remain
|
|
343
|
+
visible. See the
|
|
344
|
+
[pymatgen CifParser documentation](https://pymatgen.org/pymatgen.io.html#pymatgen.io.cif.CifParser).
|
|
345
|
+
A partially occupied CIF must first be ordered with `convert -d2o` before it
|
|
346
|
+
can be represented as an explicit atom list.
|
|
341
347
|
|
|
342
348
|
CIF `_atom_type_symbol` and `_atom_site_label` values use per-element
|
|
343
349
|
inequivalent-site identifiers such as `Li1`, `Y1`, `Cl1`, and `Cl2`.
|
|
@@ -2,6 +2,7 @@ import math
|
|
|
2
2
|
import sys
|
|
3
3
|
import types
|
|
4
4
|
import unittest
|
|
5
|
+
import warnings
|
|
5
6
|
from pathlib import Path
|
|
6
7
|
from unittest.mock import patch
|
|
7
8
|
|
|
@@ -38,6 +39,39 @@ class FakeLattice:
|
|
|
38
39
|
return math.degrees(math.acos(float(np.clip(cosine, -1.0, 1.0))))
|
|
39
40
|
|
|
40
41
|
|
|
42
|
+
class CifReaderTests(unittest.TestCase):
|
|
43
|
+
def test_only_benign_fractional_rounding_warning_is_hidden(self):
|
|
44
|
+
structure = object()
|
|
45
|
+
|
|
46
|
+
class Structure:
|
|
47
|
+
@classmethod
|
|
48
|
+
def from_file(cls, path):
|
|
49
|
+
warnings.warn(
|
|
50
|
+
"Issues encountered while parsing CIF: 4 fractional "
|
|
51
|
+
"coordinates rounded to ideal values to avoid issues "
|
|
52
|
+
"with finite precision.",
|
|
53
|
+
UserWarning,
|
|
54
|
+
)
|
|
55
|
+
warnings.warn("CIF composition mismatch", UserWarning)
|
|
56
|
+
return structure
|
|
57
|
+
|
|
58
|
+
pymatgen = types.ModuleType("pymatgen")
|
|
59
|
+
core = types.ModuleType("pymatgen.core")
|
|
60
|
+
core.Structure = Structure
|
|
61
|
+
pymatgen.core = core
|
|
62
|
+
with patch.dict(sys.modules, {
|
|
63
|
+
"pymatgen": pymatgen,
|
|
64
|
+
"pymatgen.core": core,
|
|
65
|
+
}), warnings.catch_warnings(record=True) as caught:
|
|
66
|
+
warnings.simplefilter("always")
|
|
67
|
+
result = _cifio.read_structure("input.cif")
|
|
68
|
+
|
|
69
|
+
self.assertIs(result, structure)
|
|
70
|
+
self.assertEqual([str(item.message) for item in caught], [
|
|
71
|
+
"CIF composition mismatch"
|
|
72
|
+
])
|
|
73
|
+
|
|
74
|
+
|
|
41
75
|
class LatticeGeometryTests(unittest.TestCase):
|
|
42
76
|
def test_gpumd_uses_pymatgen_lattice_row_vectors(self):
|
|
43
77
|
pymatgen = types.ModuleType("pymatgen")
|
|
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
|