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.
- {pymdkit-1.2.10/src/pymdkit.egg-info → pymdkit-1.2.11}/PKG-INFO +1 -1
- {pymdkit-1.2.10 → pymdkit-1.2.11}/pyproject.toml +1 -1
- {pymdkit-1.2.10 → pymdkit-1.2.11}/src/pymdkit/__init__.py +1 -1
- {pymdkit-1.2.10 → pymdkit-1.2.11}/src/pymdkit/commands/stable_entry.py +35 -63
- {pymdkit-1.2.10 → pymdkit-1.2.11/src/pymdkit.egg-info}/PKG-INFO +1 -1
- {pymdkit-1.2.10 → pymdkit-1.2.11}/LICENSE +0 -0
- {pymdkit-1.2.10 → pymdkit-1.2.11}/README.md +0 -0
- {pymdkit-1.2.10 → pymdkit-1.2.11}/setup.cfg +0 -0
- {pymdkit-1.2.10 → pymdkit-1.2.11}/src/pymdkit/commands/__init__.py +0 -0
- {pymdkit-1.2.10 → pymdkit-1.2.11}/src/pymdkit/commands/_fileio.py +0 -0
- {pymdkit-1.2.10 → pymdkit-1.2.11}/src/pymdkit/commands/_vasp_output.py +0 -0
- {pymdkit-1.2.10 → pymdkit-1.2.11}/src/pymdkit/commands/_vaspset.py +0 -0
- {pymdkit-1.2.10 → pymdkit-1.2.11}/src/pymdkit/commands/add_groups.py +0 -0
- {pymdkit-1.2.10 → pymdkit-1.2.11}/src/pymdkit/commands/compute_ehull.py +0 -0
- {pymdkit-1.2.10 → pymdkit-1.2.11}/src/pymdkit/commands/compute_msd_all_groups.py +0 -0
- {pymdkit-1.2.10 → pymdkit-1.2.11}/src/pymdkit/commands/compute_rmsd.py +0 -0
- {pymdkit-1.2.10 → pymdkit-1.2.11}/src/pymdkit/commands/electrostatic_energy.py +0 -0
- {pymdkit-1.2.10 → pymdkit-1.2.11}/src/pymdkit/commands/final_energy.py +0 -0
- {pymdkit-1.2.10 → pymdkit-1.2.11}/src/pymdkit/commands/gather_contcar.py +0 -0
- {pymdkit-1.2.10 → pymdkit-1.2.11}/src/pymdkit/commands/nep_rmse.py +0 -0
- {pymdkit-1.2.10 → pymdkit-1.2.11}/src/pymdkit/commands/perturb.py +0 -0
- {pymdkit-1.2.10 → pymdkit-1.2.11}/src/pymdkit/commands/stru2xyz.py +0 -0
- {pymdkit-1.2.10 → pymdkit-1.2.11}/src/pymdkit/commands/submit_vasp.py +0 -0
- {pymdkit-1.2.10 → pymdkit-1.2.11}/src/pymdkit/commands/substitute.py +0 -0
- {pymdkit-1.2.10 → pymdkit-1.2.11}/src/pymdkit/commands/supercell.py +0 -0
- {pymdkit-1.2.10 → pymdkit-1.2.11}/src/pymdkit/commands/symmetrize.py +0 -0
- {pymdkit-1.2.10 → pymdkit-1.2.11}/src/pymdkit/commands/vasp2xyz.py +0 -0
- {pymdkit-1.2.10 → pymdkit-1.2.11}/src/pymdkit/commands/vasp_relax.py +0 -0
- {pymdkit-1.2.10 → pymdkit-1.2.11}/src/pymdkit/commands/vasp_static.py +0 -0
- {pymdkit-1.2.10 → pymdkit-1.2.11}/src/pymdkit/pymdkit_main.py +0 -0
- {pymdkit-1.2.10 → pymdkit-1.2.11}/src/pymdkit.egg-info/SOURCES.txt +0 -0
- {pymdkit-1.2.10 → pymdkit-1.2.11}/src/pymdkit.egg-info/dependency_links.txt +0 -0
- {pymdkit-1.2.10 → pymdkit-1.2.11}/src/pymdkit.egg-info/entry_points.txt +0 -0
- {pymdkit-1.2.10 → pymdkit-1.2.11}/src/pymdkit.egg-info/requires.txt +0 -0
- {pymdkit-1.2.10 → pymdkit-1.2.11}/src/pymdkit.egg-info/top_level.txt +0 -0
|
@@ -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
|
|
156
|
-
|
|
157
|
-
|
|
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
|
-
|
|
172
|
-
except
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
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
|
-
|
|
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
|
|
|
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
|