File size: 12,161 Bytes
f368eec
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
"""Drug-Drug Interaction Processor for analyzing and processing drug interactions."""

import re
import networkx as nx
import matplotlib.pyplot as plt
from typing import List, Dict, Tuple, Optional

from .biomedical_llm import BiomedicalLLM
from .drug_interaction_db import DrugInteractionDatabase

class DDIProcessor:
    def __init__(self, db: DrugInteractionDatabase, bio_llm: BiomedicalLLM):
        self.db = db
        self.bio_llm = bio_llm
    
    def extract_drug_names(self, text):
        """Extract potential drug names from text using NLP techniques"""
        # In a real implementation, this would use advanced NLP
        # For now, we'll use a simple approach based on keywords and patterns
        
        # Clean and standardize text
        text = text.lower()
        
        # Common question patterns
        patterns = [
            r"can\s+i\s+take\s+(.+?)\s+(?:and|with|along\s+with)\s+(.+?)(?:\?|$)",
            r"is\s+it\s+safe\s+to\s+take\s+(.+?)\s+(?:and|with|along\s+with)\s+(.+?)(?:\?|$)",
            r"(?:interaction|interactions)\s+between\s+(.+?)\s+and\s+(.+?)(?:\?|$)",
            r"(?:will|does|do)\s+(.+?)\s+(?:interact|interfere)\s+with\s+(.+?)(?:\?|$)"
        ]
        
        for pattern in patterns:
            match = re.search(pattern, text)
            if match:
                drug1 = match.group(1).strip()
                drug2 = match.group(2).strip()
                return drug1, drug2
                
        # If no pattern matches, try to find drug names from the database
        words = text.split()
        potential_drugs = []
        
        for word in words:
            word = word.strip(".,?!()[]{}\"'")
            if self.db.search_drug(word):
                potential_drugs.append(word)
        
        if len(potential_drugs) >= 2:
            return potential_drugs[0], potential_drugs[1]
        
        return None, None
    
    def extract_drugs_from_clinical_notes(self, clinical_text):
        """Use BiomedLM to extract drugs from clinical notes"""
        try:
            # Use the biomedical LLM to extract drugs and interactions
            result = self.bio_llm.analyze_clinical_notes(clinical_text)
            
            # Return the extracted medications
            return result
        except Exception as e:
            print(f"Error extracting drugs from clinical notes: {e}")
            return {"medications": [], "potential_interactions": []}
    
    def process_query(self, query):
        """Process a natural language query about drug interactions"""
        drug1, drug2 = self.extract_drug_names(query)
        
        # If we couldn't extract drug names
        if not drug1 or not drug2:
            return {
                "status": "error",
                "message": "I couldn't identify the drugs in your question. Please specify the drugs clearly, for example: 'Can I take aspirin and warfarin together?'"
            }
        
        # Get drug interactions from database
        interactions, missing = self.db.get_interactions(drug1, drug2)
        
        # Try biomedical LLM for additional information, especially if not in database
        try:
            literature_info = self.bio_llm.extract_ddi_from_literature(drug1, drug2)
            if "interactions" in literature_info and literature_info["interactions"]:
                # Convert LLM information to the format used by the database
                for interaction in literature_info["interactions"]:
                    # Only add if we don't already have interactions from the database
                    if not interactions:
                        canonical1 = self.db.search_drug(drug1) or drug1
                        canonical2 = self.db.search_drug(drug2) or drug2
                        desc = interaction.get("description", f"Potential interaction between {drug1} and {drug2}")
                        severity = interaction.get("severity", "Unknown")
                        source = interaction.get("evidence", "Biomedical literature analysis")
                        
                        interactions.append((canonical1, canonical2, desc, severity, source))
                        
                # Clear missing drugs if LLM found information
                if missing and interactions:
                    missing = []
        except Exception as e:
            print(f"Error getting additional information: {e}")
        
        # If drugs weren't found
        if missing:
            return {
                "status": "not_found",
                "missing_drugs": missing,
                "message": f"I couldn't find information on the following drug(s): {', '.join(missing)}"
            }
        
        # Format the results
        canonical1 = self.db.search_drug(drug1) or drug1
        canonical2 = self.db.search_drug(drug2) or drug2
        
        if not interactions:
            return {
                "status": "no_interaction",
                "drugs": [canonical1, canonical2],
                "message": f"No known interactions were found between {canonical1} and {canonical2} in our database or medical literature. However, please consult with a healthcare professional for personalized advice."
            }
        
        # Format the interaction information
        interaction_details = []
        for d1, d2, desc, severity, source in interactions:
            interaction_details.append({
                "description": desc,
                "severity": severity,
                "source": source
            })
        
        return {
            "status": "found",
            "drugs": [canonical1, canonical2],
            "interactions": interaction_details
        }
    
    def get_drug_information(self, drug_name):
        """Get comprehensive information about a drug using biomedical LLM"""
        try:
            # First check if the drug exists in our database
            canonical = self.db.search_drug(drug_name)
            
            if not canonical:
                # If not in database, use just the provided name
                canonical = drug_name
            
            # Use biomedical LLM to get drug information
            drug_info = self.bio_llm.get_drug_information(canonical)
            
            # Add interactions from our database
            interactions, _ = self.db.get_all_interactions(canonical)
            interaction_drugs = []
            
            for d1, d2, _, severity, _ in interactions:
                other_drug = d2 if d1 == canonical else d1
                interaction_drugs.append(f"{other_drug} ({severity})")
            
            # Add to the drug information
            if interaction_drugs and "common_interactions" in drug_info:
                # Combine with LLM-provided interactions
                existing = drug_info["common_interactions"]
                if existing and existing[0] != "Information not available":
                    drug_info["common_interactions"] = list(set(existing + interaction_drugs))
                else:
                    drug_info["common_interactions"] = interaction_drugs
            
            return drug_info
            
        except Exception as e:
            print(f"Error getting drug information: {e}")
            return {
                "drug_name": drug_name,
                "drug_class": "Information not available",
                "mechanism": "Information not available",
                "indications": ["Information not available"],
                "side_effects": ["Information not available"],
                "common_interactions": ["Information not available"],
                "contraindications": ["Information not available"]
            }
    
    def generate_network(self, drug_name=None, depth=1):
        """

        Generate a network visualization of drug interactions

        If drug_name is provided, show interactions for that drug

        Otherwise, show a general interaction network

        """
        G = nx.Graph()
        
        # If a specific drug is provided
        if drug_name:
            canonical = self.db.search_drug(drug_name)
            if not canonical:
                return None, f"Drug '{drug_name}' not found"
            
            # Get interactions for this drug
            interactions, _ = self.db.get_all_interactions(canonical)
            
            # Add nodes and edges
            G.add_node(canonical, size=20, color='red')
            
            for drug1, drug2, desc, severity, _ in interactions:
                other_drug = drug2 if drug1 == canonical else drug1
                
                # Add nodes and edges
                if other_drug not in G:
                    G.add_node(other_drug, size=15, color='blue')
                
                # Set edge color based on severity
                if severity == "Severe":
                    edge_color = 'red'
                    weight = 3
                elif severity == "Moderate":
                    edge_color = 'orange'
                    weight = 2
                else:
                    edge_color = 'yellow'
                    weight = 1
                    
                G.add_edge(canonical, other_drug, color=edge_color, weight=weight, label=desc)
                
                # If depth > 1, add secondary interactions
                if depth > 1:
                    secondary_interactions, _ = self.db.get_all_interactions(other_drug)
                    for sec_d1, sec_d2, sec_desc, sec_severity, _ in secondary_interactions:
                        tertiary_drug = sec_d2 if sec_d1 == other_drug else sec_d1
                        
                        # Skip the original drug
                        if tertiary_drug == canonical:
                            continue
                        
                        if tertiary_drug not in G:
                            G.add_node(tertiary_drug, size=10, color='green')
                        
                        # Set edge color based on severity
                        if sec_severity == "Severe":
                            sec_edge_color = 'red'
                            sec_weight = 3
                        elif sec_severity == "Moderate":
                            sec_edge_color = 'orange'
                            sec_weight = 2
                        else:
                            sec_edge_color = 'yellow'
                            sec_weight = 1
                            
                        G.add_edge(other_drug, tertiary_drug, color=sec_edge_color, weight=sec_weight, label=sec_desc)
        else:
            # Create a general interaction network with common drugs
            sample_drugs = self.db.get_all_drugs()[:10]  # Limit to 10 drugs for clarity
            
            for drug in sample_drugs:
                G.add_node(drug, size=15, color='blue')
                
                interactions, _ = self.db.get_all_interactions(drug)
                for d1, d2, desc, severity, _ in interactions:
                    other_drug = d2 if d1 == drug else d1
                    
                    # Only add edges between drugs in our sample
                    if other_drug in sample_drugs:
                        # Set edge color based on severity
                        if severity == "Severe":
                            edge_color = 'red'
                            weight = 3
                        elif severity == "Moderate":
                            edge_color = 'orange'
                            weight = 2
                        else:
                            edge_color = 'yellow'
                            weight = 1
                            
                        G.add_edge(drug, other_drug, color=edge_color, weight=weight, label=desc)
        
        return G, None