diff --git a/src/mp_api/routes/materials/models/__init__.py b/src/mp_api/routes/materials/models/__init__.py deleted file mode 100644 index dc25bd5e..00000000 --- a/src/mp_api/routes/materials/models/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -from mp_api.routes.materials.models.core import ( - Composition, - Lattice, - Specie, - SiteSpecie, - SiteElement, - Site, - PeriodicSite, - Structure, - Status, - CrystalSystem, -) diff --git a/src/mp_api/routes/materials/models/core.py b/src/mp_api/routes/materials/models/core.py deleted file mode 100644 index 60a4c9fb..00000000 --- a/src/mp_api/routes/materials/models/core.py +++ /dev/null @@ -1,121 +0,0 @@ -from typing import Dict, List, Optional, Union, Tuple -from pydantic import BaseModel, Field -from pymatgen.core.periodic_table import Element -from enum import Enum - -Vector3D = Tuple[float, float, float] - - -class Lattice(BaseModel): - """ - A lattice object represented as a 3x3 matrix of floats in Angstroms - """ - - a: float = Field(..., title="*a* lattice parameter") - alpha: int = Field(..., title="Angle between a and b lattice vectors") - b: float = Field(..., title="b lattice parameter") - beta: int = Field(..., title="Angle between a and c lattice vectors") - c: float = Field(..., title="c lattice parameter") - gamma: int = Field(..., title="Angle between b and c lattice vectors") - volume: float = Field(..., title="Lattice volume") - - matrix: Tuple[Vector3D, Vector3D, Vector3D] = Field( - ..., description="Matrix representation of this lattice" - ) - - -class Specie(BaseModel): - """ - An extension of Element with an oxidation state and other optional - properties. Properties associated with Specie should be "idealized" - values, not calculated values. For example, high-spin Fe2+ may be - assigned an idealized spin of +5, but an actual Fe2+ site may be - calculated to have a magmom of +4.5. Calculated properties should be - assigned to Site objects, and not Specie. - """ - - symbol: str = Field(..., title="Element Symbol") - oxidation_state: float = Field(..., title="Oxidation State") - properties: Optional[Dict] = Field(..., title="Species Properties") - - -Composition = Dict[Element, float] -Composition.__doc__ = """A dictionary mapping element to total quantity""" - - -class SiteSpecie(Specie): - """ - Adds site occupation to Species - """ - - occu: float = Field(..., title="Occupation") - - -class SiteElement(BaseModel): - """ - Elements defined on site with an occupation - """ - - element: Element = Field(..., title="Element") - occu: float = Field(..., title="Occupation") - - -class Site(BaseModel): - """ - A generalized *non-periodic* site. This is essentially a composition - at a point in space, with some optional properties associated with it. A - Composition is used to represent the atoms and occupancy, which allows for - disordered site representation. Coords are given in standard cartesian - coordinates. - """ - - species: List[Union[SiteElement, SiteSpecie]] = Field(..., title="Species") - xyz: Tuple[float, float, float] = Field(..., title="Cartesian Coordinates") - label: str = Field(..., title="Label") - properties: Optional[Dict] = Field(None, title="Properties") - - -class PeriodicSite(Site): - """ - A generalized *periodic* site. This adds on fractional coordinates within the - lattice to the generalized Site model - """ - - abc: Tuple[float, float, float] = Field(..., title="Fractional Coordinates") - - -class Structure(BaseModel): - """ - Basic Structure object with periodicity. Essentially a sequence - of Sites having a common lattice and a total charge. - """ - - charge: Optional[float] = Field(None, title="Total charge") - lattice: Lattice = Field(..., title="Lattice for this structure") - sites: List[PeriodicSite] = Field(..., title="List of sites in this structure") - - class Config: - extra = "allow" - - -class Status(Enum): - """ - """ - - exp = "Experimental" - theo = "Theoretical" - deprecated = "Deprecated" - - -class CrystalSystem(Enum): - """ - The crystal system of the lattice - """ - - tri = "triclinic" - mono = "monoclinic" - ortho = "orthorhombic" - tet = "tetragonal" - trig = "trigonal" - hex = "hexagonal" - cubic = "cubic" diff --git a/src/mp_api/routes/materials/models/doc.py b/src/mp_api/routes/materials/models/doc.py deleted file mode 100644 index 93c8474c..00000000 --- a/src/mp_api/routes/materials/models/doc.py +++ /dev/null @@ -1,177 +0,0 @@ -from typing import List -from monty.json import MontyDecoder -from pydantic import BaseModel, Field, validator -from pymatgen.core.periodic_table import Element -from datetime import datetime -from mp_api.routes.materials.models import CrystalSystem -from pymatgen.core.structure import Structure -from mp_api.routes.materials.models import Composition - - -class SymmetryData(BaseModel): - """ - Defines a symmetry data set for materials documents - """ - - crystal_system: CrystalSystem = Field( - None, title="Crystal System", description="The crystal system for this lattice" - ) - - symbol: str = Field( - None, - title="Space Group Symbol", - description="The spacegroup symbol for the lattice", - ) - - number: int = Field( - None, - title="Space Group Number", - description="The spacegroup number for the lattice", - ) - - point_group: str = Field( - None, title="Point Group Symbol", description="The point group for the lattice" - ) - - symprec: float = Field( - None, - title="Symmetry Finding Precision", - description="The precision given to spglib to determine the symmetry of this lattice", - ) - - version: str = Field(None, title="SPGLib version") - - -class MaterialsCoreDoc(BaseModel): - """ - Basic information about a material such as its crystal structure and associated calculations. - """ - - structure: Structure = Field( - None, description="The lowest energy structure for this material" - ) - - initial_structures: List[Structure] = Field( - None, - description="Initial structures used in the DFT optimizations corresponding to this material", - ) - - task_id: str = Field( - None, - description="The ID of this material, used as a universal reference across property documents." - "This comes in the form: mp-******", - ) - - last_updated: datetime = Field( - None, - description="Timestamp for the most recent calculation for this Material document", - ) - - created_at: datetime = Field( - None, - description="Timestamp for the first calculation for this Material document", - ) - - # Structure metadata - nsites: int = Field(None, description="Total number of sites in the structure") - elements: List[Element] = Field( - None, description="List of elements in the material" - ) - nelements: int = Field(None, title="Number of Elements") - composition: Composition = Field( - None, description="Full composition for the material" - ) - composition_reduced: Composition = Field( - None, - title="Reduced Composition", - description="Simplified representation of the composition", - ) - formula_pretty: str = Field( - None, - title="Pretty Formula", - description="Cleaned representation of the formula", - ) - formula_anonymous: str = Field( - None, - title="Anonymous Formula", - description="Anonymized representation of the formula", - ) - chemsys: str = Field( - None, - title="Chemical System", - description="dash-delimited string of elements in the material", - ) - volume: float = Field( - None, - title="Volume", - description="Total volume for this structure in Angstroms^3" - # TODO Should be normalize to the formula unit? - ) - - density: float = Field( - None, title="Density", description="Density in grams per cm^3" - ) - - density_atomic: float = Field( - None, - title="Packing Density", - description="The atomic packing density in atoms per cm^3", - ) - - symmetry: SymmetryData = Field(None, description="Symmetry data for this material") - - deprecated: bool = Field( - None, description="Whether the material is tagged as deprecated" - ) - - task_ids: List[str] = Field( - None, description="List of IDs for calculations associated with this material" - ) - - origins: List[dict] = Field( - None, description="List of IDs used to populate data for the material" - ) - - task_types: dict = Field( - None, description="Description of calculation type for each ID in task_ids" - ) - - # Make sure that the datetime field is properly formatted - @validator("last_updated", pre=True) - def last_updated_dict_ok(cls, v): - return MontyDecoder().process_decoded(v) - - -class MaterialProperty(BaseModel): - """ - Class defining metadata that can be applied to a property of any material - This metadata is used for search - """ - - # elements list for periodic table lookup - elements: List[Element] = Field( - None, description="List of elements in the material" - ) - # Used to lookup formula components - composition_reduced: Composition = Field( - None, - title="Reduced Composition", - description="Simplified representation of the composition", - ) - - # Used to look up any anonymous formula - formula_anonymous: str = Field( - None, - title="Anonymous Formula", - description="Anonymized representation of the formula", - ) - - formula_pretty: str = Field( - None, title="Pretty Formula", description="Human readable chemical formula" - ) - - material_id: str = Field( - None, - title="Material ID", - description="The ID for the material this property document corresponds to", - ) diff --git a/src/mp_api/routes/materials/query_operators.py b/src/mp_api/routes/materials/query_operators.py index 9da8a703..b326b459 100644 --- a/src/mp_api/routes/materials/query_operators.py +++ b/src/mp_api/routes/materials/query_operators.py @@ -2,7 +2,7 @@ from fastapi import Query from mp_api.core.query_operator import STORE_PARAMS, QueryOperator from mp_api.routes.materials.utils import formula_to_criteria -from mp_api.routes.materials.models.core import CrystalSystem +from emmet.core.symmetry import CrystalSystem from pymatgen.core.periodic_table import Element from collections import defaultdict diff --git a/src/mp_api/routes/materials/resources.py b/src/mp_api/routes/materials/resources.py index e47ac6ec..0382011a 100644 --- a/src/mp_api/routes/materials/resources.py +++ b/src/mp_api/routes/materials/resources.py @@ -1,6 +1,5 @@ from fastapi import HTTPException from mp_api.core.resource import GetResource -from mp_api.routes.materials.models.core import Structure from emmet.core.material import MaterialsDoc @@ -21,7 +20,7 @@ ) from pymatgen.analysis.structure_matcher import StructureMatcher, ElementComparator -from pymatgen.core import Structure as PS +from pymatgen.core import Structure from pymatgen.core import Composition from pymongo import MongoClient # type: ignore from itertools import permutations @@ -101,7 +100,7 @@ async def find_structure( """ try: - s = PS.from_dict(structure.dict()) + s = Structure.from_dict(structure.dict()) except Exception: raise HTTPException( status_code=404, @@ -128,7 +127,7 @@ async def find_structure( criteria=crit, properties=["structure", "task_id"] ): - s2 = PS.from_dict(r["structure"]) + s2 = Structure.from_dict(r["structure"]) matched = m.fit(s, s2) if matched: diff --git a/src/mp_api/routes/phonon/models.py b/src/mp_api/routes/phonon/models.py index 9d3d57b1..3d8ffb49 100644 --- a/src/mp_api/routes/phonon/models.py +++ b/src/mp_api/routes/phonon/models.py @@ -3,8 +3,7 @@ from monty.json import MontyDecoder from pydantic import BaseModel, Field, validator - -from mp_api.routes.materials.models.core import Structure +from pymatgen.core import Structure from pymatgen.phonon.bandstructure import PhononBandStructureSymmLine diff --git a/src/mp_api/routes/search/models.py b/src/mp_api/routes/search/models.py index 8f01321a..bdccb8be 100644 --- a/src/mp_api/routes/search/models.py +++ b/src/mp_api/routes/search/models.py @@ -1,18 +1,16 @@ -from typing import List, Optional, Dict, Union -from pymatgen.core.periodic_table import Element -from pymatgen.core.structure import Structure -from pymatgen.analysis.magnetism.analyzer import Ordering +from typing import Dict, List, Optional, Union -from emmet.core.mpid import MPID from emmet.core.electronic_structure import BandstructureData, DosData -from emmet.core.thermo import DecompositionProduct +from emmet.core.mpid import MPID from emmet.core.symmetry import SymmetryData - -from mp_api.routes.materials.models.doc import Composition -from mp_api.routes.xas.models import Edge, XASType +from emmet.core.thermo import DecompositionProduct +from emmet.core.xas import Edge, Type from mp_api.routes.grain_boundary.models import GBTypeEnum - from pydantic import BaseModel, Field +from pymatgen.analysis.magnetism.analyzer import Ordering +from pymatgen.core.composition import Composition +from pymatgen.core.periodic_table import Element +from pymatgen.core.structure import Structure class SearchStats(BaseModel): @@ -68,7 +66,7 @@ class XASSearchData(BaseModel): ) absorbing_element: Element = Field(None, title="Absorbing Element") - spectrum_type: XASType = Field(None, title="Type of XAS Spectrum") + spectrum_type: Type = Field(None, title="Type of XAS Spectrum") class GBSearchData(BaseModel): diff --git a/src/mp_api/routes/search/resources.py b/src/mp_api/routes/search/resources.py index 882575bf..97bf7a0d 100644 --- a/src/mp_api/routes/search/resources.py +++ b/src/mp_api/routes/search/resources.py @@ -1,32 +1,32 @@ from typing import Optional -from typing_extensions import Literal import numpy as np +from emmet.core.search import SearchDoc from fastapi import Query -from scipy.stats import gaussian_kde - from mp_api.core.query_operator import PaginationQuery, SortQuery, SparseFieldsQuery from mp_api.core.resource import GetResource +from mp_api.routes.electronic_structure.query_operators import ESSummaryDataQuery from mp_api.routes.materials.query_operators import ( + DeprecationQuery, ElementsQuery, FormulaQuery, MinMaxQuery, SymmetryQuery, - DeprecationQuery, ) -from mp_api.routes.search.models import SearchDoc, SearchStats +from mp_api.routes.search.models import SearchStats from mp_api.routes.search.query_operators import ( - MaterialIDsSearchQuery, HasPropsQuery, - SearchIsStableQuery, - SearchElasticityQuery, - SearchMagneticQuery, + MaterialIDsSearchQuery, SearchDielectricPiezoQuery, + SearchElasticityQuery, + SearchIsStableQuery, SearchIsTheoreticalQuery, + SearchMagneticQuery, ) from mp_api.routes.surface_properties.query_operators import SurfaceMinMaxQuery -from mp_api.routes.electronic_structure.query_operators import ESSummaryDataQuery from mp_api.routes.thermo.query_operators import ThermoEnergyQuery +from scipy.stats import gaussian_kde +from typing_extensions import Literal def search_resource(search_store): diff --git a/src/mp_api/routes/tasks/models.py b/src/mp_api/routes/tasks/models.py index 7819d6e1..8a4c8dc4 100644 --- a/src/mp_api/routes/tasks/models.py +++ b/src/mp_api/routes/tasks/models.py @@ -6,7 +6,7 @@ from pydantic import BaseModel, Field, validator from pymatgen.core.structure import Structure -from mp_api.routes.materials.models import Composition +from pymatgen.core.composition import Composition from pymatgen.core.periodic_table import Element from pymatgen.io.vasp import Incar, Poscar, Kpoints, Potcar from pymatgen.core.trajectory import Trajectory diff --git a/src/mp_api/routes/xas/client.py b/src/mp_api/routes/xas/client.py index 3d85372b..fdd3f28f 100644 --- a/src/mp_api/routes/xas/client.py +++ b/src/mp_api/routes/xas/client.py @@ -1,7 +1,7 @@ from typing import List, Optional from pymatgen.core.periodic_table import Element from mp_api.core.client import BaseRester, MPRestError -from mp_api.routes.xas.models import Edge, XASType, XASDoc +from emmet.core.xas import Edge, Type, XASDoc class XASRester(BaseRester): @@ -14,7 +14,7 @@ def get_available_elements( # TODO implement actual check self, edge: Optional[Edge] = None, - spectrum_type: Optional[XASType] = None, + spectrum_type: Optional[Type] = None, absorbing_element: Optional[Element] = None, required_elements: Optional[List[Element]] = None, ): diff --git a/src/mp_api/routes/xas/models.py b/src/mp_api/routes/xas/models.py deleted file mode 100644 index 01adaf37..00000000 --- a/src/mp_api/routes/xas/models.py +++ /dev/null @@ -1,90 +0,0 @@ -from enum import Enum -from typing import List, Optional -from datetime import datetime - -from monty.json import MontyDecoder -from pydantic import BaseModel, Field, validator - -from pymatgen.core.periodic_table import Element -from pymatgen.core.structure import Structure - -from mp_api.routes.materials.models.doc import MaterialProperty - - -class Edge(Enum): - """ - The interaction edge for XAS - There are 2n-1 sub-components to each edge where - K: n=1 - L: n=2 - M: n=3 - N: n=4 - """ - - K = "K" - L2 = "L2" - L3 = "L3" - L2_3 = "L2,3" - - -class XASType(Enum): - """ - Type of XAS Spectrum - """ - - XANES = "XANES" - EXAFS = "EXAFS" - XAFS = "XAFS" - - -class XASSpectrum(BaseModel): - """ - Spectrum Data - """ - - x: List[float] = Field(None, title="X-ray energy") - y: List[float] = Field(None, title="Absorption (Arbitrary Units)") - structure: Optional[Structure] = Field(None, title="Structure") - absorbing_element: Optional[Element] = Field(None, title="Absoring Element") - edge: Edge = Field( - None, title="Absorption Edge", description="The interaction edge for XAS" - ) - - -class XASDoc(MaterialProperty): - """ - X-ray absorption spectra, absorption edge, absorbing element, ... - """ - - spectrum: Optional[XASSpectrum] = None - - edge: Edge = Field( - None, title="Absorption Edge", description="The interaction edge for XAS" - ) - absorbing_element: Element = Field(None, title="Absorbing Element") - - spectrum_type: XASType = Field(None, title="Type of XAS Spectrum") - - xas_id: str = Field( - None, title="XAS Document ID", description="The unique ID for this XAS document" - ) - - task_id: str = Field( - None, title="The material id for the material this document corresponds to" - ) - - xas_ids: List[str] = Field( - None, - title="Calculation IDs", - description="List of Calculations IDS used to make this XAS spectrum", - ) - - last_updated: datetime = Field( - None, - description="timestamp for the most recent calculation for this XAS spectrum", - ) - - # Make sure that the datetime field is properly formatted - @validator("last_updated", pre=True) - def last_updated_dict_ok(cls, v): - return MontyDecoder().process_decoded(v) diff --git a/src/mp_api/routes/xas/query_operator.py b/src/mp_api/routes/xas/query_operator.py index 8d77c6fc..66ac0499 100644 --- a/src/mp_api/routes/xas/query_operator.py +++ b/src/mp_api/routes/xas/query_operator.py @@ -1,6 +1,6 @@ from fastapi import Query from mp_api.core.query_operator import STORE_PARAMS, QueryOperator -from mp_api.routes.xas.models import Edge, XASType +from emmet.core.xas import Edge, Type from pymatgen.core.periodic_table import Element from typing import Optional @@ -9,7 +9,7 @@ class XASQuery(QueryOperator): def query( self, edge: Edge = Query(None, title="XAS Edge"), - spectrum_type: XASType = Query(None, title="Spectrum Type"), + spectrum_type: Type = Query(None, title="Spectrum Type"), absorbing_element: Element = Query(None, title="Absorbing Element"), ) -> STORE_PARAMS: """ diff --git a/src/mp_api/routes/xas/resources.py b/src/mp_api/routes/xas/resources.py index 02510ee5..8665406c 100644 --- a/src/mp_api/routes/xas/resources.py +++ b/src/mp_api/routes/xas/resources.py @@ -1,5 +1,5 @@ from mp_api.core.resource import GetResource -from mp_api.routes.xas.models import XASDoc +from emmet.core.xas import XASDoc from mp_api.core.query_operator import PaginationQuery, SortQuery, SparseFieldsQuery from mp_api.routes.materials.query_operators import ElementsQuery, FormulaQuery