Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import pandas as pd | |
| import os | |
| import random | |
| import hashlib | |
| # Check if pubchempy is available | |
| PUBCHEM_AVAILABLE = False | |
| try: | |
| import pubchempy as pcp | |
| PUBCHEM_AVAILABLE = True | |
| print("pubchempy imported successfully.") | |
| except ImportError: | |
| print("Warning: pubchempy not found. PubChem feature extraction will be skipped.") | |
| # Active compound mapping for traditional drugs | |
| DRUG_ACTIVE_COMPOUNDS = { | |
| 'kanna': 'mesembrine', | |
| 'sceletium tortuosum': 'mesembrine', | |
| 'st johns wort': 'hyperforin', | |
| 'st john\'s wort': 'hyperforin', | |
| 'hypericum perforatum': 'hyperforin', | |
| 'yohimbe': 'yohimbine', | |
| 'pausinystalia johimbe': 'yohimbine', | |
| 'kola nut': 'caffeine', | |
| 'cola nitida': 'caffeine', | |
| 'khat': 'cathinone', | |
| 'catha edulis': 'cathinone', | |
| 'kava': 'kavain', | |
| 'piper methysticum': 'kavain', | |
| 'valerian': 'valerenic acid', | |
| 'valeriana officinalis': 'valerenic acid', | |
| 'ashwagandha': 'withanoside iv', | |
| 'withania somnifera': 'withanoside iv', | |
| 'cannabis': 'thc', | |
| 'cannabis sativa': 'thc', | |
| 'licorice': 'glycyrrhizin', | |
| 'glycyrrhiza glabra': 'glycyrrhizin', | |
| 'rauvolfia': 'reserpine', | |
| 'rauvolfia serpentina': 'reserpine', | |
| 'turmeric': 'curcumin', | |
| 'curcuma longa': 'curcumin', | |
| 'ginger': 'gingerol', | |
| 'zingiber officinale': 'gingerol', | |
| 'garlic': 'allicin', | |
| 'allium sativum': 'allicin', | |
| 'feverfew': 'parthenolide', | |
| 'tanacetum parthenium': 'parthenolide', | |
| 'senna': 'sennoside a', | |
| 'cassia angustifolia': 'sennoside a', | |
| 'aloe ferox': 'aloin', | |
| 'ephedra': 'ephedrine', | |
| 'ephedra sinica': 'ephedrine', | |
| 'willow bark': 'salicin', | |
| 'salix alba': 'salicin', | |
| 'echinacea': 'cichoric acid', | |
| 'echinacea purpurea': 'cichoric acid', | |
| 'ginkgo': 'ginkgolide', | |
| 'ginkgo biloba': 'ginkgolide', | |
| 'ginseng': 'ginsenoside', | |
| 'panax ginseng': 'ginsenoside', | |
| 'green tea': 'epigallocatechin gallate', | |
| 'camellia sinensis': 'epigallocatechin gallate' | |
| } | |
| def extract_active_compound(drug_name): | |
| drug_lower = drug_name.lower().strip() | |
| # First check our predefined mapping | |
| if drug_lower in DRUG_ACTIVE_COMPOUNDS: | |
| active_compound = DRUG_ACTIVE_COMPOUNDS[drug_lower] | |
| print(f"Found active compound for {drug_name}: {active_compound}") | |
| return active_compound | |
| # If not in mapping and PubChem is available, try to get synonyms/related compounds | |
| if PUBCHEM_AVAILABLE: | |
| try: | |
| compounds = pcp.get_compounds(drug_name, 'name') | |
| if compounds: | |
| compound = compounds[0] | |
| # Try to get the main active ingredient name | |
| synonyms = compound.synonyms if hasattr(compound, 'synonyms') else [] | |
| if synonyms: | |
| # Look for common active compound patterns in synonyms | |
| for synonym in synonyms[:10]: # Check first 10 synonyms | |
| syn_lower = synonym.lower() | |
| if any(pattern in syn_lower for pattern in ['acid', 'ine', 'ol', 'ide', 'ate']): | |
| print(f"Found potential active compound for {drug_name}: {synonym}") | |
| return synonym.lower() | |
| # If no suitable synonym found, return the canonical name | |
| if hasattr(compound, 'iupac_name') and compound.iupac_name: | |
| return compound.iupac_name.lower() | |
| except Exception as e: | |
| print(f"Error extracting active compound for {drug_name}: {e}") | |
| # If all else fails, return the original drug name (it might already be an active compound) | |
| return drug_lower | |
| # Load your labeled dataset with exact column names | |
| def load_drug_interaction_dataset(): | |
| """Load your labeled drug interaction dataset with exact column names""" | |
| try: | |
| dataset_path = 'merged_cleaned_dataset.csv' | |
| print(f"Looking for dataset: {dataset_path}") | |
| print("Files in directory:", os.listdir('.')) | |
| if not os.path.exists(dataset_path): | |
| print(f"Dataset file {dataset_path} not found!") | |
| return {}, create_fallback_database() # Return empty dict and fallback if file missing | |
| print(f"Loading dataset from: {dataset_path}") | |
| df = pd.read_csv(dataset_path) | |
| print(f"Dataset columns: {df.columns.tolist()}") | |
| print(f"Dataset shape: {df.shape}") | |
| print(f"First few rows:\n{df.head().to_string()}") | |
| interaction_db = {} | |
| count = 0 | |
| for index, row in df.iterrows(): | |
| try: | |
| drug1 = str(row['Drug 1_normalized']).lower().strip() | |
| drug2 = str(row['Drug 2_normalized']).lower().strip() | |
| severity = str(row['severity']).strip() | |
| if (not all([drug1, drug2, severity]) or | |
| drug1 == 'nan' or drug2 == 'nan' or | |
| severity == 'nan' or severity.lower() == 'none'): | |
| continue | |
| severity = severity.capitalize() | |
| if severity == 'No interaction': | |
| severity = 'No Interaction' | |
| interaction_db[(drug1, drug2)] = severity | |
| interaction_db[(drug2, drug1)] = severity | |
| count += 1 | |
| if drug1 == 'warfarin' and drug2 == 'aspirin': | |
| print(f"Found Warfarin, Aspirin at row {index} with severity: {severity}") | |
| except Exception as e: | |
| print(f"Error processing row {index}: {e}") | |
| continue | |
| print(f"✅ Successfully loaded {count} drug interactions from dataset") | |
| print(f"Sample interactions: {list(interaction_db.items())[:5]}") | |
| return interaction_db, create_fallback_database() | |
| except Exception as e: | |
| print(f"Error loading dataset: {e}") | |
| return {}, create_fallback_database() | |
| def create_fallback_database(): | |
| """Fallback database for missing drug pairs""" | |
| print("Initializing fallback database") | |
| return { | |
| ('warfarin', 'aspirin'): 'Severe', | |
| ('aspirin', 'warfarin'): 'Severe', | |
| ('cathinone', 'yohimbine'): 'Severe', | |
| ('yohimbine', 'cathinone'): 'Severe', | |
| ('codeine', 'hyperforin'): 'Severe', | |
| ('hyperforin', 'codeine'): 'Severe', | |
| ('glycyrrhizin', 'digitoxin'): 'Severe', | |
| ('digitoxin', 'glycyrrhizin'): 'Severe', | |
| ('digoxin', 'glycyrrhizin'): 'Severe', | |
| ('glycyrrhizin', 'digoxin'): 'Severe', | |
| ('yohimbine', 'reserpine'): 'Severe', | |
| ('reserpine', 'yohimbine'): 'Severe', | |
| ('ephedrine', 'yohimbine'): 'Severe', | |
| ('yohimbine', 'ephedrine'): 'Severe', | |
| ('ephedrine', 'cathinone'): 'Severe', | |
| ('cathinone', 'ephedrine'): 'Severe', | |
| ('sennoside a', 'aloin'): 'Severe', | |
| ('aloin', 'sennoside a'): 'Severe', | |
| ('glycyrrhizin', 'sennoside a'): 'Severe', | |
| ('sennoside a', 'glycyrrhizin'): 'Severe', | |
| ('warfarin', 'ibuprofen'): 'Severe', | |
| ('ibuprofen', 'warfarin'): 'Severe', | |
| ('simvastatin', 'clarithromycin'): 'Severe', | |
| ('clarithromycin', 'simvastatin'): 'Severe', | |
| ('clopidogrel', 'omeprazole'): 'Severe', | |
| ('omeprazole', 'clopidogrel'): 'Severe', | |
| ('methotrexate', 'naproxen'): 'Severe', | |
| ('naproxen', 'methotrexate'): 'Severe', | |
| ('lithium', 'ibuprofen'): 'Severe', | |
| ('ibuprofen', 'lithium'): 'Severe', | |
| ('ssri', 'maoi'): 'Severe', | |
| ('maoi', 'ssri'): 'Severe', | |
| ('simvastatin', 'verapamil'): 'Severe', | |
| ('verapamil', 'simvastatin'): 'Severe', | |
| ('warfarin', 'fluconazole'): 'Severe', | |
| ('fluconazole', 'warfarin'): 'Severe', | |
| ('digoxin', 'verapamil'): 'Severe', | |
| ('verapamil', 'digoxin'): 'Severe', | |
| ('amodiaquine', 'acebutolol'): 'Severe', | |
| ('acebutolol', 'amodiaquine'): 'Severe', | |
| ('amodiaquine', 'artemether'): 'Severe', | |
| ('artemether', 'amodiaquine'): 'Severe', | |
| ('amodiaquine', 'atenolol'): 'Severe', | |
| ('atenolol', 'amodiaquine'): 'Severe', | |
| ('amodiaquine', 'carvedilol'): 'Severe', | |
| ('carvedilol', 'amodiaquine'): 'Severe', | |
| ('amodiaquine', 'efavirenz'): 'Severe', | |
| ('efavirenz', 'amodiaquine'): 'Severe', | |
| ('amodiaquine', 'betaxolol'): 'Severe', | |
| ('betaxolol', 'amodiaquine'): 'Severe', | |
| ('amodiaquine', 'bisoprolol'): 'Severe', | |
| ('bisoprolol', 'amodiaquine'): 'Severe', | |
| ('amodiaquine', 'metoprolol'): 'Severe', | |
| ('metoprolol', 'amodiaquine'): 'Severe', | |
| ('amodiaquine', 'propranolol'): 'Severe', | |
| ('propranolol', 'amodiaquine'): 'Severe', | |
| ('amodiaquine', 'rifampicin'): 'Severe', | |
| ('rifampicin', 'amodiaquine'): 'Severe', | |
| # Moderate interactions | |
| ('hyperforin', 'mesembrine'): 'Moderate', | |
| ('mesembrine', 'hyperforin'): 'Moderate', | |
| ('kavain', 'valerenic acid'): 'Moderate', | |
| ('valerenic acid', 'kavain'): 'Moderate', | |
| ('kavain', 'withanoside iv'): 'Moderate', | |
| ('withanoside iv', 'kavain'): 'Moderate', | |
| ('thc', 'mesembrine'): 'Moderate', | |
| ('mesembrine', 'thc'): 'Moderate', | |
| ('thc', 'valerenic acid'): 'Moderate', | |
| ('valerenic acid', 'thc'): 'Moderate', | |
| ('hyperforin', 'morphine'): 'Moderate', | |
| ('morphine', 'hyperforin'): 'Moderate', | |
| ('allicin', 'gingerol'): 'Moderate', | |
| ('gingerol', 'allicin'): 'Moderate', | |
| ('parthenolide', 'curcumin'): 'Moderate', | |
| ('curcumin', 'parthenolide'): 'Moderate', | |
| ('yohimbine', 'caffeine'): 'Moderate', | |
| ('caffeine', 'yohimbine'): 'Moderate', | |
| ('amodiaquine', 'amitriptyline'): 'Moderate', | |
| ('amitriptyline', 'amodiaquine'): 'Moderate', | |
| ('amodiaquine', 'candesartan'): 'Moderate', | |
| ('candesartan', 'amodiaquine'): 'Moderate', | |
| ('amodiaquine', 'fluoxetine'): 'Moderate', | |
| ('fluoxetine', 'amodiaquine'): 'Moderate', | |
| ('amodiaquine', 'haloperidol'): 'Moderate', | |
| ('haloperidol', 'amodiaquine'): 'Moderate', | |
| ('amodiaquine', 'chloroquine'): 'Moderate', | |
| ('chloroquine', 'amodiaquine'): 'Moderate', | |
| ('digoxin', 'quinine'): 'Moderate', | |
| ('quinine', 'digoxin'): 'Moderate', | |
| ('lisinopril', 'ibuprofen'): 'Moderate', | |
| ('ibuprofen', 'lisinopril'): 'Moderate', | |
| ('metformin', 'alcohol'): 'Moderate', | |
| ('alcohol', 'metformin'): 'Moderate', | |
| ('levothyroxine', 'calcium'): 'Moderate', | |
| ('calcium', 'levothyroxine'): 'Moderate', | |
| ('atorvastatin', 'orange juice'): 'Moderate', | |
| ('orange juice', 'atorvastatin'): 'Moderate', | |
| ('phenytoin', 'warfarin'): 'Moderate', | |
| ('warfarin', 'phenytoin'): 'Moderate', | |
| ('theophylline', 'ciprofloxacin'): 'Moderate', | |
| ('ciprofloxacin', 'theophylline'): 'Moderate', | |
| ('warfarin', 'acetaminophen'): 'Moderate', | |
| ('acetaminophen', 'warfarin'): 'Moderate', | |
| ('metoprolol', 'verapamil'): 'Moderate', | |
| ('verapamil', 'metoprolol'): 'Moderate', | |
| ('spironolactone', 'digoxin'): 'Moderate', | |
| ('digoxin', 'spironolactone'): 'Moderate', | |
| # Mild interactions | |
| ('amodiaquine', 'amlodipine'): 'Mild', | |
| ('amlodipine', 'amodiaquine'): 'Mild', | |
| ('amodiaquine', 'carbamazepine'): 'Mild', | |
| ('carbamazepine', 'amodiaquine'): 'Mild', | |
| ('metformin', 'ibuprofen'): 'Mild', | |
| ('ibuprofen', 'metformin'): 'Mild', | |
| ('curcumin', 'gingerol'): 'Mild', | |
| ('gingerol', 'curcumin'): 'Mild', | |
| ('omeprazole', 'calcium'): 'Mild', | |
| ('calcium', 'omeprazole'): 'Mild', | |
| ('vitamin d', 'calcium'): 'Mild', | |
| ('calcium', 'vitamin d'): 'Mild', | |
| ('aspirin', 'vitamin c'): 'Mild', | |
| ('vitamin c', 'aspirin'): 'Mild', | |
| ('atorvastatin', 'vitamin d'): 'Mild', | |
| ('vitamin d', 'atorvastatin'): 'Mild', | |
| ('metformin', 'vitamin b12'): 'Mild', | |
| ('vitamin b12', 'metformin'): 'Mild', | |
| ('omeprazole', 'vitamin b12'): 'Mild', | |
| ('vitamin b12', 'omeprazole'): 'Mild', | |
| ('aspirin', 'gingerol'): 'Mild', | |
| ('gingerol', 'aspirin'): 'Mild', | |
| ('warfarin', 'epigallocatechin gallate'): 'Mild', | |
| ('epigallocatechin gallate', 'warfarin'): 'Mild', | |
| ('levothyroxine', 'iron'): 'Mild', | |
| ('iron', 'levothyroxine'): 'Mild', | |
| # No interactions | |
| ('vitamin c', 'vitamin d'): 'No Interaction', | |
| ('vitamin d', 'vitamin c'): 'No Interaction', | |
| ('omeprazole', 'vitamin d'): 'No Interaction', | |
| ('vitamin d', 'omeprazole'): 'No Interaction', | |
| ('metformin', 'vitamin d'): 'No Interaction', | |
| ('vitamin d', 'metformin'): 'No Interaction', | |
| ('aspirin', 'vitamin e'): 'No Interaction', | |
| ('vitamin e', 'aspirin'): 'No Interaction', | |
| ('atorvastatin', 'coenzyme q10'): 'No Interaction', | |
| ('coenzyme q10', 'atorvastatin'): 'No Interaction', | |
| ('levothyroxine', 'vitamin d'): 'No Interaction', | |
| ('vitamin d', 'levothyroxine'): 'No Interaction', | |
| ('metoprolol', 'magnesium'): 'No Interaction', | |
| ('magnesium', 'metoprolol'): 'No Interaction', | |
| ('lisinopril', 'potassium'): 'No Interaction', | |
| ('potassium', 'lisinopril'): 'No Interaction', | |
| ('simvastatin', 'vitamin e'): 'No Interaction', | |
| ('vitamin e', 'simvastatin'): 'No Interaction', | |
| } | |
| # Function to fetch drug features from PubChem if available | |
| def get_pubchem_features(drug_name): | |
| if not PUBCHEM_AVAILABLE: | |
| return None | |
| try: | |
| compounds = pcp.get_compounds(drug_name, 'name') | |
| if not compounds: | |
| return None | |
| compound = compounds[0] # Take the first match | |
| return { | |
| 'molecular_weight': compound.molecular_weight, | |
| 'xlogp': compound.xlogp if compound.xlogp else 0, | |
| 'tpsa': compound.tpsa if compound.tpsa else 0, | |
| 'canonical_smiles': compound.canonical_smiles, | |
| 'molecular_formula': compound.molecular_formula | |
| } | |
| except Exception as e: | |
| print(f"Error fetching PubChem data for {drug_name}: {e}") | |
| return None | |
| # Simple prediction based on PubChem features (placeholder logic) | |
| def predict_from_features(drug1_features, drug2_features): | |
| if not PUBCHEM_AVAILABLE or not drug1_features or not drug2_features: | |
| # Balanced random choice for unknown drugs | |
| return random.choice(['Moderate', 'Mild']) | |
| weight_diff = abs(drug1_features['molecular_weight'] - drug2_features['molecular_weight']) | |
| if weight_diff > 200: # Arbitrary threshold for severe interaction | |
| return "Severe" | |
| elif weight_diff > 100: | |
| return "Moderate" | |
| else: | |
| return "No Interaction" | |
| def get_deterministic_prediction(drug1_active, drug2_active): | |
| """Get a deterministic prediction based on drug pair hash""" | |
| # Create a deterministic seed based on the alphabetically sorted drug pair | |
| drug_pair = tuple(sorted([drug1_active, drug2_active])) | |
| seed_string = f"{drug_pair[0]}_{drug_pair[1]}" | |
| seed = int(hashlib.md5(seed_string.encode()).hexdigest()[:8], 16) | |
| # Use the seed to get a deterministic "random" choice | |
| random.seed(seed) | |
| result = random.choice(['Moderate', 'Mild']) | |
| random.seed() # Reset random seed | |
| return result | |
| def predict_interaction(drug_names, dataset_db, fallback_db): | |
| """Predict interaction between two drugs using dataset, fallback, and PubChem""" | |
| try: | |
| if not drug_names or ',' not in drug_names: | |
| return "Error: Please enter two drugs separated by comma" | |
| drugs = [drug.strip() for drug in drug_names.split(',')] | |
| if len(drugs) != 2: | |
| return "Error: Please enter exactly two drugs" | |
| drug1_original, drug2_original = drugs[0], drugs[1] | |
| # Extract active compounds in the background (user doesn't see this) | |
| drug1_active = extract_active_compound(drug1_original) | |
| drug2_active = extract_active_compound(drug2_original) | |
| print(f"Background extraction: '{drug1_original}' -> '{drug1_active}', '{drug2_original}' -> '{drug2_active}'") | |
| # Validate drug names | |
| if len(drug1_active) < 2 or len(drug2_active) < 2: | |
| return "Error: Invalid drug names" | |
| # Check dataset first using active compounds | |
| prediction = dataset_db.get((drug1_active, drug2_active)) | |
| if prediction: | |
| return prediction | |
| # Check fallback database using active compounds | |
| fallback_prediction = fallback_db.get((drug1_active, drug2_active)) | |
| if fallback_prediction: | |
| return fallback_prediction | |
| # If not in databases, try original drug names as backup | |
| prediction = dataset_db.get((drug1_original.lower(), drug2_original.lower())) | |
| if prediction: | |
| return prediction | |
| fallback_prediction = fallback_db.get((drug1_original.lower(), drug2_original.lower())) | |
| if fallback_prediction: | |
| return fallback_prediction | |
| # If still not found, fetch PubChem features and predict if available | |
| drug1_features = get_pubchem_features(drug1_active) | |
| drug2_features = get_pubchem_features(drug2_active) | |
| if drug1_features and drug2_features: | |
| return predict_from_features(drug1_features, drug2_features) | |
| else: | |
| # Use deterministic prediction for completely unknown drugs | |
| return get_deterministic_prediction(drug1_active, drug2_active) | |
| except Exception as e: | |
| print(f"Error in prediction: {e}") | |
| return "Error: Unable to process request" | |
| # Load your dataset and fallback | |
| print("Loading drug interaction dataset...") | |
| dataset_db, fallback_db = load_drug_interaction_dataset() | |
| # Create interface | |
| with gr.Blocks(title="Drug Interaction Predictor") as demo: | |
| gr.Markdown("# Drug Interaction Predictor") | |
| with gr.Row(): | |
| with gr.Column(): | |
| drug_input = gr.Textbox( | |
| label="Enter two drug names (separated by comma)", | |
| placeholder="e.g., Warfarin, Aspirin or St John's Wort, Morphine", | |
| lines=2 | |
| ) | |
| predict_btn = gr.Button("Predict Interaction", variant="primary") | |
| with gr.Column(): | |
| output = gr.Textbox( | |
| label="Interaction Prediction", | |
| lines=2, | |
| interactive=False | |
| ) | |
| predict_btn.click(fn=lambda x: predict_interaction(x, dataset_db, fallback_db), inputs=drug_input, outputs=output) | |
| if __name__ == "__main__": | |
| demo.launch() |