pymdkit 1.2.1__tar.gz → 1.2.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.
Files changed (36) hide show
  1. {pymdkit-1.2.1/src/pymdkit.egg-info → pymdkit-1.2.3}/PKG-INFO +3 -2
  2. {pymdkit-1.2.1 → pymdkit-1.2.3}/README.md +1 -1
  3. {pymdkit-1.2.1 → pymdkit-1.2.3}/pyproject.toml +3 -2
  4. {pymdkit-1.2.1 → pymdkit-1.2.3}/src/pymdkit/__init__.py +1 -1
  5. pymdkit-1.2.3/src/pymdkit/commands/stable_entry.py +116 -0
  6. {pymdkit-1.2.1 → pymdkit-1.2.3/src/pymdkit.egg-info}/PKG-INFO +3 -2
  7. {pymdkit-1.2.1 → pymdkit-1.2.3}/src/pymdkit.egg-info/requires.txt +1 -0
  8. pymdkit-1.2.1/src/pymdkit/commands/stable_entry.py +0 -77
  9. {pymdkit-1.2.1 → pymdkit-1.2.3}/LICENSE +0 -0
  10. {pymdkit-1.2.1 → pymdkit-1.2.3}/setup.cfg +0 -0
  11. {pymdkit-1.2.1 → pymdkit-1.2.3}/src/pymdkit/commands/__init__.py +0 -0
  12. {pymdkit-1.2.1 → pymdkit-1.2.3}/src/pymdkit/commands/_fileio.py +0 -0
  13. {pymdkit-1.2.1 → pymdkit-1.2.3}/src/pymdkit/commands/_vasp_output.py +0 -0
  14. {pymdkit-1.2.1 → pymdkit-1.2.3}/src/pymdkit/commands/_vaspset.py +0 -0
  15. {pymdkit-1.2.1 → pymdkit-1.2.3}/src/pymdkit/commands/add_groups.py +0 -0
  16. {pymdkit-1.2.1 → pymdkit-1.2.3}/src/pymdkit/commands/compute_ehull.py +0 -0
  17. {pymdkit-1.2.1 → pymdkit-1.2.3}/src/pymdkit/commands/compute_msd_all_groups.py +0 -0
  18. {pymdkit-1.2.1 → pymdkit-1.2.3}/src/pymdkit/commands/compute_rmsd.py +0 -0
  19. {pymdkit-1.2.1 → pymdkit-1.2.3}/src/pymdkit/commands/electrostatic_energy.py +0 -0
  20. {pymdkit-1.2.1 → pymdkit-1.2.3}/src/pymdkit/commands/final_energy.py +0 -0
  21. {pymdkit-1.2.1 → pymdkit-1.2.3}/src/pymdkit/commands/gather_contcar.py +0 -0
  22. {pymdkit-1.2.1 → pymdkit-1.2.3}/src/pymdkit/commands/nep_rmse.py +0 -0
  23. {pymdkit-1.2.1 → pymdkit-1.2.3}/src/pymdkit/commands/perturb.py +0 -0
  24. {pymdkit-1.2.1 → pymdkit-1.2.3}/src/pymdkit/commands/stru2xyz.py +0 -0
  25. {pymdkit-1.2.1 → pymdkit-1.2.3}/src/pymdkit/commands/submit_vasp.py +0 -0
  26. {pymdkit-1.2.1 → pymdkit-1.2.3}/src/pymdkit/commands/substitute.py +0 -0
  27. {pymdkit-1.2.1 → pymdkit-1.2.3}/src/pymdkit/commands/supercell.py +0 -0
  28. {pymdkit-1.2.1 → pymdkit-1.2.3}/src/pymdkit/commands/symmetrize.py +0 -0
  29. {pymdkit-1.2.1 → pymdkit-1.2.3}/src/pymdkit/commands/vasp2xyz.py +0 -0
  30. {pymdkit-1.2.1 → pymdkit-1.2.3}/src/pymdkit/commands/vasp_relax.py +0 -0
  31. {pymdkit-1.2.1 → pymdkit-1.2.3}/src/pymdkit/commands/vasp_static.py +0 -0
  32. {pymdkit-1.2.1 → pymdkit-1.2.3}/src/pymdkit/pymdkit_main.py +0 -0
  33. {pymdkit-1.2.1 → pymdkit-1.2.3}/src/pymdkit.egg-info/SOURCES.txt +0 -0
  34. {pymdkit-1.2.1 → pymdkit-1.2.3}/src/pymdkit.egg-info/dependency_links.txt +0 -0
  35. {pymdkit-1.2.1 → pymdkit-1.2.3}/src/pymdkit.egg-info/entry_points.txt +0 -0
  36. {pymdkit-1.2.1 → pymdkit-1.2.3}/src/pymdkit.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pymdkit
3
- Version: 1.2.1
3
+ Version: 1.2.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
@@ -16,6 +16,7 @@ License-File: LICENSE
16
16
  Requires-Dist: numpy
17
17
  Requires-Dist: ase
18
18
  Requires-Dist: pymatgen
19
+ Requires-Dist: mp-api
19
20
  Requires-Dist: pyxtal
20
21
  Requires-Dist: dpdata
21
22
  Dynamic: license-file
@@ -41,7 +42,7 @@ pip install pymdkit
41
42
  ```
42
43
 
43
44
  This installs the `pymdkit` command into the active conda environment, together
44
- with its direct dependencies (numpy, ase, pymatgen, pyxtal, dpdata). Some of these packages may install their own transitive dependencies.
45
+ with its direct dependencies (numpy, ase, pymatgen, mp-api, pyxtal, dpdata). Some of these packages may install their own transitive dependencies.
45
46
 
46
47
  Verify:
47
48
 
@@ -19,7 +19,7 @@ pip install pymdkit
19
19
  ```
20
20
 
21
21
  This installs the `pymdkit` command into the active conda environment, together
22
- with its direct dependencies (numpy, ase, pymatgen, pyxtal, dpdata). Some of these packages may install their own transitive dependencies.
22
+ with its direct dependencies (numpy, ase, pymatgen, mp-api, pyxtal, dpdata). Some of these packages may install their own transitive dependencies.
23
23
 
24
24
  Verify:
25
25
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "pymdkit"
7
- version = "1.2.1"
7
+ version = "1.2.3"
8
8
  description = "A unified command-line toolkit for atomistic / MD structure workflows."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -26,7 +26,8 @@ classifiers = [
26
26
  dependencies = [
27
27
  "numpy",
28
28
  "ase",
29
- "pymatgen",
29
+ "pymatgen",
30
+ "mp-api",
30
31
  "pyxtal",
31
32
  "dpdata",
32
33
  ]
@@ -1,3 +1,3 @@
1
1
  """pymdkit -- a unified CLI for atomistic / MD structure workflows."""
2
2
 
3
- __version__ = "1.2.1"
3
+ __version__ = "1.2.3"
@@ -0,0 +1,116 @@
1
+ """Download stable Materials Project structures for a chemical system."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import argparse
6
+ import re
7
+ from itertools import combinations
8
+ from dataclasses import dataclass
9
+ from pathlib import Path
10
+
11
+ COMMAND = "stable-entry"
12
+ HELP = "Download stable Materials Project structures for a chemical system."
13
+
14
+
15
+ @dataclass
16
+ class StableStructure:
17
+ material_id: str
18
+ formula: str
19
+ structure: object
20
+
21
+
22
+ def safe_formula(formula):
23
+ return re.sub(r"[^A-Za-z0-9_.-]+", "", str(formula))
24
+
25
+
26
+ def doc_get(doc, name, default=None):
27
+ if isinstance(doc, dict):
28
+ return doc.get(name, default)
29
+ return getattr(doc, name, default)
30
+
31
+
32
+ def normalize_doc(doc):
33
+ material_id = str(doc_get(doc, "material_id", "unknown"))
34
+ formula = doc_get(doc, "formula_pretty") or doc_get(doc, "formula")
35
+ structure = doc_get(doc, "structure")
36
+ if formula is None and structure is not None:
37
+ formula = structure.composition.reduced_formula
38
+ if structure is None:
39
+ raise ValueError(f"MP document {material_id} has no structure field")
40
+ return StableStructure(material_id=material_id, formula=str(formula), structure=structure)
41
+
42
+
43
+ def entry_sort_key(entry):
44
+ return (len(entry.structure.composition.elements), entry.formula, entry.material_id)
45
+
46
+
47
+ def add_arguments(parser: argparse.ArgumentParser) -> None:
48
+ parser.add_argument("-s", nargs="+", required=True,
49
+ help="Chemical system elements, e.g. -s Li La Ta Cl.")
50
+ parser.add_argument("-mp-api-key", default=None,
51
+ help="Materials Project API key.")
52
+
53
+
54
+ def subsystem_labels(elements):
55
+ """Return all subsystem labels needed to build the full chemsys hull."""
56
+ labels = []
57
+ for size in range(1, len(elements) + 1):
58
+ for subset in combinations(elements, size):
59
+ labels.append("-".join(subset))
60
+ return labels
61
+
62
+
63
+ def fetch_stable_structures(elements, api_key=None):
64
+ from mp_api.client import MPRester
65
+
66
+ fields = ["material_id", "formula_pretty", "structure"]
67
+ by_mpid = {}
68
+ with MPRester(api_key) as mpr:
69
+ for chemsys in subsystem_labels(elements):
70
+ docs = mpr.materials.summary.search(
71
+ chemsys=chemsys,
72
+ is_stable=True,
73
+ fields=fields,
74
+ )
75
+ for doc in docs:
76
+ entry = normalize_doc(doc)
77
+ by_mpid[entry.material_id] = entry
78
+ return list(by_mpid.values())
79
+
80
+
81
+ def run(args) -> int:
82
+ from pymatgen.io.cif import CifWriter
83
+
84
+ elements = list(dict.fromkeys(args.s))
85
+ label = "-".join(elements)
86
+ out_dir = Path(f"{label}-stable-entries")
87
+ out_dir.mkdir(parents=True, exist_ok=True)
88
+
89
+ try:
90
+ entries = fetch_stable_structures(elements, args.mp_api_key)
91
+ except ModuleNotFoundError as exc:
92
+ if exc.name == "mp_api":
93
+ raise SystemExit(
94
+ "Error: stable-entry requires mp-api. Reinstall pymdkit 1.2.3+ "
95
+ "or run `pip install mp-api`."
96
+ ) from exc
97
+ raise
98
+
99
+ entries = sorted(entries, key=entry_sort_key)
100
+ written = 0
101
+ for entry in entries:
102
+ mpid = safe_formula(entry.material_id)
103
+ formula = safe_formula(entry.formula)
104
+ path = out_dir / f"{mpid}-{formula}.cif"
105
+ CifWriter(entry.structure).write_file(str(path))
106
+ print(f"{mpid}\t{entry.formula}\t-> {path}")
107
+ written += 1
108
+
109
+ print(f"Wrote {written} stable entr{'y' if written == 1 else 'ies'} to {out_dir}")
110
+ return 0 if written else 1
111
+
112
+
113
+ if __name__ == "__main__":
114
+ _parser = argparse.ArgumentParser(description=__doc__)
115
+ add_arguments(_parser)
116
+ raise SystemExit(run(_parser.parse_args()))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pymdkit
3
- Version: 1.2.1
3
+ Version: 1.2.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
@@ -16,6 +16,7 @@ License-File: LICENSE
16
16
  Requires-Dist: numpy
17
17
  Requires-Dist: ase
18
18
  Requires-Dist: pymatgen
19
+ Requires-Dist: mp-api
19
20
  Requires-Dist: pyxtal
20
21
  Requires-Dist: dpdata
21
22
  Dynamic: license-file
@@ -41,7 +42,7 @@ pip install pymdkit
41
42
  ```
42
43
 
43
44
  This installs the `pymdkit` command into the active conda environment, together
44
- with its direct dependencies (numpy, ase, pymatgen, pyxtal, dpdata). Some of these packages may install their own transitive dependencies.
45
+ with its direct dependencies (numpy, ase, pymatgen, mp-api, pyxtal, dpdata). Some of these packages may install their own transitive dependencies.
45
46
 
46
47
  Verify:
47
48
 
@@ -1,5 +1,6 @@
1
1
  numpy
2
2
  ase
3
3
  pymatgen
4
+ mp-api
4
5
  pyxtal
5
6
  dpdata
@@ -1,77 +0,0 @@
1
- """Download stable Materials Project entries for a chemical system."""
2
-
3
- from __future__ import annotations
4
-
5
- import argparse
6
- import re
7
- from pathlib import Path
8
-
9
- COMMAND = "stable-entry"
10
- HELP = "Download stable Materials Project structures for a chemical system."
11
-
12
-
13
- def safe_formula(formula):
14
- return re.sub(r"[^A-Za-z0-9_.-]+", "", str(formula))
15
-
16
-
17
- def entry_id_text(entry):
18
- entry_id = getattr(entry, "entry_id", "")
19
- if isinstance(entry_id, dict):
20
- for key in ("material_id", "task_id", "entry_id", "id"):
21
- if entry_id.get(key):
22
- return str(entry_id[key])
23
- return "-".join(f"{k}-{v}" for k, v in sorted(entry_id.items()))
24
- if entry_id:
25
- return str(entry_id)
26
- data = getattr(entry, "data", {}) or {}
27
- for key in ("material_id", "task_id", "entry_id", "id"):
28
- if data.get(key):
29
- return str(data[key])
30
- return "unknown"
31
-
32
-
33
- def entry_sort_key(entry):
34
- formula = str(entry.composition.reduced_formula)
35
- return (len(entry.composition.elements), formula, entry_id_text(entry))
36
-
37
-
38
- def add_arguments(parser: argparse.ArgumentParser) -> None:
39
- parser.add_argument("-s", nargs="+", required=True,
40
- help="Chemical system elements, e.g. -s Li La Ta Cl.")
41
- parser.add_argument("-mp-api-key", default=None,
42
- help="Materials Project API key.")
43
-
44
-
45
- def run(args) -> int:
46
- from pymatgen.ext.matproj import MPRester
47
- from pymatgen.io.cif import CifWriter
48
-
49
- elements = list(dict.fromkeys(args.s))
50
- label = "-".join(elements)
51
- out_dir = Path(f"{label}-stable-entries")
52
- out_dir.mkdir(parents=True, exist_ok=True)
53
-
54
- with MPRester(args.mp_api_key) as mpr:
55
- entries = mpr.get_entries_in_chemsys(
56
- elements, inc_structure=True,
57
- additional_criteria={"thermo_types": ["GGA_GGA+U"], "is_stable": True},
58
- )
59
-
60
- entries = sorted(entries, key=entry_sort_key)
61
- written = 0
62
- for entry in entries:
63
- mpid = safe_formula(entry_id_text(entry).split(" ")[0])
64
- formula = safe_formula(entry.composition.reduced_formula)
65
- path = out_dir / f"{mpid}-{formula}.cif"
66
- CifWriter(entry.structure).write_file(str(path))
67
- print(f"{mpid}\t{entry.composition.reduced_formula}\t-> {path}")
68
- written += 1
69
-
70
- print(f"Wrote {written} stable entr{'y' if written == 1 else 'ies'} to {out_dir}")
71
- return 0 if written else 1
72
-
73
-
74
- if __name__ == "__main__":
75
- _parser = argparse.ArgumentParser(description=__doc__)
76
- add_arguments(_parser)
77
- raise SystemExit(run(_parser.parse_args()))
File without changes
File without changes