Spaces:
Sleeping
Sleeping
File size: 13,694 Bytes
e47681e 9353b00 e47681e 9353b00 e47681e 9353b00 e47681e 9353b00 e47681e 9353b00 e47681e 9353b00 e47681e 9353b00 e47681e 9353b00 e47681e 9353b00 e47681e 9353b00 e47681e 9353b00 e47681e 9353b00 e47681e 9353b00 e47681e 9353b00 e47681e 9353b00 e47681e 9353b00 e47681e 9353b00 e47681e 9353b00 e47681e 9353b00 e47681e 9353b00 e47681e 9353b00 e47681e 9353b00 e47681e 9353b00 e47681e 9353b00 e47681e 9353b00 e47681e 9353b00 e47681e 9353b00 e47681e 9353b00 e47681e 9353b00 e47681e 9353b00 e47681e 9353b00 e47681e 9353b00 e47681e 9353b00 e47681e 9353b00 e47681e 9353b00 e47681e 9353b00 e47681e 9353b00 e47681e 9353b00 e47681e 9353b00 e47681e 9353b00 e47681e 9353b00 e47681e 9353b00 e47681e 9353b00 e47681e 9353b00 e47681e 9353b00 e47681e 9353b00 e47681e 9353b00 e47681e 9353b00 e47681e 9353b00 e47681e 9353b00 e47681e 9353b00 e47681e 9353b00 e47681e 9353b00 e47681e 9353b00 e47681e 9353b00 e47681e 9353b00 e47681e 9353b00 e47681e 9353b00 e47681e 9353b00 e47681e 9353b00 | 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 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 | """
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() |