Skip to content

Commit

Permalink
Merge pull request #926 from espottesmith/query_restructure
Browse files Browse the repository at this point in the history
[WIP] Large structural changes to MPcules
  • Loading branch information
tschaume authored Sep 4, 2024
2 parents 7ded807 + 1ddb41c commit 69adac5
Show file tree
Hide file tree
Showing 74 changed files with 3,598 additions and 5,528 deletions.
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,6 @@ emmet/scripts/token.json

Error_Record

# emmet autogenerated enums
# Emmet autogenerated enums
# emmet-core/emmet/core/vasp/calc_types/enums.py
# emmet-core/emmet/core/qchem/calc_types/enums.py
emmet-core/emmet/core/qchem/calc_types/enums.py
6 changes: 4 additions & 2 deletions emmet-api/emmet/api/routes/molecules/association/resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,15 @@
from emmet.api.routes.molecules.molecules.query_operators import (
FormulaQuery,
ChemsysQuery,
ElementsQuery,
CompositionElementsQuery,
ChargeSpinQuery,
DeprecationQuery,
MultiTaskIDQuery,
MultiMPculeIDQuery,
FindMoleculeQuery,
CalcMethodQuery,
HashQuery,
StringRepQuery,
)

from emmet.api.core.global_header import GlobalHeaderProcessor
Expand Down Expand Up @@ -52,11 +53,12 @@ def mol_assoc_resource(assoc_store):
MultiMPculeIDQuery(),
FormulaQuery(),
ChemsysQuery(),
ElementsQuery(),
CompositionElementsQuery(),
ChargeSpinQuery(),
MultiTaskIDQuery(),
CalcMethodQuery(),
HashQuery(),
StringRepQuery(),
DeprecationQuery(),
NumericQuery(model=MoleculeDoc),
PaginationQuery(),
Expand Down
12 changes: 6 additions & 6 deletions emmet-api/emmet/api/routes/molecules/bonds/query_operators.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ def query(
bond_type: Optional[str] = Query(
None, description="Bond type of interest; e.g. C-O for carbon-oxygen bonds."
),
max_bond_length: Optional[float] = Query(
bond_length_max: Optional[float] = Query(
None,
description="Maximum value for the bond lengths in the molecule.",
),
min_bond_length: Optional[float] = Query(
bond_length_min: Optional[float] = Query(
None,
description="Minimum value for the bond lengths in the molecule.",
),
Expand All @@ -39,10 +39,10 @@ def query(
key: dict() # type: ignore
} # type: ignore

if max_bond_length is not None:
crit[key]["$lte"] = max_bond_length
if min_bond_length is not None:
crit[key]["$gte"] = min_bond_length
if bond_length_max is not None:
crit[key]["$lte"] = bond_length_max
if bond_length_min is not None:
crit[key]["$gte"] = bond_length_min

# If no max or min, just make sure bond type exists
if len(crit[key]) == 0:
Expand Down
4 changes: 2 additions & 2 deletions emmet-api/emmet/api/routes/molecules/bonds/resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
ExactCalcMethodQuery,
FormulaQuery,
ChemsysQuery,
ElementsQuery,
CompositionElementsQuery,
ChargeSpinQuery,
)
from emmet.api.routes.molecules.utils import MethodQuery, MultiPropertyIDQuery
Expand All @@ -28,7 +28,7 @@ def bonding_resource(bonds_store):
ExactCalcMethodQuery(),
FormulaQuery(),
ChemsysQuery(),
ElementsQuery(),
CompositionElementsQuery(),
ChargeSpinQuery(),
MethodQuery(),
MultiPropertyIDQuery(),
Expand Down
110 changes: 110 additions & 0 deletions emmet-api/emmet/api/routes/molecules/electric/query_operators.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
from typing import Any, Literal, Optional, Dict
from fastapi import Query
from maggma.api.query_operator import QueryOperator
from maggma.api.utils import STORE_PARAMS


allowed_components = {
"dipole": {"X", "Y", "Z"},
"resp_dipole": {"X", "Y", "Z"},
"quadrupole": {"XX", "XY", "YY", "XZ", "YZ", "ZZ"},
"octopole": {"XXX", "XXY", "XYY", "YYY", "XXZ", "XYZ", "YYZ", "XZZ", "YZZ", "ZZZ"},
"hexadecapole": {
"XXXX",
"XXXY",
"XXYY",
"XYYY",
"YYYY",
"XXXZ",
"XXYZ",
"XYYZ",
"YYYZ",
"XXZZ",
"XYZZ",
"YYZZ",
"XZZZ",
"YZZZ",
"ZZZZ",
},
}


class MultipoleMomentComponentQuery(QueryOperator):
"""
Method to generate a query on components of electric multipole moments.
"""

def query(
self,
moment_type: Optional[
Literal["dipole", "resp_dipole", "quadrupole", "octopole", "hexadecapole"]
] = Query(
None,
description=(
"Type of multipole moment. Allowed values: 'dipole', 'resp_dipole', 'quadrupole', 'octopole', and "
"'hexadecapole'"
),
),
component: Optional[str] = Query(
None,
description="Component to query on, i.e. 'X', 'Y', or 'Z' for dipole moments",
),
component_value_min: Optional[float] = Query(
None, description="Minimum value for the multipole moment component"
),
component_value_max: Optional[float] = Query(
None, description="Maximum value for the multipole moment component"
),
) -> STORE_PARAMS:
self.moment_type = moment_type
self.component = component
self.min_value = component_value_min
self.max_value = component_value_max

if self.moment_type is None or self.component is None:
return {"criteria": dict()}

allowed = allowed_components[self.moment_type]

if self.component not in allowed:
raise ValueError(
f"Improper component! Allowed components for {self.moment_type} are {allowed}!"
)

key_prefix = self.moment_type + "_moment"

if self.moment_type in ["dipole", "resp_dipole"]:
mapping = {"X": "0", "Y": "1", "Z": "2"}
key_suffix = mapping[self.component]
else:
key_suffix = self.component

key = key_prefix + "." + key_suffix

crit: Dict[str, Any] = {key: dict()} # type: ignore

if self.min_value is not None and isinstance(self.min_value, float):
crit[key]["$gte"] = self.min_value
if self.max_value is not None and isinstance(self.max_value, float):
crit[key]["$lte"] = self.max_value

if not isinstance(self.min_value, float) and not isinstance(
self.max_value, float
):
crit[key]["$exists"] = True

return {"criteria": crit}

def ensure_indexes(self):
# Right now, indexing on all sub-fields of all electric multipole moments
# TODO: is this necessary? Is this the best way to do this?
indexes = list()
for dp in ["dipole_moment", "resp_dipole_moment"]:
for index in range(3):
indexes.append((f"{dp}.{index}", False))

for mp in ["quadrupole", "octopole", "hexadecapole"]:
for valid_key in allowed_components[mp]:
indexes.append((f"{mp}_moment.{valid_key}", False))

return indexes
64 changes: 64 additions & 0 deletions emmet-api/emmet/api/routes/molecules/electric/resources.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
from maggma.api.resource import ReadOnlyResource
from emmet.core.molecules.electric import ElectricMultipoleDoc

from maggma.api.query_operator import (
PaginationQuery,
SparseFieldsQuery,
NumericQuery,
)

from emmet.api.routes.molecules.electric.query_operators import (
MultipoleMomentComponentQuery,
)
from emmet.api.routes.molecules.molecules.query_operators import (
MultiMPculeIDQuery,
ExactCalcMethodQuery,
FormulaQuery,
ChemsysQuery,
CompositionElementsQuery,
ChargeSpinQuery,
)
from emmet.api.routes.molecules.utils import MultiPropertyIDQuery
from emmet.api.core.settings import MAPISettings
from emmet.api.core.global_header import GlobalHeaderProcessor


def electric_multipole_resource(multipole_store):
resource = ReadOnlyResource(
multipole_store,
ElectricMultipoleDoc,
query_operators=[
MultiMPculeIDQuery(),
ExactCalcMethodQuery(),
FormulaQuery(),
ChemsysQuery(),
CompositionElementsQuery(),
ChargeSpinQuery(),
MultiPropertyIDQuery(),
MultipoleMomentComponentQuery(),
PaginationQuery(),
NumericQuery(
model=ElectricMultipoleDoc,
fields=[
"total_dipole",
"resp_total_dipole",
],
),
SparseFieldsQuery(
ElectricMultipoleDoc,
default_fields=[
"molecule_id",
"property_id",
"solvent",
"last_updated",
],
),
],
header_processor=GlobalHeaderProcessor(),
tags=["Molecules Electric Dipoles and Multipoles"],
sub_path="/multipoles/",
disable_validation=True,
timeout=MAPISettings().TIMEOUT,
)

return resource
Original file line number Diff line number Diff line change
Expand Up @@ -15,64 +15,64 @@ def query(
None,
description="Element symbol for coordinated metal, e.g. 'Li' for lithium or 'Mg' for magnesium",
),
min_metal_partial_charge: Optional[float] = Query(
metal_partial_charge_min: Optional[float] = Query(
None, description="Minimum metal partial charge."
),
max_metal_partial_charge: Optional[float] = Query(
metal_partial_charge_max: Optional[float] = Query(
None, description="Maximum metal partial charge."
),
min_metal_partial_spin: Optional[float] = Query(
metal_partial_spin_min: Optional[float] = Query(
None,
description="Minimum metal partial spin (only meaningful for open-shell systems).",
),
max_metal_partial_spin: Optional[float] = Query(
metal_partial_spin_max: Optional[float] = Query(
None,
description="Maximum metal partial spin (only meaningful for open-shell systems).",
),
min_metal_assigned_charge: Optional[float] = Query(
metal_assigned_charge_min: Optional[float] = Query(
None,
description="Minimum charge of the metal, determined by analyzing partial charges/spins.",
),
max_metal_assigned_charge: Optional[float] = Query(
metal_assigned_charge_max: Optional[float] = Query(
None,
description="Maximum charge of the metal, determined by analyzing partial charges/spins.",
),
min_metal_assigned_spin: Optional[Union[int, float]] = Query(
metal_assigned_spin_min: Optional[Union[int, float]] = Query(
None,
description="Minimum spin multiplicity of the metal, determined by analyzing partial spins.",
),
max_metal_assigned_spin: Optional[Union[int, float]] = Query(
metal_assigned_spin_max: Optional[Union[int, float]] = Query(
None,
description="Maximum spin multiplicity of the metal, determined by analyzing partial spins.",
),
min_number_coordinate_bonds: Optional[int] = Query(
number_coordinate_bonds_min: Optional[int] = Query(
None, description="Minimum number of atoms coordinated to the metal."
),
max_number_coordinate_bonds: Optional[int] = Query(
number_coordinate_bonds_max: Optional[int] = Query(
None, description="Maximum number of atoms coordinated to the metal."
),
min_binding_energy: Optional[float] = Query(
binding_energy_min: Optional[float] = Query(
None, description="Minimum binding electronic energy (units: eV)"
),
max_binding_energy: Optional[float] = Query(
binding_energy_max: Optional[float] = Query(
None, description="Maximum binding electronic energy (units: eV)"
),
min_binding_enthalpy: Optional[float] = Query(
binding_enthalpy_min: Optional[float] = Query(
None, description="Minimum binding enthalpy (units: eV)"
),
max_binding_enthalpy: Optional[float] = Query(
binding_enthalpy_max: Optional[float] = Query(
None, description="Maximum binding enthalpy (units: eV)"
),
min_binding_entropy: Optional[float] = Query(
binding_entropy_min: Optional[float] = Query(
None, description="Minimum binding entropy (units: eV/K)"
),
max_binding_entropy: Optional[float] = Query(
binding_entropy_max: Optional[float] = Query(
None, description="Maximum binding entropy (units: eV/K)"
),
min_binding_free_energy: Optional[float] = Query(
binding_free_energy_min: Optional[float] = Query(
None, description="Minimum binding free energy (units: eV)"
),
max_binding_free_energy: Optional[float] = Query(
binding_free_energy_max: Optional[float] = Query(
None, description="Maximum binding free energy (units: eV)"
),
) -> STORE_PARAMS:
Expand All @@ -83,23 +83,23 @@ def query(

d = {
"metal_partial_charge": [
min_metal_partial_charge,
max_metal_partial_charge,
metal_partial_charge_min,
metal_partial_charge_max,
],
"metal_partial_spin": [min_metal_partial_spin, max_metal_partial_spin],
"metal_partial_spin": [metal_partial_spin_min, metal_partial_spin_max],
"metal_assigned_charge": [
min_metal_assigned_charge,
max_metal_assigned_charge,
metal_assigned_charge_min,
metal_assigned_charge_max,
],
"metal_assigned_spin": [min_metal_assigned_spin, max_metal_assigned_spin],
"metal_assigned_spin": [metal_assigned_spin_min, metal_assigned_spin_max],
"number_coordinate_bonds": [
min_number_coordinate_bonds,
max_number_coordinate_bonds,
number_coordinate_bonds_min,
number_coordinate_bonds_max,
],
"binding_energy": [min_binding_energy, max_binding_energy],
"binding_enthalpy": [min_binding_enthalpy, max_binding_enthalpy],
"binding_entropy": [min_binding_entropy, max_binding_entropy],
"binding_free_energy": [min_binding_free_energy, max_binding_free_energy],
"binding_energy": [binding_energy_min, binding_energy_max],
"binding_enthalpy": [binding_enthalpy_min, binding_enthalpy_max],
"binding_entropy": [binding_entropy_min, binding_entropy_max],
"binding_free_energy": [binding_free_energy_min, binding_free_energy_max],
}

for entry in d:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
ExactCalcMethodQuery,
FormulaQuery,
ChemsysQuery,
ElementsQuery,
CompositionElementsQuery,
ChargeSpinQuery,
)
from emmet.api.routes.molecules.metal_binding.query_operators import BindingDataQuery
Expand All @@ -26,7 +26,7 @@ def metal_binding_resource(metal_binding_store):
ExactCalcMethodQuery(),
FormulaQuery(),
ChemsysQuery(),
ElementsQuery(),
CompositionElementsQuery(),
ChargeSpinQuery(),
MethodQuery(),
BindingDataQuery(),
Expand Down
Loading

0 comments on commit 69adac5

Please sign in to comment.