Source code for tooluniverse.string_tool
"""
STRING Database REST API Tool
This tool provides access to protein-protein interaction data from the STRING
database. STRING is a database of known and predicted protein-protein
interactions.
"""
import requests
from typing import Dict, Any, List
from .base_tool import BaseTool
from .tool_registry import register_tool
STRING_BASE_URL = "https://string-db.org/api"
[docs]
@register_tool("STRINGRESTTool")
class STRINGRESTTool(BaseTool):
"""
STRING Database REST API tool.
Generic wrapper for STRING API endpoints defined in ppi_tools.json.
"""
[docs]
def __init__(self, tool_config):
super().__init__(tool_config)
fields = tool_config.get("fields", {})
parameter = tool_config.get("parameter", {})
self.endpoint_template: str = fields.get("endpoint", "/tsv/network")
self.required: List[str] = parameter.get("required", [])
self.output_format: str = fields.get("return_format", "TSV")
def _build_url(self, arguments: Dict[str, Any]) -> str | Dict[str, Any]:
"""Build URL for STRING API request."""
url_path = self.endpoint_template
return STRING_BASE_URL + url_path
def _build_params(self, arguments: Dict[str, Any]) -> Dict[str, Any]:
"""Build parameters for STRING API request."""
params = {}
# Map protein IDs to STRING format
if "protein_ids" in arguments:
protein_ids = arguments["protein_ids"]
if isinstance(protein_ids, list):
params["identifiers"] = "\r".join(protein_ids)
else:
params["identifiers"] = str(protein_ids)
# Add other parameters
if "species" in arguments:
params["species"] = arguments["species"]
if "confidence_score" in arguments:
params["required_score"] = int(arguments["confidence_score"] * 1000)
if "limit" in arguments:
params["limit"] = arguments["limit"]
if "network_type" in arguments:
params["network_type"] = arguments["network_type"]
return params
def _make_request(self, url: str, params: Dict[str, Any]) -> Dict[str, Any]:
"""Perform a GET request and handle common errors."""
try:
response = requests.get(url, params=params, timeout=30)
response.raise_for_status()
if self.output_format == "TSV":
return self._parse_tsv_response(response.text)
else:
return response.json()
except requests.exceptions.RequestException as e:
return {"error": f"Request failed: {str(e)}"}
except Exception as e:
return {"error": f"Unexpected error: {str(e)}"}
def _parse_tsv_response(self, text: str) -> Dict[str, Any]:
"""Parse TSV response from STRING API."""
lines = text.strip().split("\n")
if len(lines) < 2:
return {"data": [], "error": "No data returned"}
# Parse header
header = lines[0].split("\t")
# Parse data rows
data = []
for line in lines[1:]:
if line.strip():
values = line.split("\t")
row = {}
for i, value in enumerate(values):
if i < len(header):
row[header[i]] = value
data.append(row)
return {"data": data, "header": header}
[docs]
def run(self, arguments: Dict[str, Any]) -> Dict[str, Any]:
"""Execute the tool with given arguments."""
# Validate required parameters
for param in self.required:
if param not in arguments:
return {"error": f"Missing required parameter: {param}"}
url = self._build_url(arguments)
if isinstance(url, dict) and "error" in url:
return url
params = self._build_params(arguments)
return self._make_request(url, params)