diff --git a/README.md b/README.md index 01a69d3..df0bacb 100644 --- a/README.md +++ b/README.md @@ -45,8 +45,8 @@ Users will be prompted to select one or more surfaces that should be relaxed. Input to this function includes: -* The SMILES string of the adsorbate to place -* The Materials Project ID of the bulk structure from which surfaces will be generated +* The name of the adsorbate to place +* A unique ID of the bulk structure from which surfaces will be generated This function will perform the following steps: @@ -68,6 +68,25 @@ This should take 2-10 minutes to finish while tens to hundreds (depending on the * The predicted force on each atom in the final structure +### Supported bulks and adsorbates + +A finite set of bulk materials and adsorbates can be referenced by ID throughout the OCP API. The lists of supported values can be viewed in two ways. + +1. Visit the UI at https://open-catalyst.metademolab.com/demo and explore the lists in Step 1 and Step 3. +2. Use the low-level client that ships with this library: +```python +from ocpapi import Client + +client = Client() + +bulks = await client.get_bulks() +print({b.src_id: b.formula for b in bulks.bulks_supported}) + +adsorbates = await client.get_adsorbates() +print(adsorbates.adsorbates_supported) +``` + + ### Persisting results **Results should be saved whenever possible in order to avoid expensive recomputation.** diff --git a/ocpapi/client/client.py b/ocpapi/client/client.py index 92e0377..57f6b39 100644 --- a/ocpapi/client/client.py +++ b/ocpapi/client/client.py @@ -109,15 +109,15 @@ async def get_models(self) -> Models: Fetch the list of models that are supported in the API. Raises: - RateLimitExceededException if the call was rejected because a + RateLimitExceededException: If the call was rejected because a server side rate limit was breached. - NonRetryableRequestException if the call was rejected and a retry + NonRetryableRequestException: If the call was rejected and a retry is not expected to succeed. - RequestException for all other errors when making the request; it + RequestException: For all other errors when making the request; it is possible, though not guaranteed, that a retry could succeed. Returns: - Models + The models that are supported in the API. """ response: str = await self._run_request( path="ocp/models", @@ -130,15 +130,15 @@ async def get_bulks(self) -> Bulks: Fetch the list of bulk materials that are supported in the API. Raises: - RateLimitExceededException if the call was rejected because a + RateLimitExceededException: If the call was rejected because a server side rate limit was breached. - NonRetryableRequestException if the call was rejected and a retry + NonRetryableRequestException: If the call was rejected and a retry is not expected to succeed. - RequestException for all other errors when making the request; it + RequestException: For all other errors when making the request; it is possible, though not guaranteed, that a retry could succeed. Returns: - Bulks + The bulks that are supported throughout the API. """ response: str = await self._run_request( path="ocp/bulks", @@ -151,15 +151,15 @@ async def get_adsorbates(self) -> Adsorbates: Fetch the list of adsorbates that are supported in the API. Raises: - RateLimitExceededException if the call was rejected because a + RateLimitExceededException: If the call was rejected because a server side rate limit was breached. - NonRetryableRequestException if the call was rejected and a retry + NonRetryableRequestException: If the call was rejected and a retry is not expected to succeed. - RequestException for all other errors when making the request; it + RequestException: For all other errors when making the request; it is possible, though not guaranteed, that a retry could succeed. Returns: - Adsorbates + The adsorbates that are supported throughout the API. """ response: str = await self._run_request( path="ocp/adsorbates", @@ -176,15 +176,15 @@ async def get_slabs(self, bulk: Union[str, Bulk]) -> Slabs: instance to use. Raises: - RateLimitExceededException if the call was rejected because a + RateLimitExceededException: If the call was rejected because a server side rate limit was breached. - NonRetryableRequestException if the call was rejected and a retry + NonRetryableRequestException: If the call was rejected and a retry is not expected to succeed. - RequestException for all other errors when making the request; it + RequestException: For all other errors when making the request; it is possible, though not guaranteed, that a retry could succeed. Returns: - Slabs + Slabs for each of the unique surfaces of the material. """ response: str = await self._run_request( path="ocp/slabs", @@ -204,20 +204,20 @@ async def get_adsorbate_slab_configs( input slab. Args: - adsorbate: SMILES string describing the adsorbate to place. + adsorbate: Description of the the adsorbate to place. slab: Information about the slab on which the adsorbate should be placed. Raises: - RateLimitExceededException if the call was rejected because a + RateLimitExceededException: If the call was rejected because a server side rate limit was breached. - NonRetryableRequestException if the call was rejected and a retry + NonRetryableRequestException: If the call was rejected and a retry is not expected to succeed. - RequestException for all other errors when making the request; it + RequestException: For all other errors when making the request; it is possible, though not guaranteed, that a retry could succeed. Returns: - AdsorbateSlabConfigs + Configurations for each adsorbate binding site on the slab. """ response: str = await self._run_request( path="ocp/adsorbate-slab-configs", @@ -248,7 +248,7 @@ async def submit_adsorbate_slab_relaxations( that is returned from this method. Args: - adsorbate: SMILES string describing the adsorbate being simulated. + adsorbate: Description of the adsorbate being simulated. adsorbate_configs: List of adsorbate configurations to relax. This should only include the adsorbates themselves; the surface is defined in the "slab" field that is a peer to this one. @@ -262,15 +262,15 @@ async def submit_adsorbate_slab_relaxations( testing when there is no reason for results to be persisted. Raises: - RateLimitExceededException if the call was rejected because a + RateLimitExceededException: If the call was rejected because a server side rate limit was breached. - NonRetryableRequestException if the call was rejected and a retry + NonRetryableRequestException: If the call was rejected and a retry is not expected to succeed. - RequestException for all other errors when making the request; it + RequestException: For all other errors when making the request; it is possible, though not guaranteed, that a retry could succeed. Returns: - AdsorbateSlabRelaxationsSystem + IDs of the relaxations. """ response: str = await self._run_request( path="ocp/adsorbate-slab-relaxations", @@ -299,15 +299,15 @@ async def get_adsorbate_slab_relaxations_request( system_id: The ID of the system to fetch. Raises: - RateLimitExceededException if the call was rejected because a + RateLimitExceededException: If the call was rejected because a server side rate limit was breached. - NonRetryableRequestException if the call was rejected and a retry + NonRetryableRequestException: If the call was rejected and a retry is not expected to succeed. - RequestException for all other errors when making the request; it + RequestException: For all other errors when making the request; it is possible, though not guaranteed, that a retry could succeed. Returns: - AdsorbateSlabRelaxationsRequest + The original request that was made when submitting relaxations. """ response: str = await self._run_request( path=f"ocp/adsorbate-slab-relaxations/{system_id}", @@ -332,15 +332,15 @@ async def get_adsorbate_slab_relaxations_results( configuration to fetch. Otherwise all fields are returned. Raises: - RateLimitExceededException if the call was rejected because a + RateLimitExceededException: If the call was rejected because a server side rate limit was breached. - NonRetryableRequestException if the call was rejected and a retry + NonRetryableRequestException: If the call was rejected and a retry is not expected to succeed. - RequestException for all other errors when making the request; it + RequestException: For all other errors when making the request; it is possible, though not guaranteed, that a retry could succeed. Returns: - AdsorbateSlabRelaxationsResults + The relaxation results for each configuration in the system. """ params: Dict[str, Any] = {} if fields: @@ -362,11 +362,11 @@ async def delete_adsorbate_slab_relaxations(self, system_id: str) -> None: system_id: The ID of the system to delete. Raises: - RateLimitExceededException if the call was rejected because a + RateLimitExceededException: If the call was rejected because a server side rate limit was breached. - NonRetryableRequestException if the call was rejected and a retry + NonRetryableRequestException: If the call was rejected and a retry is not expected to succeed. - RequestException for all other errors when making the request; it + RequestException: For all other errors when making the request; it is possible, though not guaranteed, that a retry could succeed. """ await self._run_request( @@ -384,11 +384,11 @@ async def _run_request(self, path: str, method: str, **kwargs) -> str: method: The HTTP method to use (GET, POST, etc.). Raises: - RateLimitExceededException if the call was rejected because a + RateLimitExceededException: If the call was rejected because a server side rate limit was breached. - NonRetryableRequestException if the call was rejected and a retry + NonRetryableRequestException: If the call was rejected and a retry is not expected to succeed. - RequestException for all other errors when making the request; it + RequestException: For all other errors when making the request; it is possible, though not guaranteed, that a retry could succeed. Returns: diff --git a/ocpapi/client/models.py b/ocpapi/client/models.py index 21d0619..3e8a964 100644 --- a/ocpapi/client/models.py +++ b/ocpapi/client/models.py @@ -10,13 +10,13 @@ class _DataModel: """ Base class for all data models. - - Attributes: - other_fields: Fields that may have been added to the API that all - not yet supported explicitly in this class. """ other_fields: CatchAll + """ + Fields that may have been added to the API that all not yet supported + explicitly in this class. + """ @dataclass_json(undefined=Undefined.INCLUDE) @@ -24,12 +24,12 @@ class _DataModel: class Model(_DataModel): """ Stores information about a single model supported in the API. - - Attributes: - id: The ID of the model. """ id: str + """ + The ID of the model. + """ @dataclass_json(undefined=Undefined.INCLUDE) @@ -37,12 +37,12 @@ class Model(_DataModel): class Models(_DataModel): """ Stores the response from a request for models supported in the API. - - Attributes: - models: The list of models that are supported. """ models: List[Model] + """ + The list of models that are supported. + """ @dataclass_json(undefined=Undefined.INCLUDE) @@ -50,17 +50,23 @@ class Models(_DataModel): class Bulk(_DataModel): """ Stores information about a single bulk material. - - Attributes: - src_id: The ID of the material. - formula: The chemical formula of the material. - elements: The list of elements in the material. """ src_id: str + """ + The ID of the material. + """ + formula: str + """ + The chemical formula of the material. + """ + # Stored under "els" in the API response elements: List[str] = field(metadata=config(field_name="els")) + """ + The list of elements in the material. + """ @dataclass_json(undefined=Undefined.INCLUDE) @@ -68,12 +74,12 @@ class Bulk(_DataModel): class Bulks(_DataModel): """ Stores the response from a request to fetch bulks supported in the API. - - Attributes: - bulks_supported: List of bulks that can be used in the API. """ bulks_supported: List[Bulk] + """ + List of bulks that can be used in the API. + """ @dataclass_json(undefined=Undefined.INCLUDE) @@ -82,13 +88,12 @@ class Adsorbates(_DataModel): """ Stores the response from a request to fetch adsorbates supported in the API. - - Attributes: - adsorbates_supported: List of adsorbates that can be used in the API, - each in SMILES notation. """ adsorbates_supported: List[str] + """ + List of adsorbates that can be used in the API. + """ @dataclass_json(undefined=Undefined.INCLUDE) @@ -97,17 +102,6 @@ class Atoms(_DataModel): """ Subset of the fields from an ASE Atoms object that are used within this API. - - Attributes: - cell: 3x3 matrix with unit cell vectors. - pbc: Whether the structure is periodic along the a, b, and c lattice - vectors, respectively. - numbers: The atomic number of each atom in the unit cell. - positions: The coordinates of each atom in the unit cell, relative to - the cartesian frame. - tags: Labels for each atom in the unit cell where 0 represents a - subsurface atom (fixed during optimization), 1 represents a - surface atom, and 2 represents an adsorbate atom. """ cell: Tuple[ @@ -115,12 +109,43 @@ class Atoms(_DataModel): Tuple[float, float, float], Tuple[float, float, float], ] + """ + 3x3 matrix with unit cell vectors. + """ + pbc: Tuple[bool, bool, bool] + """ + Whether the structure is periodic along the a, b, and c lattice vectors, + respectively. + """ + numbers: List[int] + """ + The atomic number of each atom in the unit cell. + """ + positions: List[Tuple[float, float, float]] + """ + The coordinates of each atom in the unit cell, relative to the cartesian + frame. + """ + tags: List[int] + """ + Labels for each atom in the unit cell where 0 represents a subsurface atom + (fixed during optimization), 1 represents a surface atom, and 2 represents + an adsorbate atom. + """ def to_ase_atoms(self) -> "ASEAtoms": + """ + Creates an ase.Atoms object with the positions, element numbers, + etc. populated from values on this object. + + Returns: + ase.Atoms object with values from this object. + """ + from ase import Atoms as ASEAtoms from ase.constraints import FixAtoms @@ -140,22 +165,30 @@ def to_ase_atoms(self) -> "ASEAtoms": class SlabMetadata(_DataModel): """ Stores metadata about a slab that is returned from the API. - - Attributes: - bulk_src_id: The ID of the bulk material from which the slab was - derived. - millers: The Miller indices of the slab relative to bulk structure. - shift: The position along the vector defined by the Miller indices - at which a cut was taken to generate the slab surface. - top: If False, the top and bottom surfaces for this millers/shift - pair are distinct and this slab represents the bottom surface. """ # Stored under "bulk_id" in the API response bulk_src_id: str = field(metadata=config(field_name="bulk_id")) + """ + The ID of the bulk material from which the slab was derived. + """ + millers: Tuple[int, int, int] + """ + The Miller indices of the slab relative to bulk structure. + """ + shift: float + """ + The position along the vector defined by the Miller indices at which a + cut was taken to generate the slab surface. + """ + top: bool + """ + If False, the top and bottom surfaces for this millers/shift pair are + distinct and this slab represents the bottom surface. + """ @dataclass_json(undefined=Undefined.INCLUDE) @@ -163,16 +196,19 @@ class SlabMetadata(_DataModel): class Slab(_DataModel): """ Stores all information about a slab that is returned from the API. - - Attributes: - atoms: The structure of the slab. - metadata: Extra information about the slab. """ # Stored under "slab_atomsobject" in the API response atoms: Atoms = field(metadata=config(field_name="slab_atomsobject")) + """ + The structure of the slab. + """ + # Stored under "slab_metadata" in the API response metadata: SlabMetadata = field(metadata=config(field_name="slab_metadata")) + """ + Extra information about the slab. + """ @dataclass_json(undefined=Undefined.INCLUDE) @@ -180,13 +216,12 @@ class Slab(_DataModel): class Slabs(_DataModel): """ Stores the response from a request to fetch slabs for a bulk structure. - - Attributes: - slabs: The list of slabs that were generated from the input bulk - structure. """ slabs: List[Slab] + """ + The list of slabs that were generated from the input bulk structure. + """ @dataclass_json(undefined=Undefined.INCLUDE) @@ -195,15 +230,17 @@ class AdsorbateSlabConfigs(_DataModel): """ Stores the response from a request to fetch placements of a single absorbate on a slab. - - Attributes: - adsorbate_configs: List of structures, each representing one possible - adsorbate placement. - slab: The structure of the slab on which the adsorbate is placed. """ adsorbate_configs: List[Atoms] + """ + List of structures, each representing one possible adsorbate placement. + """ + slab: Slab + """ + The structure of the slab on which the adsorbate is placed. + """ @dataclass_json(undefined=Undefined.INCLUDE) @@ -212,16 +249,19 @@ class AdsorbateSlabRelaxationsSystem(_DataModel): """ Stores the response from a request to submit a new batch of adsorbate slab relaxations. - - Attributes: - system_id: Unique ID for this set of relaxations which can be used to - fetch results later. - config_ids: The list of IDs assigned to each of the input adsorbate - placements, in the same order in which they were submitted. """ system_id: str + """ + Unique ID for this set of relaxations which can be used to fetch results + later. + """ + config_ids: List[int] + """ + The list of IDs assigned to each of the input adsorbate placements, in the + same order in which they were submitted. + """ @dataclass_json(undefined=Undefined.INCLUDE) @@ -229,54 +269,79 @@ class AdsorbateSlabRelaxationsSystem(_DataModel): class AdsorbateSlabRelaxationsRequest(_DataModel): """ Stores the request to submit a new batch of adsorbate slab relaxations. - - Attributes: - adsorbate: SMILES string desribing the adsorbate. - adsorbate_configs: List of adsorbate placements being relaxed. - bulk: Information about the original bulk structure used to create - the slab. - slab: The structure of the slab on which adsorbates are placed. - model: The type of the ML model being used during relaxations. - ephemeral: Whether the relaxations can be deleted (assume they - cannot be deleted if None). - adsorbate_reaction: If possible, an html-formatted string describing - the reaction will be added to this field. """ adsorbate: str + """ + Description of the adsorbate. + """ + adsorbate_configs: List[Atoms] + """ + List of adsorbate placements being relaxed. + """ + bulk: Bulk + """ + Information about the original bulk structure used to create the slab. + """ + slab: Slab + """ + The structure of the slab on which adsorbates are placed. + """ + model: str + """ + The type of the ML model being used during relaxations. + """ + # Omit from serialization when None ephemeral: Optional[bool] = field( default=None, metadata=config(exclude=lambda v: v is None), ) + """ + Whether the relaxations can be deleted (assume they cannot be deleted if + None). + """ + adsorbate_reaction: Optional[str] = field( default=None, metadata=config(exclude=lambda v: v is None), ) + """ + If possible, an html-formatted string describing the reaction will be added + to this field. + """ class Status(Enum): """ Relaxation status of a single adsorbate placement on a slab. - - Attributes: - NOT_AVAILABLE: The configuration exists but the result is not yet - available. It is possible that checking again in the future could - yield a result. - FAILED_RELAXATION: The relaxation failed for this configuration. - SUCCESS: The relaxation was successful and the requested information - about the configuration was returned. - DOES_NOT_EXIST: The requested configuration does not exist. """ NOT_AVAILABLE = "not_available" + """ + The configuration exists but the result is not yet available. It is + possible that checking again in the future could yield a result. + """ + FAILED_RELAXATION = "failed_relaxation" + """ + The relaxation failed for this configuration. + """ + SUCCESS = "success" + """ + The relaxation was successful and the requested information about the + configuration was returned. + """ + DOES_NOT_EXIST = "does_not_exist" + """ + The requested configuration does not exist. + """ def __str__(self) -> str: return self.value @@ -292,35 +357,27 @@ class AdsorbateSlabRelaxationResult(_DataModel): The API to fetch relaxation results supports requesting a subset of fields in order to limit the size of response payloads. Optional attributes will be defined only if they are including the response. - - Attributes: - config_id: ID of the configuration within the system - status: The status of the request for information about this - configuration. - system_id: The ID of the system in which the configuration was - originally submitted. - cell: 3x3 matrix with unit cell vectors. - pbc: Whether the structure is periodic along the a, b, and c lattice - vectors, respectively. - numbers: The atomic number of each atom in the unit cell. - positions: The coordinates of each atom in the unit cell, relative to - the cartesian frame. - tags: Labels for each atom in the unit cell where 0 represents a - subsurface atom (fixed during optimization), 1 represents a - surface atom, and 2 represents an adsorbate atom. - energy: The energy of the configuration. - energy_trajectory: The energy of the configuration at each point along - the relaxation trajectory. - forces: The forces on each atom in the relaxed structure. """ config_id: int + """ + ID of the configuration within the system. + """ + status: Status + """ + The status of the request for information about this configuration. + """ + # Omit from serialization when None system_id: Optional[str] = field( default=None, metadata=config(exclude=lambda v: v is None), ) + """ + The ID of the system in which the configuration was originally submitted. + """ + cell: Optional[ Tuple[ Tuple[float, float, float], @@ -331,42 +388,82 @@ class AdsorbateSlabRelaxationResult(_DataModel): default=None, metadata=config(exclude=lambda v: v is None), ) + """ + 3x3 matrix with unit cell vectors. + """ + pbc: Optional[Tuple[bool, bool, bool]] = field( default=None, metadata=config(exclude=lambda v: v is None), ) + """ + Whether the structure is periodic along the a, b, and c lattice vectors, + respectively. + """ + numbers: Optional[List[int]] = field( default=None, metadata=config(exclude=lambda v: v is None), ) + """ + The atomic number of each atom in the unit cell. + """ + positions: Optional[List[Tuple[float, float, float]]] = field( default=None, metadata=config(exclude=lambda v: v is None), ) + """ + The coordinates of each atom in the unit cell, relative to the cartesian + frame. + """ + tags: Optional[List[int]] = field( default=None, metadata=config(exclude=lambda v: v is None), ) + """ + Labels for each atom in the unit cell where 0 represents a subsurface atom + (fixed during optimization), 1 represents a surface atom, and 2 represents + an adsorbate atom. + """ + energy: Optional[float] = field( default=None, metadata=config(exclude=lambda v: v is None), ) + """ + The energy of the configuration. + """ + energy_trajectory: Optional[List[float]] = field( default=None, metadata=config(exclude=lambda v: v is None), ) + """ + The energy of the configuration at each point along the relaxation + trajectory. + """ + forces: Optional[List[Tuple[float, float, float]]] = field( default=None, metadata=config(exclude=lambda v: v is None), ) + """ + The forces on each atom in the relaxed structure. + """ def to_ase_atoms(self) -> "ASEAtoms": """ - Creates an ASE Atoms object from values in this instance. Only those - fields that are supported by the ASE Atoms class will be copied. + Creates an ase.Atoms object with the positions, element numbers, + etc. populated from values on this object. + + The predicted energy and forces will also be copied to the new + ase.Atoms object as a SinglePointCalculator (a calculator that + stores the results of an already-run simulation). Returns: - ASE Atoms object with values from this instance. + ase.Atoms object with values from this object. """ from ase import Atoms as ASEAtoms from ase.calculators.singlepoint import SinglePointCalculator @@ -396,14 +493,16 @@ class AdsorbateSlabRelaxationsResults(_DataModel): """ Stores the response from a request for results of adsorbate slab relaxations. - - Attributes: - configs: List of configurations in the system, each representing - one placement of an adsorbate on a slab surface. - omitted_config_ids: List of IDs of configurations that were requested - but omitted by the server. Results for these IDs can be requested - again. """ configs: List[AdsorbateSlabRelaxationResult] + """ + List of configurations in the system, each representing one placement of + an adsorbate on a slab surface. + """ + omitted_config_ids: List[int] = field(default_factory=lambda: list()) + """ + List of IDs of configurations that were requested but omitted by the + server. Results for these IDs can be requested again. + """ diff --git a/ocpapi/workflows/adsorbates.py b/ocpapi/workflows/adsorbates.py index d53d4fd..011b6ac 100644 --- a/ocpapi/workflows/adsorbates.py +++ b/ocpapi/workflows/adsorbates.py @@ -137,19 +137,25 @@ def __init__(self, adsorbate: str) -> None: class Lifetime(Enum): """ Represents different lifetimes when running relaxations. - - Attributes: - SAVE: The relaxation will be available on API servers indefinitely. - It will not be possible to delete the relaxation in the future. - MARK_EPHEMERAL: The relaxation will be saved on API servers, but - can be deleted at any time in the future. - DELETE: The relaxation will be deleted from API servers as soon as - the results have been fetched. """ SAVE = auto() + """ + The relaxation will be available on API servers indefinitely. It will not + be possible to delete the relaxation in the future. + """ + MARK_EPHEMERAL = auto() + """ + The relaxation will be saved on API servers, but can be deleted at any time + in the future. + """ + DELETE = auto() + """ + The relaxation will be deleted from API servers as soon as the results have + been fetched. + """ @dataclass_json(undefined=Undefined.EXCLUDE) @@ -157,21 +163,33 @@ class Lifetime(Enum): class AdsorbateSlabRelaxations: """ Stores the relaxations of adsorbate placements on the surface of a slab. - - Attributes: - slab: The slab on which the adsorbate was placed. - configs: Details of the relaxation of each adsorbate placement, - include the final position. - system_id: The ID of the system that stores all of the relaxations. - api_host: The API host on which the relaxations were run. - ui_url: The URL at which results can be visualized. """ slab: Slab + """ + The slab on which the adsorbate was placed. + """ + configs: List[AdsorbateSlabRelaxationResult] + """ + Details of the relaxation of each adsorbate placement, including the + final position. + """ + system_id: str + """ + The ID of the system that stores all of the relaxations. + """ + api_host: str + """ + The API host on which the relaxations were run. + """ + ui_url: Optional[str] + """ + The URL at which results can be visualized. + """ @dataclass_json(undefined=Undefined.EXCLUDE) @@ -180,19 +198,28 @@ class AdsorbateBindingSites: """ Stores the inputs and results of a set of relaxations of adsorbate placements on the surface of a slab. - - Attributes: - adsorbate: The SMILES string of the adsorbate. - bulk: The bulk material that was being modeled. - model: The type of the model that was run. - slabs: The list of slabs that were generated from the bulk structure. - Each contains its own list of adsorbate placements. """ adsorbate: str + """ + Description of the adsorbate. + """ + bulk: Bulk + """ + The bulk material that was being modeled. + """ + model: str + """ + The type of the model that was run. + """ + slabs: List[AdsorbateSlabRelaxations] + """ + The list of slabs that were generated from the bulk structure. Each + contains its own list of adsorbate placements. + """ @retry_api_calls(max_attempts=3) @@ -205,7 +232,7 @@ async def _ensure_model_supported(client: Client, model: str) -> None: model: The model to check. Raises: - UnsupportedModelException if the model is not supported. + UnsupportedModelException: If the model is not supported. """ models: Models = await client.get_models() allowed_models: List[str] = [m.id for m in models.models] @@ -226,7 +253,7 @@ async def _get_bulk_if_supported(client: Client, bulk: str) -> Bulk: bulk: The bulk to fetch. Raises: - UnsupportedBulkException if the requested bulk is not supported. + UnsupportedBulkException: If the requested bulk is not supported. Returns: Bulk instance for the input type. @@ -248,7 +275,7 @@ async def _ensure_adsorbate_supported(client: Client, adsorbate: str) -> None: adsorbate: The adsorbate to check. Raises: - UnsupportedAdsorbateException if the adsorbate is not supported. + UnsupportedAdsorbateException: If the adsorbate is not supported. """ adsorbates: Adsorbates = await client.get_adsorbates() if adsorbate not in adsorbates.adsorbates_supported: @@ -266,6 +293,9 @@ async def _get_slabs( Args: client: The client to use when making requests to the API. bulk: The bulk material from which slabs will be generated. + + Returns: + The list of slabs that were generated. """ slabs: Slabs = await client.get_slabs(bulk) return slabs.slabs @@ -282,7 +312,7 @@ async def _get_absorbate_configs_on_slab( Args: client: The client to use when making API calls. - adsorbate: The SMILES string of the adsorbate to place. + adsorbate: Description of the adsorbate to place. slab: The slab on which the adsorbate should be placed. Returns: @@ -326,6 +356,7 @@ async def _get_adsorbate_configs_on_slabs( ) -> List[AdsorbateSlabConfigs]: """ Finds candidate adsorbate binding sites on each of the input slabs. + Args: client: The client to use when making API calls. adsorbate: Description of the adsorbate to place. @@ -377,7 +408,7 @@ async def _submit_relaxations( Args: client: The client to use when making API calls. - adsorbate: The SMILES string of the adsorbate to place. + adsorbate: Description of the adsorbate to place. adsorbate_configs: Positions of the adsorbate on the slab. Each will be relaxed independently. bulk: The bulk material from which the slab was generated. @@ -624,7 +655,7 @@ async def _run_relaxations_on_slab( Args: client: The client to use when making API calls. - adsorbate: The SMILES string of the adsorbate to place. + adsorbate: Description of the adsorbate to place. adsorbate_configs: The positions of atoms in each adsorbate placement to be relaxed. bulk: The bulk material from which the slab was generated. @@ -717,7 +748,7 @@ async def _relax_binding_sites_on_slabs( Args: client: The client to use when making API calls. - adsorbate: The SMILES string of the adsorbate to place. + adsorbate: Description of the adsorbate to place. bulk: The bulk material from which the slab was generated. adslabs: The slabs and, for each, the binding sites that should be relaxed. @@ -811,7 +842,7 @@ async def find_adsorbate_binding_sites( atomic positions to minimize forces generated by the input model. Args: - adsorbate: SMILES string describing the adsorbate to place. + adsorbate: Description of the adsorbate to place. bulk: The ID (typically Materials Project MP ID) of the bulk material on which the adsorbate will be placed. model: The type of the model to use when calculating forces during @@ -829,9 +860,9 @@ async def find_adsorbate_binding_sites( to locally-optimized positions using the input model. Raises: - UnsupportedModelException if the requested model is not supported. - UnsupportedBulkException if the requested bulk is not supported. - UnsupportedAdsorbateException if the requested adsorbate is not + UnsupportedModelException: If the requested model is not supported. + UnsupportedBulkException: If the requested bulk is not supported. + UnsupportedAdsorbateException: If the requested adsorbate is not supported. """ with set_context_var(_CTX_AD_BULK, (adsorbate, bulk)): diff --git a/ocpapi/workflows/retry.py b/ocpapi/workflows/retry.py index a295e07..1df18f8 100644 --- a/ocpapi/workflows/retry.py +++ b/ocpapi/workflows/retry.py @@ -25,14 +25,17 @@ class RateLimitLogging: """ Controls logging when rate limits are hit. - - Attributes: - logger: The logger to use. - action: A short description of the action being attempted. """ logger: logging.Logger + """ + The logger to use. + """ + action: str + """ + A short description of the action being attempted. + """ class _wait_check_retry_after(wait_base):