from collections.abc import Generator, Iterable
from typing import Any
from ase.atoms import Atoms
from structuretoolkit.common.pymatgen import pymatgen_to_ase
[docs]
def search(
chemsys: str | list[str], fields: Iterable[str] = (), api_key=None, **kwargs
) -> Generator[dict[str, Any], None, None]:
"""
Search the database for all structures matching the given query.
Note that `chemsys` takes distinct values for unaries, binaries and so! A query with `chemsys=["Fe", "O"]` will
return iron and oxygen structures but not iron oxide. Similarly `chemsys=["Fe-O"]` will
not return unary structures.
All keyword arguments for filtering from the original API are supported. See the
`original docs <https://docs.materialsproject.org/downloading-data/using-the-api>`_ for them.
Search for all iron structures:
>>> irons = structuretoolkit.build.materialsproject.search("Fe")
>>> len(list(irons))
10
Search for all structures with Al, Li that are on the T=0 convex hull:
>>> alli = structuretoolkit.build.materialsproject.search(['Al', 'Li', 'Al-Li'], is_stable=True)
>>> len(list(alli))
6
Usage is only possible with an API key obtained from the Materials Project. To do this, create an account with
them, login and access `this webpage <https://next-gen.materialsproject.org/api#api-key>`.
Once you have a key, either pass it as the `api_key` parameter or export an
environment variable, called `MP_API_KEY`, in your shell setup.
Args:
chemsys (str, list of str): confine search to given elements; either an element symbol or multiple element
symbols separated by dashes; if a list of strings is given return structures matching either of them
fields (iterable of str): pass as `fields` to :meth:`mp_api.MPRester.summary.search` to request additional
database entries beyond the structure
api_key (str, optional): if your API key is not exported in the environment flag MP_API_KEY, pass it here
**kwargs: passed verbatim to :meth:`mp_api.MPRester.summary.search` to further filter the results
Returns:
list of dict: one dictionary for each search results with at least keys
'material_id': database key of the hit
'structure': ASE atoms object
plus any requested via `fields`.
"""
from mp_api.client import MPRester
rest_kwargs = {
"use_document_model": False, # returns results as dictionaries
"include_user_agent": True, # send some additional software version info to MP
}
if api_key is not None:
rest_kwargs["api_key"] = api_key
with MPRester(**rest_kwargs) as mpr:
results = mpr.summary.search(
chemsys=chemsys,
**kwargs,
fields=list(fields) + ["structure", "material_id"],
)
for r in results:
if "structure" in r:
r["structure"] = pymatgen_to_ase(r["structure"])
yield r
[docs]
def by_id(
material_id: str | int,
final: bool = True,
conventional_unit_cell: bool = False,
api_key=None,
) -> Atoms | list[Atoms]:
"""
Retrieve a structure by material id.
This is how you would ask for the iron ground state:
>>> structuretoolkit.build.materialsproject.by_id('mp-13')
Fe: [0. 0. 0.]
tags:
spin: [(0: 2.214)]
pbc: [ True True True]
cell:
Cell([[2.318956, 0.000185, -0.819712], [-1.159251, 2.008215, -0.819524], [2.5e-05, 0.000273, 2.459206]])
Usage is only possible with an API key obtained from the Materials Project. To do this, create an account with
them, login and access `this webpage <https://next-gen.materialsproject.org/api#api-key>`.
Once you have a key, either pass it as the `api_key` parameter or export an
environment variable, called `MP_API_KEY`, in your shell setup.
Args:
material_id (str): the id assigned to a structure by the materials project
api_key (str, optional): if your API key is not exported in the environment flag MP_API_KEY, pass it here
final (bool, optional): if set to False, returns the list of initial structures,
else returns the final structure. (Default is True)
conventional_unit_cell (bool, optional): if set to True, returns the standard conventional unit cell.
(Default is False)
Returns:
:class:`~.Atoms`: requested final structure if final is True
list of :class:~.Atoms`: a list of initial (pre-relaxation) structures if final is False
Raises:
ValueError: material id does not exist
"""
from mp_api.client import MPRester
rest_kwargs = {
"include_user_agent": True, # send some additional software version info to MP
}
if api_key is not None:
rest_kwargs["api_key"] = api_key
with MPRester(**rest_kwargs) as mpr:
if final:
return pymatgen_to_ase(
mpr.get_structure_by_material_id(
material_id=material_id,
final=final,
conventional_unit_cell=conventional_unit_cell,
)
)
else:
return [
pymatgen_to_ase(mpr_structure)
for mpr_structure in (
mpr.get_structure_by_material_id(
material_id=material_id,
final=final,
conventional_unit_cell=conventional_unit_cell,
)
)
]