Source code for tooluniverse.omim_tool
"""
OMIM (Online Mendelian Inheritance in Man) API tool for ToolUniverse.
OMIM is a comprehensive database of human genes and genetic disorders,
with particular emphasis on the molecular relationships between genetic
variation and phenotypic expression.
API Documentation: https://omim.org/help/api
Requires API key: https://omim.org/api
"""
import os
import requests
from typing import Dict, Any, Optional, List
from .base_tool import BaseTool
from .tool_registry import register_tool
# Base URL for OMIM API
OMIM_API_URL = "https://api.omim.org/api"
[docs]
@register_tool("OMIMTool")
class OMIMTool(BaseTool):
"""
Tool for querying OMIM (Online Mendelian Inheritance in Man).
OMIM provides:
- Mendelian disease information
- Gene-disease relationships
- Clinical synopses
- Inheritance patterns
Requires API key via OMIM_API_KEY environment variable.
Register at https://omim.org/api for free academic access.
"""
[docs]
def __init__(self, tool_config: Dict[str, Any]):
super().__init__(tool_config)
self.timeout: int = tool_config.get("timeout", 30)
self.parameter = tool_config.get("parameter", {})
self.api_key = os.environ.get("OMIM_API_KEY", "")
[docs]
def _get_params(self, extra_params: Dict = None) -> Dict[str, Any]:
"""Get base parameters with API key."""
params = {"apiKey": self.api_key, "format": "json"}
if extra_params:
params.update(extra_params)
return params
[docs]
def run(self, arguments: Dict[str, Any]) -> Dict[str, Any]:
"""Execute OMIM API call based on operation type."""
if not self.api_key:
return {
"status": "error",
"error": "OMIM API key required. Set OMIM_API_KEY environment variable. Register at https://omim.org/api",
}
operation = arguments.get("operation", "")
if operation == "search":
return self._search(arguments)
elif operation == "get_entry":
return self._get_entry(arguments)
elif operation == "get_gene_map":
return self._get_gene_map(arguments)
elif operation == "get_clinical_synopsis":
return self._get_clinical_synopsis(arguments)
else:
return {
"status": "error",
"error": f"Unknown operation: {operation}. Supported: search, get_entry, get_gene_map, get_clinical_synopsis",
}
[docs]
def _search(self, arguments: Dict[str, Any]) -> Dict[str, Any]:
"""
Search OMIM entries.
Args:
arguments: Dict containing:
- query: Search terms (gene name, disease name, phenotype)
- limit: Maximum results (default 10, max 20)
- start: Offset for pagination (default 0)
"""
query = arguments.get("query", "")
if not query:
return {"status": "error", "error": "Missing required parameter: query"}
limit = min(arguments.get("limit", 10), 20)
start = arguments.get("start", 0)
params = self._get_params(
{
"search": query,
"limit": limit,
"start": start,
"include": "all",
}
)
try:
response = requests.get(
f"{OMIM_API_URL}/entry/search",
params=params,
timeout=self.timeout,
headers={"User-Agent": "ToolUniverse/OMIM"},
)
response.raise_for_status()
data = response.json()
# Parse OMIM response
omim_data = data.get("omim", {})
search_response = omim_data.get("searchResponse", {})
return {
"status": "success",
"data": {
"total_results": search_response.get("totalResults", 0),
"start": search_response.get("startIndex", 0),
"entries": search_response.get("entryList", []),
},
"metadata": {
"source": "OMIM",
"query": query,
},
}
except requests.exceptions.HTTPError as e:
if e.response.status_code == 401:
return {"status": "error", "error": "Invalid API key"}
return {"status": "error", "error": f"HTTP error: {e.response.status_code}"}
except requests.exceptions.RequestException as e:
return {"status": "error", "error": f"Request failed: {str(e)}"}
except Exception as e:
return {"status": "error", "error": f"Unexpected error: {str(e)}"}
[docs]
def _get_entry(self, arguments: Dict[str, Any]) -> Dict[str, Any]:
"""
Get OMIM entry by MIM number.
Args:
arguments: Dict containing:
- mim_number: OMIM MIM number (e.g., 164730 for BRAF)
- include: Data to include (default: all basic data)
"""
mim_number = arguments.get("mim_number", "")
if not mim_number:
return {
"status": "error",
"error": "Missing required parameter: mim_number",
}
# Clean MIM number (remove any prefix)
mim_number = str(mim_number).replace("OMIM:", "").replace("MIM:", "").strip()
include = arguments.get("include", "text,clinicalSynopsis,geneMap")
params = self._get_params(
{
"mimNumber": mim_number,
"include": include,
}
)
try:
response = requests.get(
f"{OMIM_API_URL}/entry",
params=params,
timeout=self.timeout,
headers={"User-Agent": "ToolUniverse/OMIM"},
)
response.raise_for_status()
data = response.json()
omim_data = data.get("omim", {})
entry_list = omim_data.get("entryList", [])
if entry_list:
entry = entry_list[0].get("entry", {})
return {
"status": "success",
"data": entry,
"metadata": {
"source": "OMIM",
"mim_number": mim_number,
},
}
else:
return {
"status": "error",
"error": f"No entry found for MIM: {mim_number}",
}
except requests.exceptions.HTTPError as e:
return {"status": "error", "error": f"HTTP error: {e.response.status_code}"}
except requests.exceptions.RequestException as e:
return {"status": "error", "error": f"Request failed: {str(e)}"}
except Exception as e:
return {"status": "error", "error": f"Unexpected error: {str(e)}"}
[docs]
def _get_gene_map(self, arguments: Dict[str, Any]) -> Dict[str, Any]:
"""
Get gene-disease mapping information.
Args:
arguments: Dict containing:
- mim_number: OMIM MIM number for gene or phenotype
OR
- chromosome: Chromosome number (1-22, X, Y)
"""
mim_number = arguments.get("mim_number", "")
chromosome = arguments.get("chromosome", "")
if not mim_number and not chromosome:
return {
"status": "error",
"error": "Either mim_number or chromosome required",
}
params = self._get_params({})
if mim_number:
mim_number = (
str(mim_number).replace("OMIM:", "").replace("MIM:", "").strip()
)
params["mimNumber"] = mim_number
else:
params["chromosome"] = str(chromosome)
params["limit"] = min(arguments.get("limit", 50), 100)
try:
response = requests.get(
f"{OMIM_API_URL}/geneMap",
params=params,
timeout=self.timeout,
headers={"User-Agent": "ToolUniverse/OMIM"},
)
response.raise_for_status()
data = response.json()
omim_data = data.get("omim", {})
gene_map_list = omim_data.get("geneMapList", [])
return {
"status": "success",
"data": {
"gene_maps": gene_map_list,
"count": len(gene_map_list),
},
"metadata": {
"source": "OMIM Gene Map",
"mim_number": mim_number if mim_number else None,
"chromosome": chromosome if chromosome else None,
},
}
except requests.exceptions.RequestException as e:
return {"status": "error", "error": f"Request failed: {str(e)}"}
except Exception as e:
return {"status": "error", "error": f"Unexpected error: {str(e)}"}
[docs]
def _get_clinical_synopsis(self, arguments: Dict[str, Any]) -> Dict[str, Any]:
"""
Get clinical synopsis (phenotype features) for an OMIM entry.
Args:
arguments: Dict containing:
- mim_number: OMIM MIM number for a phenotype entry
"""
mim_number = arguments.get("mim_number", "")
if not mim_number:
return {
"status": "error",
"error": "Missing required parameter: mim_number",
}
mim_number = str(mim_number).replace("OMIM:", "").replace("MIM:", "").strip()
params = self._get_params(
{
"mimNumber": mim_number,
"include": "clinicalSynopsis",
}
)
try:
response = requests.get(
f"{OMIM_API_URL}/clinicalSynopsis",
params=params,
timeout=self.timeout,
headers={"User-Agent": "ToolUniverse/OMIM"},
)
response.raise_for_status()
data = response.json()
omim_data = data.get("omim", {})
synopsis_list = omim_data.get("clinicalSynopsisList", [])
if synopsis_list:
synopsis = synopsis_list[0].get("clinicalSynopsis", {})
return {
"status": "success",
"data": synopsis,
"metadata": {
"source": "OMIM Clinical Synopsis",
"mim_number": mim_number,
},
}
else:
return {
"status": "error",
"error": f"No clinical synopsis for MIM: {mim_number}",
}
except requests.exceptions.RequestException as e:
return {"status": "error", "error": f"Request failed: {str(e)}"}
except Exception as e:
return {"status": "error", "error": f"Unexpected error: {str(e)}"}