Source code for tooluniverse.swisslipids_tool

"""
SwissLipids tool for ToolUniverse.

SwissLipids (swisslipids.org, maintained by the SIB Swiss Institute of
Bioinformatics) is a curated knowledge resource for lipids. It organises
lipids into a structural hierarchy (class -> species -> subspecies) and links
each entry to formula, monoisotopic mass, adduct m/z values (useful for
lipidomics MS), cross-references (ChEBI, HMDB, LIPID MAPS, Rhea, MetaNetX),
and reactions.

It is complementary to the existing LIPID MAPS tools — a different
organisation's independently curated lipid database, with its own hierarchy
and the adduct-m/z table that LIPID MAPS does not provide.

API: https://www.swisslipids.org/api/index.php (public, no key).
"""

from typing import Any, Dict, List

import requests

from .base_tool import BaseTool
from .tool_registry import register_tool

SWISSLIPIDS_API = "https://www.swisslipids.org/api/index.php"


[docs] @register_tool("SwissLipidsTool") class SwissLipidsTool(BaseTool): """Search SwissLipids and retrieve lipid entries (SIB)."""
[docs] def __init__(self, tool_config: Dict[str, Any]): super().__init__(tool_config) self.timeout: int = tool_config.get("timeout", 30) self.operation: str = tool_config.get("fields", {}).get("operation", "search")
[docs] def run(self, arguments: Dict[str, Any]) -> Dict[str, Any]: operation = arguments.get("operation") or self.operation if operation == "search": return self._search(arguments) if operation == "get_lipid": return self._get_lipid(arguments) return { "status": "error", "error": f"Unknown operation: {operation}. Supported: search, get_lipid.", }
[docs] def _request(self, path: str, params: Dict[str, Any] | None = None): try: resp = requests.get( f"{SWISSLIPIDS_API}/{path}", params=params or {}, headers={"Accept": "application/json"}, timeout=self.timeout, ) except requests.Timeout: return None, { "status": "error", "error": f"SwissLipids request timed out after {self.timeout}s.", } except requests.exceptions.RequestException as e: return None, { "status": "error", "error": f"Failed to reach SwissLipids: {str(e)}", } if resp.status_code != 200: return None, { "status": "error", "error": f"SwissLipids returned HTTP {resp.status_code}", "detail": resp.text[:300], } try: return resp.json(), None except ValueError: return None, { "status": "error", "error": "SwissLipids returned a non-JSON response.", }
[docs] def _get_lipid(self, arguments: Dict[str, Any]) -> Dict[str, Any]: entity_id = arguments.get("entity_id") or arguments.get("slm_id") if not entity_id or not str(entity_id).strip(): return { "status": "error", "error": "Parameter 'entity_id' is required (a SwissLipids id, e.g. 'SLM:000000510').", } entity_id = str(entity_id).strip() if not entity_id.upper().startswith("SLM:"): entity_id = f"SLM:{entity_id}" body, err = self._request(f"entity/{entity_id}") if err: # The entity endpoint returns HTTP 500 for non-existent or malformed # ids, so translate any HTTP error into an actionable not-found. if "HTTP" in err.get("error", ""): return { "status": "error", "error": f"No SwissLipids entry for '{entity_id}' (it may not exist " "or the id is malformed). Find valid ids with SwissLipids_search.", } return err entry = body[0] if isinstance(body, list) and body else body if not isinstance(entry, dict) or not entry.get("entity_id"): return { "status": "error", "error": f"No SwissLipids entry found for {entity_id}.", } chem = entry.get("chemical_data") or {} xrefs: List[Dict[str, Any]] = [ {"source": x.get("source"), "id": x.get("id"), "url": x.get("url")} for x in (entry.get("xrefs") or []) if x.get("id") ] synonyms = [ s.get("name") for s in (entry.get("synonyms") or []) if s.get("name") ] classification = [] for c in entry.get("classification") or []: if isinstance(c, dict): name = c.get("entity_name") or c.get("name") if name: classification.append(name) return { "status": "success", "data": { "entity_id": entry.get("entity_id"), "entity_name": entry.get("entity_name"), "entity_type": entry.get("entity_type"), "formula": chem.get("formula"), "mass": chem.get("mass"), "charge": chem.get("charge"), "adduct_mz": chem.get("mz"), "classification": classification, "synonyms": synonyms, "xrefs": xrefs, }, "metadata": {"source": "SwissLipids (swisslipids.org, SIB)"}, }