-
Notifications
You must be signed in to change notification settings - Fork 1
feat: initial support for data-platform #430
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| # Data Platform API. | ||
|
|
||
| The DeepOriginClient can be used to access the data platform API using: | ||
|
|
||
| ```{.python notest} | ||
| from deeporigin.platform.client import DeepOriginClient | ||
|
|
||
| client = DeepOriginClient() | ||
| ``` | ||
|
|
||
| Then, the following methods can be used, for example: | ||
|
|
||
| ```{.python notest} | ||
| # Check the health status of the data platform | ||
| health_status = client.data.health() | ||
|
|
||
| # Search ligands joined with tool results | ||
| results = client.data.search_ligands_with_results( | ||
| limit=10, | ||
| experiments=[{"toolId": "deeporigin.docking"}], | ||
| ) | ||
|
|
||
| # Search an entity (e.g., ligands) | ||
| results = client.data.search("ligands") | ||
|
|
||
| # Search ligands using convenience method | ||
| results = client.data.search_ligands(limit=10) | ||
|
|
||
| # Search proteins using convenience method | ||
| results = client.data.search_proteins(limit=10) | ||
|
|
||
| # List public models | ||
| models = client.data.list_models() | ||
| ``` | ||
|
|
||
|
|
||
| ::: src.platform.data.Data | ||
| options: | ||
| heading_level: 2 | ||
| docstring_style: google | ||
| show_root_heading: true | ||
| show_category_heading: true | ||
| show_object_full_path: false | ||
| show_root_toc_entry: false | ||
| inherited_members: true | ||
| members_order: alphabetical | ||
| filters: | ||
| - "!^_" # Exclude private members (names starting with "_") | ||
| show_signature: true | ||
| show_signature_annotations: true | ||
| show_if_no_docstring: true | ||
| group_by_category: true |
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,300 @@ | ||||||||
| """Data Platform API wrapper for DeepOriginClient.""" | ||||||||
|
|
||||||||
| from __future__ import annotations | ||||||||
|
|
||||||||
| from functools import lru_cache | ||||||||
| from typing import TYPE_CHECKING, Any | ||||||||
|
|
||||||||
| if TYPE_CHECKING: | ||||||||
| from deeporigin.platform.client import DeepOriginClient | ||||||||
|
|
||||||||
|
|
||||||||
| class Data: | ||||||||
| """Data Platform API wrapper. | ||||||||
|
|
||||||||
| Provides access to data platform-related endpoints through the DeepOriginClient. | ||||||||
| """ | ||||||||
|
|
||||||||
| def __init__(self, client: DeepOriginClient) -> None: | ||||||||
| """Initialize Data wrapper. | ||||||||
|
|
||||||||
| Args: | ||||||||
| client: The DeepOriginClient instance to use for API calls. | ||||||||
| """ | ||||||||
| self._c = client | ||||||||
|
|
||||||||
| def health(self) -> dict: | ||||||||
| """Check the health status of the data platform. | ||||||||
|
|
||||||||
| Returns: | ||||||||
| Dictionary containing the health status response. | ||||||||
| """ | ||||||||
| return self._c.get_json("/data-platform/health") | ||||||||
|
|
||||||||
| @lru_cache(maxsize=1) # noqa: B019 | ||||||||
| def list_models(self) -> dict: | ||||||||
| """List public models. | ||||||||
|
|
||||||||
| Returns: | ||||||||
| Dictionary containing the list of models. | ||||||||
| """ | ||||||||
| return self._c.get_json(f"/data-platform/{self._c.org_key}/meta/models") | ||||||||
|
|
||||||||
| def search_ligands_with_results( | ||||||||
| self, | ||||||||
| *, | ||||||||
| cursor: str | None = None, | ||||||||
| experiments: list[dict[str, str]] | None = None, | ||||||||
| filter: dict[str, Any] | None = None, | ||||||||
| limit: int | None = None, | ||||||||
| offset: int | None = None, | ||||||||
| select: list[str] | None = None, | ||||||||
| sort: dict[str, str] | None = None, | ||||||||
| ) -> dict: | ||||||||
| """Search ligands joined with tool results (wide pivot view). | ||||||||
|
|
||||||||
| Args: | ||||||||
| cursor: Cursor for pagination. | ||||||||
| experiments: List of experiment filters, each containing toolId and | ||||||||
| optionally toolVersion. | ||||||||
| filter: Additional filter criteria as a dictionary. | ||||||||
| limit: Maximum number of results to return. Defaults to 100. | ||||||||
| offset: Number of results to skip. | ||||||||
| select: List of fields to select in the response. | ||||||||
| sort: Dictionary mapping field names to sort order ("asc" or "desc"). | ||||||||
|
|
||||||||
| Returns: | ||||||||
| Dictionary containing the search results. | ||||||||
| """ | ||||||||
| body: dict[str, Any] = {} | ||||||||
| if cursor is not None: | ||||||||
| body["cursor"] = cursor | ||||||||
| if experiments is not None: | ||||||||
| body["experiments"] = experiments | ||||||||
| if filter is not None: | ||||||||
| body["filter"] = filter | ||||||||
| if limit is not None: | ||||||||
| body["limit"] = limit | ||||||||
| if offset is not None: | ||||||||
| body["offset"] = offset | ||||||||
| if select is not None: | ||||||||
| body["select"] = select | ||||||||
| if sort is not None: | ||||||||
| body["sort"] = sort | ||||||||
|
|
||||||||
| return self._c.post_json( | ||||||||
| f"/data-platform/{self._c.org_key}/ligands_with_results/search", | ||||||||
| body=body, | ||||||||
| ) | ||||||||
|
|
||||||||
| def search( | ||||||||
| self, | ||||||||
| entity: str, | ||||||||
| *, | ||||||||
| cursor: str | None = None, | ||||||||
| filter_dict: dict[str, Any] | None = None, | ||||||||
|
||||||||
| limit: int | None = None, | ||||||||
| offset: int | None = None, | ||||||||
| select: list[str] | None = None, | ||||||||
| sort: dict[str, str] | None = None, | ||||||||
| ) -> dict: | ||||||||
| """Search an entity (table). | ||||||||
|
|
||||||||
| Args: | ||||||||
| entity: Entity (table) name to search (e.g., "ligands"). | ||||||||
| cursor: Cursor for pagination. | ||||||||
| filter_dict: Additional filter criteria as a dictionary. | ||||||||
| limit: Maximum number of results to return. Defaults to 100. | ||||||||
| offset: Number of results to skip. | ||||||||
| select: List of fields to select in the response. | ||||||||
| sort: Dictionary mapping field names to sort order ("asc" or "desc"). | ||||||||
|
|
||||||||
| Returns: | ||||||||
| Dictionary containing the search results. | ||||||||
|
|
||||||||
| Raises: | ||||||||
| ValueError: If the entity is not a valid table name. | ||||||||
| """ | ||||||||
| # Validate entity against list of available models | ||||||||
| models_response = self.list_models() | ||||||||
| valid_table_names = { | ||||||||
| model["tableName"] for model in models_response.get("models", []) | ||||||||
| } | ||||||||
| if entity not in valid_table_names: | ||||||||
| raise ValueError( | ||||||||
| f"Invalid entity '{entity}'. Valid entities are: {', '.join(sorted(valid_table_names))}" | ||||||||
| ) | ||||||||
|
|
||||||||
| if filter_dict is None: | ||||||||
| filter_dict = {"deleted": False} | ||||||||
| else: | ||||||||
| filter_dict = filter_dict.copy() | ||||||||
| filter_dict["deleted"] = False | ||||||||
|
|
||||||||
| body: dict[str, Any] = {} | ||||||||
| if cursor is not None: | ||||||||
| body["cursor"] = cursor | ||||||||
|
|
||||||||
| body["filter"] = filter_dict | ||||||||
| if limit is not None: | ||||||||
| body["limit"] = limit | ||||||||
| if offset is not None: | ||||||||
| body["offset"] = offset | ||||||||
| if select is not None: | ||||||||
| body["select"] = select | ||||||||
| if sort is not None: | ||||||||
| body["sort"] = sort | ||||||||
|
|
||||||||
| return self._c.post_json( | ||||||||
| f"/data-platform/{self._c.org_key}/{entity}/search", | ||||||||
| body=body, | ||||||||
| ) | ||||||||
|
|
||||||||
| def search_ligands( | ||||||||
| self, | ||||||||
| *, | ||||||||
| cursor: str | None = None, | ||||||||
| filter: dict[str, Any] | None = None, | ||||||||
| min_molecular_weight: float | int | None = None, | ||||||||
| max_molecular_weight: float | int | None = None, | ||||||||
| limit: int | None = None, | ||||||||
| offset: int | None = None, | ||||||||
| select: list[str] | None = None, | ||||||||
| sort: dict[str, str] | None = None, | ||||||||
| ) -> dict: | ||||||||
| """Search ligands entity. | ||||||||
|
|
||||||||
| Convenience method that calls search(entity="ligands"). | ||||||||
|
|
||||||||
| Args: | ||||||||
| cursor: Cursor for pagination. | ||||||||
| filter: Additional filter criteria as a dictionary. | ||||||||
| min_molecular_weight: Minimum molecular weight filter (inclusive). | ||||||||
| max_molecular_weight: Maximum molecular weight filter (inclusive). | ||||||||
| limit: Maximum number of results to return. Defaults to 100. | ||||||||
| offset: Number of results to skip. | ||||||||
| select: List of fields to select in the response. | ||||||||
| sort: Dictionary mapping field names to sort order ("asc" or "desc"). | ||||||||
|
|
||||||||
| Returns: | ||||||||
| Dictionary containing the search results. | ||||||||
|
|
||||||||
| Raises: | ||||||||
| ValueError: If ligands is not a valid table name (should not happen). | ||||||||
| """ | ||||||||
| # Build filter dict, starting with provided filter or empty dict | ||||||||
| filter_dict = filter.copy() if filter is not None else {} | ||||||||
| filter_dict.setdefault("deleted", False) | ||||||||
|
||||||||
| filter_dict.setdefault("deleted", False) | |
| # Ensure deleted records are excluded consistently with other search methods | |
| filter_dict["deleted"] = False |
Copilot
AI
Feb 3, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The search_proteins method does not accept a filter parameter like search_ligands does (line 157). Users cannot pass custom filters to search_proteins, which limits flexibility. Consider adding a filter parameter to maintain consistency with search_ligands and allow users to specify custom filter criteria beyond the convenience parameters (pdb_id, molecular_weight, sequence).
Uh oh!
There was an error while loading. Please reload this page.