File size: 2,689 Bytes
1c6cb4b
7b3f817
cdc75a8
98d71a3
1c6cb4b
98d71a3
 
 
1087a21
98d71a3
 
a9daa10
98d71a3
 
1087a21
98d71a3
1087a21
98d71a3
cdc75a8
98d71a3
 
 
7b3f817
a9daa10
98d71a3
a9daa10
98d71a3
a9daa10
98d71a3
cdc75a8
 
1c6cb4b
7b3f817
98d71a3
1087a21
98d71a3
1087a21
cdc75a8
98d71a3
 
 
 
cdc75a8
98d71a3
 
 
 
 
 
 
 
 
 
 
 
 
a9daa10
98d71a3
 
a9daa10
cdc75a8
98d71a3
 
 
cdc75a8
98d71a3
7b3f817
 
98d71a3
7b3f817
98d71a3
7b3f817
98d71a3
 
 
 
 
 
cdc75a8
 
98d71a3
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# genesis/api_clients/umls_api.py
import os
import requests
from typing import Dict, List, Optional

# UMLS API
UMLS_BASE = "https://uts-ws.nlm.nih.gov/rest"
UMLS_API_KEY = os.getenv("UMLS_API_KEY")  # Add this to your Hugging Face secrets or .env

if not UMLS_API_KEY:
    raise EnvironmentError("UMLS_API_KEY is missing. Add it to your environment variables or Hugging Face secrets.")

# UMLS requires ticket-granting service for authentication
def get_tgt() -> str:
    """
    Obtain a Ticket Granting Ticket (TGT) for UMLS authentication.
    """
    r = requests.post("https://utslogin.nlm.nih.gov/cas/v1/api-key", data={"apikey": UMLS_API_KEY})
    r.raise_for_status()
    from xml.etree import ElementTree
    root = ElementTree.fromstring(r.text)
    return root.attrib.get("action")


def get_service_ticket(tgt: str) -> str:
    """
    Get a single-use service ticket for API requests.
    """
    r = requests.post(tgt, data={"service": "http://umlsks.nlm.nih.gov"})
    r.raise_for_status()
    return r.text


def search_umls(query: str, max_results: int = 10) -> List[Dict]:
    """
    Search UMLS Metathesaurus for a term and return CUIs and names.
    """
    tgt = get_tgt()
    ticket = get_service_ticket(tgt)
    params = {"string": query, "ticket": ticket, "pageSize": max_results}
    
    r = requests.get(f"{UMLS_BASE}/search/current", params=params)
    r.raise_for_status()
    results = r.json().get("result", {}).get("results", [])
    
    return [
        {
            "ui": item.get("ui"),
            "name": item.get("name"),
            "rootSource": item.get("rootSource")
        }
        for item in results if item.get("ui") != "NONE"
    ]


def get_concept_details(cui: str) -> Dict:
    """
    Get full details for a given CUI (Concept Unique Identifier).
    Includes synonyms, definitions, and mappings.
    """
    tgt = get_tgt()
    ticket = get_service_ticket(tgt)
    
    r = requests.get(f"{UMLS_BASE}/content/current/CUI/{cui}", params={"ticket": ticket})
    r.raise_for_status()
    return r.json().get("result", {})


def map_between_ontologies(cui: str) -> List[Dict]:
    """
    Given a CUI, return cross-ontology mappings (e.g., SNOMED β†’ MeSH β†’ ICD).
    """
    tgt = get_tgt()
    ticket = get_service_ticket(tgt)
    
    r = requests.get(f"{UMLS_BASE}/crosswalk/current/source/{cui}", params={"ticket": ticket})
    r.raise_for_status()
    return r.json().get("result", [])


def normalize_term(term: str) -> Optional[Dict]:
    """
    Normalize a free-text biomedical term to its canonical CUI and return metadata.
    """
    matches = search_umls(term, max_results=1)
    return matches[0] if matches else None