pymdkit 1.2.10__tar.gz → 1.2.11__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 (35) hide show
  1. {pymdkit-1.2.10/src/pymdkit.egg-info → pymdkit-1.2.11}/PKG-INFO +1 -1
  2. {pymdkit-1.2.10 → pymdkit-1.2.11}/pyproject.toml +1 -1
  3. {pymdkit-1.2.10 → pymdkit-1.2.11}/src/pymdkit/__init__.py +1 -1
  4. {pymdkit-1.2.10 → pymdkit-1.2.11}/src/pymdkit/commands/stable_entry.py +35 -63
  5. {pymdkit-1.2.10 → pymdkit-1.2.11/src/pymdkit.egg-info}/PKG-INFO +1 -1
  6. {pymdkit-1.2.10 → pymdkit-1.2.11}/LICENSE +0 -0
  7. {pymdkit-1.2.10 → pymdkit-1.2.11}/README.md +0 -0
  8. {pymdkit-1.2.10 → pymdkit-1.2.11}/setup.cfg +0 -0
  9. {pymdkit-1.2.10 → pymdkit-1.2.11}/src/pymdkit/commands/__init__.py +0 -0
  10. {pymdkit-1.2.10 → pymdkit-1.2.11}/src/pymdkit/commands/_fileio.py +0 -0
  11. {pymdkit-1.2.10 → pymdkit-1.2.11}/src/pymdkit/commands/_vasp_output.py +0 -0
  12. {pymdkit-1.2.10 → pymdkit-1.2.11}/src/pymdkit/commands/_vaspset.py +0 -0
  13. {pymdkit-1.2.10 → pymdkit-1.2.11}/src/pymdkit/commands/add_groups.py +0 -0
  14. {pymdkit-1.2.10 → pymdkit-1.2.11}/src/pymdkit/commands/compute_ehull.py +0 -0
  15. {pymdkit-1.2.10 → pymdkit-1.2.11}/src/pymdkit/commands/compute_msd_all_groups.py +0 -0
  16. {pymdkit-1.2.10 → pymdkit-1.2.11}/src/pymdkit/commands/compute_rmsd.py +0 -0
  17. {pymdkit-1.2.10 → pymdkit-1.2.11}/src/pymdkit/commands/electrostatic_energy.py +0 -0
  18. {pymdkit-1.2.10 → pymdkit-1.2.11}/src/pymdkit/commands/final_energy.py +0 -0
  19. {pymdkit-1.2.10 → pymdkit-1.2.11}/src/pymdkit/commands/gather_contcar.py +0 -0
  20. {pymdkit-1.2.10 → pymdkit-1.2.11}/src/pymdkit/commands/nep_rmse.py +0 -0
  21. {pymdkit-1.2.10 → pymdkit-1.2.11}/src/pymdkit/commands/perturb.py +0 -0
  22. {pymdkit-1.2.10 → pymdkit-1.2.11}/src/pymdkit/commands/stru2xyz.py +0 -0
  23. {pymdkit-1.2.10 → pymdkit-1.2.11}/src/pymdkit/commands/submit_vasp.py +0 -0
  24. {pymdkit-1.2.10 → pymdkit-1.2.11}/src/pymdkit/commands/substitute.py +0 -0
  25. {pymdkit-1.2.10 → pymdkit-1.2.11}/src/pymdkit/commands/supercell.py +0 -0
  26. {pymdkit-1.2.10 → pymdkit-1.2.11}/src/pymdkit/commands/symmetrize.py +0 -0
  27. {pymdkit-1.2.10 → pymdkit-1.2.11}/src/pymdkit/commands/vasp2xyz.py +0 -0
  28. {pymdkit-1.2.10 → pymdkit-1.2.11}/src/pymdkit/commands/vasp_relax.py +0 -0
  29. {pymdkit-1.2.10 → pymdkit-1.2.11}/src/pymdkit/commands/vasp_static.py +0 -0
  30. {pymdkit-1.2.10 → pymdkit-1.2.11}/src/pymdkit/pymdkit_main.py +0 -0
  31. {pymdkit-1.2.10 → pymdkit-1.2.11}/src/pymdkit.egg-info/SOURCES.txt +0 -0
  32. {pymdkit-1.2.10 → pymdkit-1.2.11}/src/pymdkit.egg-info/dependency_links.txt +0 -0
  33. {pymdkit-1.2.10 → pymdkit-1.2.11}/src/pymdkit.egg-info/entry_points.txt +0 -0
  34. {pymdkit-1.2.10 → pymdkit-1.2.11}/src/pymdkit.egg-info/requires.txt +0 -0
  35. {pymdkit-1.2.10 → pymdkit-1.2.11}/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.10
3
+ Version: 1.2.11
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
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "pymdkit"
7
- version = "1.2.10"
7
+ version = "1.2.11"
8
8
  description = "A unified command-line toolkit for atomistic / MD structure workflows."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -1,3 +1,3 @@
1
1
  """pymdkit -- a unified CLI for atomistic / MD structure workflows."""
2
2
 
3
- __version__ = "1.2.10"
3
+ __version__ = "1.2.11"
@@ -3,10 +3,7 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import argparse
6
- import json
7
6
  import re
8
- from urllib.parse import quote
9
- from urllib.request import Request, urlopen
10
7
  from pathlib import Path
11
8
 
12
9
  COMMAND = "stable-entry"
@@ -152,69 +149,44 @@ def fetch_stable_entries(elements, api_key=None):
152
149
  return list(by_mpid.values())
153
150
 
154
151
 
155
- def api_key_value(api_key=None):
156
- if api_key:
157
- return api_key
158
- try:
159
- from pymatgen.ext.matproj import MPRester
160
- return getattr(MPRester(), "api_key", None)
161
- except Exception:
162
- return None
152
+ def get_api_structure(material_id, api_key=None):
153
+ """Return the MP API structure for a public material_id."""
154
+ from mp_api.client import MPRester as MPApiRester
163
155
 
156
+ with MPApiRester(api_key) as mpr:
157
+ if hasattr(mpr, "get_structure_by_material_id"):
158
+ try:
159
+ return mpr.get_structure_by_material_id(
160
+ material_id,
161
+ conventional_unit_cell=True,
162
+ )
163
+ except TypeError:
164
+ return mpr.get_structure_by_material_id(material_id)
165
+
166
+ docs = mpr.materials.summary.search(
167
+ material_ids=[material_id],
168
+ fields=["material_id", "structure"],
169
+ )
170
+ if not docs:
171
+ raise RuntimeError(f"no MP summary structure found for {material_id}")
172
+ return doc_get(docs[0], "structure")
173
+
174
+
175
+ def write_mp_symmetrized_cif(material_id, fallback_structure, path, api_key=None):
176
+ """Write an MP API structure as a symmetrized CIF."""
177
+ from pymatgen.io.cif import CifWriter
164
178
 
165
- def extract_cif_text(text):
166
- stripped = text.lstrip()
167
- if not stripped.startswith(("{", "[")):
168
- if "_symmetry_space_group_name_H-M" in text or stripped.startswith(("data_", "#")):
169
- return text
170
179
  try:
171
- payload = json.loads(text)
172
- except json.JSONDecodeError:
173
- return None
174
- candidates = []
175
- if isinstance(payload, dict):
176
- candidates.extend(payload.get("response", []) or [])
177
- candidates.extend(payload.get("data", []) or [])
178
- candidates.append(payload)
179
- for item in candidates:
180
- if isinstance(item, dict):
181
- cif = item.get("cif") or item.get("cif_symmetrized") or item.get("symmetrized_cif")
182
- if cif:
183
- return cif
184
- return None
185
-
186
-
187
- def download_mp_symmetrized_cif(material_id, path, api_key=None):
188
- """Download the Materials Project CIF (Symmetrized) file for material_id."""
189
- key = api_key_value(api_key)
190
- headers = {"Accept": "text/plain", "User-Agent": "pymdkit"}
191
- if key:
192
- headers["X-API-KEY"] = key
193
- quoted = quote(material_id, safe="")
194
- urls = [
195
- f"https://api.materialsproject.org/materials/{quoted}/cif?symmetrized=true",
196
- f"https://api.materialsproject.org/materials/{quoted}/cif",
197
- f"https://api.materialsproject.org/materials/core/{quoted}/cif?symmetrized=true",
198
- f"https://api.materialsproject.org/materials/core/{quoted}/cif",
199
- f"https://materialsproject.org/materials/{quoted}/cif?download=true&symmetrized=true",
200
- f"https://materialsproject.org/materials/{quoted}/cif?symmetrized=true",
201
- f"https://www.materialsproject.org/rest/v2/materials/{quoted}/cif",
202
- ]
203
- errors = []
204
- for url in urls:
205
- try:
206
- req = Request(url, headers=headers)
207
- with urlopen(req, timeout=60) as response:
208
- text = response.read().decode("utf-8")
209
- cif_text = extract_cif_text(text)
210
- if cif_text:
211
- Path(path).write_text(cif_text, encoding="utf-8")
212
- return
213
- errors.append(f"{url}: response did not contain CIF text")
214
- except Exception as exc: # noqa: BLE001 - try alternate MP endpoints
215
- errors.append(f"{url}: {type(exc).__name__}: {exc}")
216
- raise RuntimeError("Could not download MP CIF (Symmetrized): " + " | ".join(errors))
180
+ structure = get_api_structure(material_id, api_key)
181
+ except Exception as exc: # noqa: BLE001 - keep command useful if MP API changes
182
+ structure = fallback_structure
183
+ print(f" ! {material_id}: MP API structure fetch failed ({type(exc).__name__}); "
184
+ "using thermo structure fallback.")
217
185
 
186
+ try:
187
+ CifWriter(structure, symprec=0.1, refine_struct=True).write_file(str(path))
188
+ except TypeError:
189
+ CifWriter(structure, symprec=0.1).write_file(str(path))
218
190
 
219
191
  def run(args) -> int:
220
192
 
@@ -239,7 +211,7 @@ def run(args) -> int:
239
211
  mpid = safe_formula(entry_id_text(entry).split(" ")[0])
240
212
  formula = safe_formula(entry.composition.reduced_formula)
241
213
  path = out_dir / f"{mpid}-{formula}.cif"
242
- download_mp_symmetrized_cif(mpid, path, args.mp_api_key)
214
+ write_mp_symmetrized_cif(mpid, entry.structure, path, args.mp_api_key)
243
215
  print(f"{mpid}\t{entry.composition.reduced_formula}\t-> {path}")
244
216
  written += 1
245
217
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pymdkit
3
- Version: 1.2.10
3
+ Version: 1.2.11
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
File without changes
File without changes
File without changes