""" Enhanced Homeopathic Analysis Engine with AI-like matching """ import re from typing import Dict, List from datetime import datetime from database import REMEDY_DATABASE class EnhancedAnalyzer: def __init__(self): # Weighted scoring system self.weights = { "chief_complaint": 0.35, # 35% "modalities": 0.40, # 40% "emotional": 0.15, # 15% "generalities": 0.10 # 10% } # Keywords for different categories self.keywords = { "pain": ["pain", "ache", "sore", "hurt", "tender"], "inflammation": ["inflam", "red", "swell", "hot", "burn"], "digestive": ["stomach", "digest", "nausea", "vomit", "diarrhea"], "respiratory": ["cough", "breath", "lung", "chest", "throat"], "emotional": ["anxious", "fear", "worry", "sad", "angry", "irritable"] } def analyze_case(self, patient_data: Dict, use_ai: bool = True) -> Dict: """ Main analysis function """ # Validate input if not patient_data.get("chief_complaint"): return self._error_result("Please describe your main complaint") # Calculate matches matches = self._calculate_matches(patient_data) if not matches: return self._error_result("No remedies found matching the symptoms") # Enhance with recommendations enhanced_matches = [] for match in matches[:6]: # Top 6 only enhanced = self._enhance_match(match, patient_data) enhanced_matches.append(enhanced) # Generate comprehensive report report = self._generate_report(enhanced_matches, patient_data) return { "success": True, "matches": enhanced_matches, "report": report, "analysis_id": f"ANA{datetime.now().strftime('%Y%m%d%H%M%S')}", "timestamp": datetime.now().isoformat() } def _calculate_matches(self, patient_data: Dict) -> List[Dict]: """Calculate remedy matches with advanced scoring""" matches = [] for remedy_name, remedy_data in REMEDY_DATABASE.items(): score = self._calculate_remedy_score(patient_data, remedy_data, remedy_name) if score >= 25: # Minimum threshold matches.append({ "name": remedy_name, "data": remedy_data, "score": min(99, score), "match_reasons": self._get_match_reasons(patient_data, remedy_data) }) # Sort by score matches.sort(key=lambda x: x["score"], reverse=True) return matches def _calculate_remedy_score(self, patient: Dict, remedy: Dict, remedy_name: str) -> float: """Calculate weighted score for a remedy""" total_score = 0 # 1. Chief complaint matching complaint_score = self._score_complaint(patient, remedy) total_score += complaint_score * self.weights["chief_complaint"] # 2. Modality matching modality_score = self._score_modalities(patient, remedy) total_score += modality_score * self.weights["modalities"] # 3. Emotional matching emotional_score = self._score_emotional(patient, remedy) total_score += emotional_score * self.weights["emotional"] # 4. General symptoms matching general_score = self._score_generals(patient, remedy) total_score += general_score * self.weights["generalities"] return total_score def _score_complaint(self, patient: Dict, remedy: Dict) -> float: """Score chief complaint matching""" complaint = patient.get("chief_complaint", "").lower() if not complaint: return 0 score = 0 # Check remedy indications for indication in remedy.get("indications", []): indication_lower = indication.lower() # Direct match if indication_lower in complaint: score += 20 # Word overlap indication_words = set(re.findall(r'\b\w{4,}\b', indication_lower)) complaint_words = set(re.findall(r'\b\w{4,}\b', complaint)) common_words = indication_words.intersection(complaint_words) if common_words: score += len(common_words) * 5 return min(100, score) def _score_modalities(self, patient: Dict, remedy: Dict) -> float: """Score modality matching""" score = 0 # Patient aggravations patient_worse = patient.get("aggravations", "").lower() remedy_worse = [w.lower() for w in remedy.get("modalities", {}).get("worse", [])] for modality in remedy_worse: if modality in patient_worse: score += 15 # Patient ameliorations patient_better = patient.get("ameliorations", "").lower() remedy_better = [b.lower() for b in remedy.get("modalities", {}).get("better", [])] for modality in remedy_better: if modality in patient_better: score += 15 return min(100, score) def _score_emotional(self, patient: Dict, remedy: Dict) -> float: """Score emotional state matching""" emotional = patient.get("emotional_state", "").lower() if not emotional: return 0 remedy_mental = remedy.get("mental", "").lower() if not remedy_mental: return 0 score = 0 # Check for emotional keywords emotional_words = ["anxious", "fear", "worry", "sad", "depressed", "angry", "irritable", "restless", "weepy"] for word in emotional_words: if word in emotional and word in remedy_mental: score += 10 return min(100, score) def _score_generals(self, patient: Dict, remedy: Dict) -> float: """Score general symptoms""" generalities = patient.get("generalities", "").lower() if not generalities: return 0 score = 0 # Thermal preferences thermals = { "worse_cold": ["worse cold", "chilly", "cold aggravates"], "better_cold": ["better cold", "likes cold"], "worse_heat": ["worse heat", "heat aggravates"], "better_heat": ["better heat", "likes warmth"] } remedy_text = f"{remedy.get('physical', '')} {remedy.get('description', '')}".lower() for thermal_type, keywords in thermals.items(): patient_has = any(k in generalities for k in keywords) remedy_has = any(k in remedy_text for k in keywords) if patient_has and remedy_has: score += 10 return min(100, score) def _get_match_reasons(self, patient: Dict, remedy: Dict) -> List[str]: """Get reasons why remedy matches""" reasons = [] # Check modalities patient_worse = patient.get("aggravations", "").lower() remedy_worse = [w.lower() for w in remedy.get("modalities", {}).get("worse", [])] for modality in remedy_worse: if modality in patient_worse: reasons.append(f"Worse from {modality}") break # Check indications complaint = patient.get("chief_complaint", "").lower() for indication in remedy.get("indications", [])[:2]: if indication.lower() in complaint: reasons.append(f"Indication: {indication}") break return reasons[:3] def _enhance_match(self, match: Dict, patient_data: Dict) -> Dict: """Add recommendations and details to match""" remedy = match["data"] score = match["score"] # Determine case type timing = patient_data.get("timing", "").lower() intensity = patient_data.get("intensity", 5) if any(word in timing for word in ["acute", "sudden", "today"]) and intensity >= 7: case_type = "acute" elif any(word in timing for word in ["chronic", "months", "years"]): case_type = "chronic" else: case_type = "subacute" # Determine potency based on score and case type if case_type == "acute": if score > 80: potency = "200C" elif score > 60: potency = "30C" else: potency = "6C" frequency = "Every 2-4 hours" duration = "24-48 hours" elif case_type == "chronic": if score > 80: potency = "1M" elif score > 60: potency = "200C" else: potency = "30C" frequency = "Once daily or weekly" duration = "4-6 weeks" else: potency = "30C" frequency = "3 times daily" duration = "1-2 weeks" # Get remedy's potencies remedy_potencies = remedy.get("potencies", []) if isinstance(remedy_potencies, list): alternative_potencies = [p for p in remedy_potencies if p != potency][:2] else: alternative_potencies = [] match["recommendations"] = { "primary_potency": potency, "alternative_potencies": alternative_potencies, "frequency": frequency, "duration": duration, "case_type": case_type, "confidence_level": self._get_confidence_level(score), "administration": "3-5 pellets sublingually, away from meals", "cautions": "Avoid coffee, mint, camphor during treatment" } return match def _get_confidence_level(self, score: float) -> str: """Convert score to confidence level""" if score >= 80: return "High" elif score >= 60: return "Moderate" elif score >= 40: return "Fair" else: return "Low" def _generate_report(self, matches: List[Dict], patient_data: Dict) -> Dict: """Generate analysis report""" if not matches: return {} top_match = matches[0] return { "summary": { "top_remedy": top_match["name"], "confidence_score": top_match["score"], "confidence_level": top_match["recommendations"]["confidence_level"], "case_type": top_match["recommendations"]["case_type"], "analysis_date": datetime.now().strftime("%Y-%m-%d %H:%M"), "remedies_considered": len(matches) }, "key_findings": [ f"Primary match: {top_match['name']} ({top_match['score']:.1f}%)", f"Case type: {top_match['recommendations']['case_type'].upper()}", f"Recommended potency: {top_match['recommendations']['primary_potency']}", f"Administration: {top_match['recommendations']['frequency']}" ], "clinical_notes": [ "Stop when improvement begins", "Repeat only if symptoms return", "Monitor for initial aggravation", "Consult practitioner if no improvement in 1 week" ], "differentiation": self._get_differentiation(matches[:3]) } def _get_differentiation(self, top_matches: List[Dict]) -> List[str]: """Get differentiation between top remedies""" if len(top_matches) < 2: return [] differentiations = [] primary = top_matches[0] for match in top_matches[1:3]: diff = self._compare_remedies(primary, match) if diff: differentiations.append(f"vs {match['name']}: {diff}") return differentiations[:2] def _compare_remedies(self, remedy1: Dict, remedy2: Dict) -> str: """Compare two remedies""" differences = [] # Compare modalities worse1 = remedy1["data"].get("modalities", {}).get("worse", []) worse2 = remedy2["data"].get("modalities", {}).get("worse", []) unique1 = [w for w in worse1 if w not in worse2] if unique1: differences.append(f"Unique worse: {unique1[0]}") # Compare mental states mental1 = remedy1["data"].get("mental", "") mental2 = remedy2["data"].get("mental", "") words1 = set(re.findall(r'\b\w{4,}\b', mental1.lower())) words2 = set(re.findall(r'\b\w{4,}\b', mental2.lower())) unique_mental = words1 - words2 if unique_mental: differences.append(f"Mental: {list(unique_mental)[0]}") return "; ".join(differences) if differences else "Similar picture" def _error_result(self, message: str) -> Dict: """Return error result""" return { "success": False, "error": message, "matches": [], "timestamp": datetime.now().isoformat() } # Global instance analyzer = EnhancedAnalyzer()