Skip to content

Commit

Permalink
Update client to fully reconstruct pydantic models via use of native …
Browse files Browse the repository at this point in the history
…pymatgen objects (#223)

* Bump required monty version

* Change how pydantic objects are reconstructed in the client

* Add comment

* Start switch to using native pymatgen models

* Update tasks endpoint to use pymatgen models

* Pymatgen version import fix

* task_id list search added to tasks

* Insertion electrode model and query op updates

* Multiple task_id search added to molecules

* Deprecation query changed to list of task_ids

* Linting

* client: catch __version__ import for old pymatgen

* dependabot PRs

Bump boto3 from 1.17.22 to 1.17.32

Bumps [boto3](https://github.com/boto/boto3) from 1.17.22 to 1.17.32.
- [Release notes](https://github.com/boto/boto3/releases)
- [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst)
- [Commits](boto/boto3@1.17.22...1.17.32)

Signed-off-by: dependabot[bot] <support@github.com>

Bump flake8 from 3.8.4 to 3.9.0

Bumps [flake8](https://gitlab.com/pycqa/flake8) from 3.8.4 to 3.9.0.
- [Release notes](https://gitlab.com/pycqa/flake8/tags)
- [Commits](https://gitlab.com/pycqa/flake8/compare/3.8.4...3.9.0)

Signed-off-by: dependabot[bot] <support@github.com>

Bump pre-commit from 2.11.0 to 2.11.1

Bumps [pre-commit](https://github.com/pre-commit/pre-commit) from 2.11.0 to 2.11.1.
- [Release notes](https://github.com/pre-commit/pre-commit/releases)
- [Changelog](https://github.com/pre-commit/pre-commit/blob/master/CHANGELOG.md)
- [Commits](pre-commit/pre-commit@v2.11.0...v2.11.1)

Signed-off-by: dependabot[bot] <support@github.com>

Bump pycodestyle from 2.6.0 to 2.7.0

Bumps [pycodestyle](https://github.com/PyCQA/pycodestyle) from 2.6.0 to 2.7.0.
- [Release notes](https://github.com/PyCQA/pycodestyle/releases)
- [Changelog](https://github.com/PyCQA/pycodestyle/blob/master/CHANGES.txt)
- [Commits](https://github.com/PyCQA/pycodestyle/commits)

Signed-off-by: dependabot[bot] <support@github.com>

* Bump boto3 from 1.17.32 to 1.17.33

Bumps [boto3](https://github.com/boto/boto3) from 1.17.32 to 1.17.33.
- [Release notes](https://github.com/boto/boto3/releases)
- [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst)
- [Commits](boto/boto3@1.17.32...1.17.33)

Signed-off-by: dependabot[bot] <support@github.com>

* Wildcard added to chemsys search

* InsertionElectrode object added to model

* API pinned to temp monty fix

* Linting

* github testing updated from master to main

* Mypy fixes

* Ignore missing imports mypy

* Literal pulled from typing_extensions

* More linting

* added more fields to electrode doc (#229)

* added more fields to electrode doc

* added elements field

* linting

* update

* more useful fields

Co-authored-by: Jason Munro <jmunro@lbl.gov>
Co-authored-by: Patrick Huck <phuck@lbl.gov>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: JSX <jmmshn@gmail.com>
  • Loading branch information
5 people committed Mar 24, 2021
1 parent 5216ab0 commit a21a96f
Show file tree
Hide file tree
Showing 24 changed files with 252 additions and 207 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/testing.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ name: testing
on:
push:
branches:
- master
- main

pull_request:
branches:
- master
- main

jobs:
lint:
Expand Down
2 changes: 1 addition & 1 deletion requirements-server.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ maggma==0.26.0
uvicorn==0.13.4
gunicorn[gevent]>=20.0.1
aws-xray-sdk==2.6.0
boto3==1.17.22
boto3==1.17.33
6 changes: 3 additions & 3 deletions requirements-testing.txt
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
pre-commit==2.11.0
pre-commit==2.11.1
pytest==6.2.2
pytest-asyncio==0.14.0
pytest-cov==2.11.1
pytest-mock==3.5.1
pycodestyle==2.6.0
flake8==3.8.4
pycodestyle==2.7.0
flake8==3.9.0
mypy==0.812
mypy-extensions==0.4.3
2 changes: 2 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@ pymatgen>=2020.9.14,<2022
typing-extensions==3.7.4.3
maggma==0.26.0
requests==2.25.1
git+git://github.com/mkhorton/monty@patch-4#egg=monty
#monty>=2021.3.3
16 changes: 1 addition & 15 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,5 @@ max-line-length = 120
[pydocstyle]
ignore = D105,D2,D4

[mypy-pymatgen.*]
ignore_missing_imports = True


[mypy-pytest]
ignore_missing_imports = True


[mypy-uvicorn]
ignore_missing_imports = True

[mypy-monty.*]
ignore_missing_imports = True

[mypy-aws_xray_sdk.*]
[mypy]
ignore_missing_imports = True
6 changes: 3 additions & 3 deletions src/mp_api/charge_density/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,12 @@ def get_calculation_details(self, material_id: str):
"""

base_endpoint = "/".join(self.endpoint.split("/")[0:3])
task_rester = TaskRester(api_key=self.api_key, endpoint=base_endpoint)
task_rester = TaskRester(api_key=self.api_key, endpoint=base_endpoint) # type: ignore

result = task_rester.get_task_from_material_id(
result = task_rester.get_task_from_material_id( # type: ignore
material_id, fields=["task_id", "orig_inputs"]
).get("data")[0]

task_rester.session.close()
task_rester.session.close() # type: ignore

return result
2 changes: 1 addition & 1 deletion src/mp_api/core/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from datetime import datetime
from monty.json import MSONable
from mp_api.core.resource import Resource
from pymatgen import __version__ as pmg_version # type: ignore
from pymatgen.core import __version__ as pmg_version # type: ignore
from fastapi.openapi.utils import get_openapi


Expand Down
9 changes: 7 additions & 2 deletions src/mp_api/core/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,15 @@

import requests
from monty.json import MontyDecoder
from pymatgen import __version__ as pmg_version # type: ignore
from requests.exceptions import RequestException
from pydantic import BaseModel

try:
from pymatgen.core import __version__ as pmg_version # type: ignore
except ImportError:
# fallback to root-level import for older pymatgen versions
from pymatgen import __version__ as pmg_version # type: ignore

# TODO: think about how to migrate from PMG_MAPI_KEY
DEFAULT_API_KEY = environ.get("MP_API_KEY", None)
DEFAULT_ENDPOINT = environ.get("MP_API_ENDPOINT", "https://api.materialsproject.org/")
Expand Down Expand Up @@ -199,7 +204,7 @@ def _query_resource(
data = json.loads(response.text)

if self.document_model:
data["data"] = [self.document_model.construct(**d) for d in data["data"]] # type: ignore
data["data"] = [self.document_model.parse_obj(d) for d in data["data"]] # type: ignore

return data

Expand Down
73 changes: 59 additions & 14 deletions src/mp_api/electrodes/models.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
from monty.json import MontyDecoder
from pymatgen.core.periodic_table import Element
from typing import Dict, List
from pymatgen.core import Structure
from typing import Dict, List, Union
from datetime import datetime

from pydantic import BaseModel, Field, validator
from mp_api.materials.models import Composition

from pymatgen.apps.battery.insertion_battery import InsertionElectrode


class VoltageStep(BaseModel):
"""
Expand All @@ -21,13 +24,11 @@ class VoltageStep(BaseModel):
)

average_voltage: float = Field(
None,
description="The average voltage in V for a particular voltage step.",
None, description="The average voltage in V for a particular voltage step.",
)

min_voltage: float = Field(
None,
description="The min voltage in V for a particular voltage step.",
None, description="The min voltage in V for a particular voltage step.",
)

capacity_grav: float = Field(None, description="Gravimetric capacity in mAh/g.")
Expand Down Expand Up @@ -55,6 +56,14 @@ class InsertionVoltageStep(VoltageStep):
Features specific to insertion electrode
"""

formula_charge: str = Field(
None, description="The chemical formula of the charged material."
)

formula_discharge: str = Field(
None, description="The chemical formula of the discharged material."
)

stability_charge: float = Field(
None, description="The energy above hull of the charged material."
)
Expand All @@ -63,17 +72,29 @@ class InsertionVoltageStep(VoltageStep):
None, description="The energy above hull of the discharged material."
)

id_charge: Union[str] = Field(
None, description="The material-id of the charged structure."
)

id_discharge: Union[str] = Field(
None, description="The material-id of the discharged structure."
)


class InsertionElectrodeDoc(InsertionVoltageStep):

battery_id: str = Field(None, description="The id for this battery document.")

framework: Composition = Field(
framework_formula: str = Field(
None, description="The id for this battery document."
)

host_structure: Structure = Field(
None,
description="The composition of the host framework (structure without the working ion)",
description="Host structure (structure without the working ion)",
)

voltage_pairs: List[InsertionVoltageStep] = Field(
adj_pairs: List[InsertionVoltageStep] = Field(
None,
description="Returns all the Voltage Steps",
)
Expand All @@ -86,7 +107,7 @@ class InsertionElectrodeDoc(InsertionVoltageStep):
num_steps: float = Field(
None,
description="The number of distinct voltage steps in from fully charge to "
"discharge based on the stable intermediate states",
"discharge based on the stable intermediate states",
)

max_voltage_step: float = Field(
Expand All @@ -98,6 +119,32 @@ class InsertionElectrodeDoc(InsertionVoltageStep):
description="Timestamp for the most recent calculation for this Material document",
)

framework: Composition = Field(
None,
description="The chemical compositions of the host framework",
)

material_ids: List[str] = Field(
None,
description="The ids of all structures that matched to the present host lattice, regardless of stability. "
"The stable entries can be found in the adjacent pairs.",
)

elements: List[Element] = Field(
None,
description="The atomic species contained in this electrode.",
)

chemsys: str = Field(
None,
description="The chemical system this electrode belongs to. "
"Note: The conversion electrode can be calculated on this chemical system",
)

electrode_object: InsertionElectrode = Field(
None, description="Returns InsertionElectrode object",
)

# Make sure that the datetime field is properly formatted
@validator("last_updated", pre=True)
def last_updated_dict_ok(cls, v):
Expand All @@ -118,14 +165,12 @@ class ConversionElectrode(ConversionVoltageStep):

battery_id: str = Field(None, description="The id for this battery document.")

voltage_pairs: List[ConversionVoltageStep] = Field(
None,
description="Returns all the Voltage Steps",
electrode_object: InsertionElectrode = Field(
None, description="Returns InsertionElectrode object",
)

working_ion: str = Field(
None,
description="The working ion as an Element object",
None, description="The working ion as an Element object",
)

num_steps: float = Field(
Expand Down
12 changes: 4 additions & 8 deletions src/mp_api/electrodes/query_operators.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,20 +46,16 @@ def query(
description="Minimum value for the minimum voltage for a particular voltage step in V.",
),
capacity_grav_max: Optional[float] = Query(
None,
description="Maximum value for the gravimetric capacity in maH/g.",
None, description="Maximum value for the gravimetric capacity in maH/g.",
),
capacity_grav_min: Optional[float] = Query(
None,
description="Minimum value for the gravimetric capacity in maH/g.",
None, description="Minimum value for the gravimetric capacity in maH/g.",
),
capacity_vol_max: Optional[float] = Query(
None,
description="Maximum value for the volumetric capacity in maH/cc.",
None, description="Maximum value for the volumetric capacity in maH/cc.",
),
capacity_vol_min: Optional[float] = Query(
None,
description="Minimum value for the volumetric capacity in maH/cc.",
None, description="Minimum value for the volumetric capacity in maH/cc.",
),
energy_grav_max: Optional[float] = Query(
None,
Expand Down
4 changes: 3 additions & 1 deletion src/mp_api/materials/models/doc.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
from pydantic import BaseModel, Field, validator
from pymatgen.core.periodic_table import Element
from datetime import datetime
from mp_api.materials.models import Structure, Composition, CrystalSystem
from mp_api.materials.models import CrystalSystem
from pymatgen.core.structure import Structure
from pymatgen.core.composition import Composition


class SymmetryData(BaseModel):
Expand Down
24 changes: 14 additions & 10 deletions src/mp_api/materials/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,20 @@ def formula_to_criteria(formula: str) -> Dict:
"""
dummies = "ADEGJLMQRXZ"

if "*" in formula:
if "-" in formula:
crit = {} # type: dict
eles = formula.split("-")

if "*" in eles:
crit["nelements"] = len(eles)
crit["elements"] = {"$in": [ele for ele in eles if ele != "*"]}
return crit
else:
chemsys = "-".join(sorted(eles))
crit["chemsys"] = chemsys
return crit

elif "*" in formula:
# Wild card in formula
nstars = formula.count("*")

Expand All @@ -39,15 +52,6 @@ def formula_to_criteria(formula: str) -> Dict:

return crit

elif "-" in formula:
crit = {}
eles = formula.split("-")
chemsys = "-".join(sorted(eles))

crit["chemsys"] = chemsys

return crit

elif any(isinstance(el, DummySpecies) for el in Composition(formula)):
# Assume fully anonymized formula
return {"formula_anonymous": Composition(formula).anonymized_formula}
Expand Down
4 changes: 2 additions & 2 deletions src/mp_api/molecules/resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
MoleculeElementsQuery,
MoleculeFormulaQuery,
)
from mp_api.search.query_operators import SearchTaskIDsQuery
from mp_api.tasks.query_operators import MultipleTaskIDsQuery


def molecules_resource(molecules_store):
Expand All @@ -18,7 +18,7 @@ def molecules_resource(molecules_store):
MoleculeBaseQuery(),
MoleculeElementsQuery(),
MoleculeFormulaQuery(),
SearchTaskIDsQuery(),
MultipleTaskIDsQuery(),
SortQuery(),
PaginationQuery(),
SparseFieldsQuery(MoleculesDoc, default_fields=["task_id"]),
Expand Down

0 comments on commit a21a96f

Please sign in to comment.