mgbam commited on
Commit
98d71a3
Β·
verified Β·
1 Parent(s): 7bfdf8c

Update genesis/api_clients/umls_api.py

Browse files
Files changed (1) hide show
  1. genesis/api_clients/umls_api.py +55 -62
genesis/api_clients/umls_api.py CHANGED
@@ -1,93 +1,86 @@
1
  # genesis/api_clients/umls_api.py
2
  import os
3
  import requests
 
4
 
5
- UMLS_API_KEY = os.getenv("UMLS_API_KEY")
6
- UMLS_AUTH_ENDPOINT = "https://utslogin.nlm.nih.gov/cas/v1/api-key"
7
- UMLS_BASE_URL = "https://uts-ws.nlm.nih.gov/rest"
8
 
 
 
9
 
10
- def get_tgt():
 
11
  """
12
- Get Ticket-Granting Ticket (TGT) for UMLS API authentication.
13
  """
14
- params = {"apikey": UMLS_API_KEY}
15
- r = requests.post(UMLS_AUTH_ENDPOINT, data=params)
16
  r.raise_for_status()
 
 
 
17
 
18
- # Extract TGT from HTML response
19
- tgt_url = r.text.split('action="')[1].split('"')[0]
20
- return tgt_url
21
 
22
-
23
- def get_service_ticket(tgt):
24
  """
25
- Get Service Ticket (ST) from the TGT for making API requests.
26
  """
27
- params = {"service": "http://umlsks.nlm.nih.gov"}
28
- r = requests.post(tgt, data=params)
29
  r.raise_for_status()
30
  return r.text
31
 
32
 
33
- def search_umls(term: str, max_results: int = 10):
34
  """
35
- Search UMLS for a term and return matching concepts.
36
  """
37
  tgt = get_tgt()
38
- st = get_service_ticket(tgt)
39
-
40
- url = f"{UMLS_BASE_URL}/search/current"
41
- params = {"string": term, "ticket": st, "pageSize": max_results}
42
- r = requests.get(url, params=params)
43
  r.raise_for_status()
44
-
45
- data = r.json()
46
- results = []
47
-
48
- for result in data.get("result", {}).get("results", []):
49
- results.append({
50
- "ui": result.get("ui", ""),
51
- "name": result.get("name", ""),
52
- "rootSource": result.get("rootSource", "")
53
- })
54
-
55
- return results
56
-
57
-
58
- def get_concept_details(cui: str):
59
  """
60
- Retrieve detailed information for a concept by CUI (Concept Unique Identifier).
 
61
  """
62
  tgt = get_tgt()
63
- st = get_service_ticket(tgt)
64
-
65
- url = f"{UMLS_BASE_URL}/content/current/CUI/{cui}"
66
- params = {"ticket": st}
67
- r = requests.get(url, params=params)
68
  r.raise_for_status()
69
- return r.json()
70
 
71
 
72
- def map_related_concepts(term: str):
73
  """
74
- Search UMLS and map related concepts with synonyms and semantic types.
75
  """
76
- concepts = search_umls(term, max_results=5)
77
- mapped = []
78
-
79
- for c in concepts:
80
- cui = c["ui"]
81
- if cui and cui != "NONE":
82
- details = get_concept_details(cui)
83
- entity = details.get("result", {})
84
 
85
- mapped.append({
86
- "cui": cui,
87
- "name": entity.get("name", ""),
88
- "synonyms": [syn.get("name", "") for syn in entity.get("atoms", [])],
89
- "semantic_types": [st.get("name", "") for st in entity.get("semanticTypes", [])],
90
- "rootSource": c.get("rootSource", "")
91
- })
92
 
93
- return mapped
 
 
 
 
 
 
1
  # genesis/api_clients/umls_api.py
2
  import os
3
  import requests
4
+ from typing import Dict, List, Optional
5
 
6
+ # UMLS API
7
+ UMLS_BASE = "https://uts-ws.nlm.nih.gov/rest"
8
+ UMLS_API_KEY = os.getenv("UMLS_API_KEY") # Add this to your Hugging Face secrets or .env
9
 
10
+ if not UMLS_API_KEY:
11
+ raise EnvironmentError("UMLS_API_KEY is missing. Add it to your environment variables or Hugging Face secrets.")
12
 
13
+ # UMLS requires ticket-granting service for authentication
14
+ def get_tgt() -> str:
15
  """
16
+ Obtain a Ticket Granting Ticket (TGT) for UMLS authentication.
17
  """
18
+ r = requests.post("https://utslogin.nlm.nih.gov/cas/v1/api-key", data={"apikey": UMLS_API_KEY})
 
19
  r.raise_for_status()
20
+ from xml.etree import ElementTree
21
+ root = ElementTree.fromstring(r.text)
22
+ return root.attrib.get("action")
23
 
 
 
 
24
 
25
+ def get_service_ticket(tgt: str) -> str:
 
26
  """
27
+ Get a single-use service ticket for API requests.
28
  """
29
+ r = requests.post(tgt, data={"service": "http://umlsks.nlm.nih.gov"})
 
30
  r.raise_for_status()
31
  return r.text
32
 
33
 
34
+ def search_umls(query: str, max_results: int = 10) -> List[Dict]:
35
  """
36
+ Search UMLS Metathesaurus for a term and return CUIs and names.
37
  """
38
  tgt = get_tgt()
39
+ ticket = get_service_ticket(tgt)
40
+ params = {"string": query, "ticket": ticket, "pageSize": max_results}
41
+
42
+ r = requests.get(f"{UMLS_BASE}/search/current", params=params)
 
43
  r.raise_for_status()
44
+ results = r.json().get("result", {}).get("results", [])
45
+
46
+ return [
47
+ {
48
+ "ui": item.get("ui"),
49
+ "name": item.get("name"),
50
+ "rootSource": item.get("rootSource")
51
+ }
52
+ for item in results if item.get("ui") != "NONE"
53
+ ]
54
+
55
+
56
+ def get_concept_details(cui: str) -> Dict:
 
 
57
  """
58
+ Get full details for a given CUI (Concept Unique Identifier).
59
+ Includes synonyms, definitions, and mappings.
60
  """
61
  tgt = get_tgt()
62
+ ticket = get_service_ticket(tgt)
63
+
64
+ r = requests.get(f"{UMLS_BASE}/content/current/CUI/{cui}", params={"ticket": ticket})
 
 
65
  r.raise_for_status()
66
+ return r.json().get("result", {})
67
 
68
 
69
+ def map_between_ontologies(cui: str) -> List[Dict]:
70
  """
71
+ Given a CUI, return cross-ontology mappings (e.g., SNOMED β†’ MeSH β†’ ICD).
72
  """
73
+ tgt = get_tgt()
74
+ ticket = get_service_ticket(tgt)
75
+
76
+ r = requests.get(f"{UMLS_BASE}/crosswalk/current/source/{cui}", params={"ticket": ticket})
77
+ r.raise_for_status()
78
+ return r.json().get("result", [])
 
 
79
 
 
 
 
 
 
 
 
80
 
81
+ def normalize_term(term: str) -> Optional[Dict]:
82
+ """
83
+ Normalize a free-text biomedical term to its canonical CUI and return metadata.
84
+ """
85
+ matches = search_umls(term, max_results=1)
86
+ return matches[0] if matches else None