ahmedmiloudi/BioTechLabAI
1
1"""2Bioactivity Profiler Module3============================4Analyse de bioactivité et SAR (Structure-Activity Relationships)5 6Fonctionnalités:7- Analyse IC50/Ki/EC508- SAR analysis9- Dose-response curves10- Selectivity profiling11 12Auteur: Drug Discovery Platform13Date: 2026-01-3114"""15 16import pandas as pd17import numpy as np18from typing import Dict, List, Optional19import logging20 21logger = logging.getLogger(__name__)22 23 24class BioactivityProfiler:25 """Profiler pour données de bioactivité"""26 27 def __init__(self):28 logger.info("BioactivityProfiler initialized")29 30 def analyze_potency_distribution(self, bioactivities: List) -> Dict:31 """Analyse distribution des potences"""32 if not bioactivities:33 return {}34 35 values = [b.activity_value for b in bioactivities if b.activity_value > 0]36 37 return {38 'count': len(values),39 'mean_nM': np.mean(values),40 'median_nM': np.median(values),41 'std_nM': np.std(values),42 'min_nM': np.min(values),43 'max_nM': np.max(values),44 'potent_compounds': sum(1 for v in values if v < 100), # < 100nM45 'moderate_compounds': sum(1 for v in values if 100 <= v < 1000),46 'weak_compounds': sum(1 for v in values if v >= 1000)47 }48 49 def calculate_selectivity(self, target_ic50: float, offtarget_ic50s: List[float]) -> Dict:50 """Calcule sélectivité"""51 selectivities = [off / target_ic50 for off in offtarget_ic50s if off > 0]52 53 return {54 'mean_selectivity': np.mean(selectivities) if selectivities else 0,55 'max_selectivity': np.max(selectivities) if selectivities else 0,56 'selective_ratio': sum(1 for s in selectivities if s > 10) / len(selectivities) if selectivities else 057 }58 59 def identify_sar_trends(self, compounds_df: pd.DataFrame) -> List[Dict]:60 """Identifie trends SAR (simplifié)"""61 trends = []62 63 if 'MW' in compounds_df.columns and 'IC50' in compounds_df.columns:64 corr = compounds_df[['MW', 'IC50']].corr().iloc[0, 1]65 if abs(corr) > 0.5:66 trends.append({67 'feature': 'Molecular Weight',68 'correlation': corr,69 'trend': 'positive' if corr > 0 else 'negative'70 })71 72 return trends73 74 def predict_activity_class(self, ic50_nM: float) -> str:75 """Classe activité"""76 if ic50_nM < 10:77 return 'Very Potent'78 elif ic50_nM < 100:79 return 'Potent'80 elif ic50_nM < 1000:81 return 'Moderate'82 else:83 return 'Weak'84 85if __name__ == "__main__":86 profiler = BioactivityProfiler()87 print("BioactivityProfiler ready")88 