mgbam commited on
Commit
df8495c
·
verified ·
1 Parent(s): 4d349c5

Update api_clients/clinicaltrials_client.py

Browse files
api_clients/clinicaltrials_client.py CHANGED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # api_clients/clinicaltrials_client.py
2
+ """
3
+ Client for the ClinicalTrials.gov API (Version 2).
4
+ This client is optimized to find active, recruiting studies for a given condition,
5
+ which is the most relevant information for patients and caregivers.
6
+ """
7
+ import aiohttp
8
+ from urllib.parse import quote_plus
9
+ from .config import CLINICALTRIALS_BASE_URL, REQUEST_HEADERS
10
+
11
+ async def find_trials(session: aiohttp.ClientSession, condition_query: str, max_results: int = 5) -> list[dict]:
12
+ """
13
+ Searches ClinicalTrials.gov for active, recruiting studies related to a condition.
14
+
15
+ Args:
16
+ session (aiohttp.ClientSession): The active HTTP session.
17
+ condition_query (str): The medical condition to search for (e.g., "Type 2 Diabetes").
18
+ max_results (int): The maximum number of trial results to return.
19
+
20
+ Returns:
21
+ list[dict]: A list of dictionaries, where each dictionary represents a clinical trial.
22
+ Returns an empty list if no trials are found or an error occurs.
23
+ """
24
+ if not condition_query:
25
+ return []
26
+
27
+ # The API is powerful. We will specifically query for trials that are currently recruiting,
28
+ # as this is the most actionable information for a user.
29
+ # The `quote_plus` function ensures the query is safely encoded for the URL.
30
+ formatted_query = quote_plus(condition_query)
31
+
32
+ # Construct the query parameters
33
+ params = {
34
+ 'query.term': formatted_query,
35
+ 'filter.overallStatus': 'RECRUITING', # The "wow" factor: finding ACTIONABLE trials
36
+ 'pageSize': max_results,
37
+ 'format': 'json'
38
+ }
39
+
40
+ url = f"{CLINICALTRIALS_BASE_URL}/studies"
41
+
42
+ try:
43
+ async with session.get(url, params=params, headers=REQUEST_HEADERS, timeout=15) as resp:
44
+ # Raise an exception for bad status codes (4xx or 5xx)
45
+ resp.raise_for_status()
46
+ data = await resp.json()
47
+
48
+ studies_list = data.get('studies', [])
49
+ if not studies_list:
50
+ return []
51
+
52
+ # Parse the complex response into a simple, clean list of dictionaries
53
+ parsed_trials = []
54
+ for study in studies_list:
55
+ # Use nested .get() calls to safely access potentially missing keys
56
+ protocol = study.get('protocolSection', {})
57
+ id_module = protocol.get('identificationModule', {})
58
+ status_module = protocol.get('statusModule', {})
59
+
60
+ nct_id = id_module.get('nctId', '')
61
+ if not nct_id:
62
+ continue # Skip if the trial has no ID
63
+
64
+ parsed_trials.append({
65
+ "title": id_module.get('briefTitle', 'Title Not Available'),
66
+ "nct_id": nct_id,
67
+ "status": status_module.get('overallStatus', 'Status Unknown'),
68
+ "url": f"https://clinicaltrials.gov/study/{nct_id}",
69
+ "condition": ", ".join(protocol.get('conditionsModule', {}).get('conditions', ['N/A'])),
70
+ "intervention": ", ".join(i.get('name', 'N/A') for i in protocol.get('armsAndInterventionsModule', {}).get('interventions', []))
71
+ })
72
+
73
+ return parsed_trials
74
+
75
+ except aiohttp.ClientError as e:
76
+ print(f"An error occurred while fetching data from ClinicalTrials.gov: {e}")
77
+ return []
78
+ except Exception as e:
79
+ print(f"A general error occurred in the clinicaltrials_client: {e}")
80
+ return []