From 003e68390e6315087c6d6b38fd70797d99c2d9b9 Mon Sep 17 00:00:00 2001 From: Kyle Michel Date: Fri, 13 Oct 2023 08:41:46 -0700 Subject: [PATCH] Documentation fixes Adds a note to the README about the supported bulks and adsorbates, fixes some language in documentation throughout the package, and modifies some docstrings so that they work well with sphinx documentation generators. --- README.md | 23 ++- ocpapi/client/client.py | 80 ++++---- ocpapi/client/models.py | 323 +++++++++++++++++++++------------ ocpapi/workflows/adsorbates.py | 99 ++++++---- ocpapi/workflows/retry.py | 11 +- 5 files changed, 344 insertions(+), 192 deletions(-) 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):