yekkala commited on
Commit
e56baf3
·
verified ·
1 Parent(s): ec530e2

Create symptom_analyzer.py

Browse files
Files changed (1) hide show
  1. utils/symptom_analyzer.py +218 -0
utils/symptom_analyzer.py ADDED
@@ -0,0 +1,218 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Advanced symptom analyzer for homeopathic case analysis
3
+ """
4
+ import re
5
+ from typing import Dict, List, Tuple
6
+ import spacy
7
+ try:
8
+ nlp = spacy.load("en_core_web_sm")
9
+ except:
10
+ # Fallback if spaCy not installed
11
+ nlp = None
12
+
13
+ class SymptomAnalyzer:
14
+ def __init__(self):
15
+ self.symptom_categories = {
16
+ 'location': ['head', 'stomach', 'throat', 'chest', 'back', 'limbs', 'joints'],
17
+ 'sensation': ['burning', 'throbbing', 'stabbing', 'aching', 'pressing', 'shooting'],
18
+ 'modality': ['worse', 'better', 'aggravated', 'ameliorated', 'increased', 'decreased'],
19
+ 'time': ['morning', 'evening', 'night', 'afternoon', 'midnight', 'dawn'],
20
+ 'emotional': ['anxious', 'fearful', 'irritable', 'sad', 'restless', 'apathetic']
21
+ }
22
+
23
+ def analyze_case_sheet(self, case_data: Dict) -> Dict:
24
+ """Comprehensive analysis of case sheet data"""
25
+ analysis = {
26
+ 'physical_symptoms': self._extract_physical_symptoms(case_data.get('symptoms', '')),
27
+ 'modalities': self._extract_modalities(case_data.get('modalities', '')),
28
+ 'time_factors': self._extract_time_factors(case_data.get('timing', '')),
29
+ 'emotional_state': self._analyze_emotional_state(case_data.get('emotional_state', '')),
30
+ 'constitutional_factors': self._analyze_constitutional(case_data.get('constitutional', '')),
31
+ 'key_symptoms': [],
32
+ 'strange_rare_peculiar': []
33
+ }
34
+
35
+ # Identify key symptoms
36
+ analysis['key_symptoms'] = self._identify_key_symptoms(analysis)
37
+
38
+ # Identify strange, rare, peculiar symptoms
39
+ analysis['strange_rare_peculiar'] = self._identify_srp(analysis)
40
+
41
+ return analysis
42
+
43
+ def _extract_physical_symptoms(self, text: str) -> List[Dict]:
44
+ """Extract physical symptoms with details"""
45
+ symptoms = []
46
+
47
+ # Simple pattern matching (can be enhanced with NLP)
48
+ patterns = {
49
+ 'pain': r'(pain|ache|sore|tenderness)(?:\s+(?:in|of|at)\s+(\w+))?',
50
+ 'fever': r'(fever|temperature|hot|cold|chill)',
51
+ 'digestive': r'(nausea|vomiting|diarrhea|constipation|bloating|indigestion)',
52
+ 'respiratory': r'(cough|breath|sneeze|nasal|throat)',
53
+ 'skin': r'(rash|itch|redness|swelling|eruption)'
54
+ }
55
+
56
+ for symptom_type, pattern in patterns.items():
57
+ matches = re.finditer(pattern, text.lower())
58
+ for match in matches:
59
+ symptoms.append({
60
+ 'type': symptom_type,
61
+ 'description': match.group(),
62
+ 'location': match.group(2) if match.lastindex > 1 else 'general'
63
+ })
64
+
65
+ return symptoms
66
+
67
+ def _extract_modalities(self, text: str) -> Dict:
68
+ """Extract what makes symptoms better or worse"""
69
+ modalities = {
70
+ 'aggravations': [],
71
+ 'ameliorations': []
72
+ }
73
+
74
+ # Look for worsening factors
75
+ worse_patterns = [
76
+ r'worse\s+(?:with|from|after|by)\s+([^.]+)',
77
+ r'aggravated\s+by\s+([^.]+)',
78
+ r'increased\s+with\s+([^.]+)'
79
+ ]
80
+
81
+ for pattern in worse_patterns:
82
+ matches = re.findall(pattern, text.lower())
83
+ for match in matches:
84
+ modalities['aggravations'].extend([m.strip() for m in match.split(',')])
85
+
86
+ # Look for improving factors
87
+ better_patterns = [
88
+ r'better\s+(?:with|from|after|by)\s+([^.]+)',
89
+ r'relieved\s+by\s+([^.]+)',
90
+ r'ameliorated\s+by\s+([^.]+)'
91
+ ]
92
+
93
+ for pattern in better_patterns:
94
+ matches = re.findall(pattern, text.lower())
95
+ for match in matches:
96
+ modalities['ameliorations'].extend([m.strip() for m in match.split(',')])
97
+
98
+ return modalities
99
+
100
+ def _extract_time_factors(self, text: str) -> Dict:
101
+ """Extract time-related factors"""
102
+ time_factors = {
103
+ 'time_of_day': [],
104
+ 'periodicity': [],
105
+ 'duration': []
106
+ }
107
+
108
+ # Time of day patterns
109
+ time_patterns = {
110
+ 'morning': r'\b(morning|dawn|sunrise|AM)\b',
111
+ 'afternoon': r'\b(afternoon|midday|noon|2pm|3pm)\b',
112
+ 'evening': r'\b(evening|dusk|sunset|PM)\b',
113
+ 'night': r'\b(night|midnight|2am|3am)\b'
114
+ }
115
+
116
+ for time_name, pattern in time_patterns.items():
117
+ if re.search(pattern, text.lower()):
118
+ time_factors['time_of_day'].append(time_name)
119
+
120
+ # Periodicity
121
+ if re.search(r'\b(every\s+\w+|daily|weekly|monthly|periodic)\b', text.lower()):
122
+ time_factors['periodicity'].append('periodic')
123
+
124
+ return time_factors
125
+
126
+ def _analyze_emotional_state(self, text: str) -> Dict:
127
+ """Analyze emotional and mental state"""
128
+ emotions = {
129
+ 'fear': ['fear', 'anxious', 'worried', 'apprehensive', 'panic'],
130
+ 'anger': ['angry', 'irritable', 'frustrated', 'resentful'],
131
+ 'sadness': ['sad', 'depressed', 'weepy', 'grief', 'melancholy'],
132
+ 'restlessness': ['restless', 'agitated', 'nervous', 'fidgety']
133
+ }
134
+
135
+ detected = []
136
+ for emotion, keywords in emotions.items():
137
+ if any(keyword in text.lower() for keyword in keywords):
138
+ detected.append(emotion)
139
+
140
+ return {
141
+ 'primary_emotions': detected,
142
+ 'description': text
143
+ }
144
+
145
+ def _analyze_constitutional(self, text: str) -> Dict:
146
+ """Analyze constitutional factors"""
147
+ factors = {
148
+ 'thermals': self._extract_thermals(text),
149
+ 'desires_aversions': self._extract_desires_aversions(text),
150
+ 'generalities': []
151
+ }
152
+
153
+ # General constitutional factors
154
+ general_terms = ['weak', 'strong', 'lean', 'stout', 'pale', 'flushed']
155
+ for term in general_terms:
156
+ if term in text.lower():
157
+ factors['generalities'].append(term)
158
+
159
+ return factors
160
+
161
+ def _extract_thermals(self, text: str) -> List[str]:
162
+ """Extract thermal preferences"""
163
+ thermals = []
164
+ if 'warm' in text.lower() or 'heat' in text.lower():
165
+ thermals.append('warm-blooded')
166
+ if 'cold' in text.lower() or 'chilly' in text.lower():
167
+ thermals.append('cold-blooded')
168
+ return thermals
169
+
170
+ def _extract_desires_aversions(self, text: str) -> Dict:
171
+ """Extract food desires and aversions"""
172
+ desires = []
173
+ aversions = []
174
+
175
+ # Simple pattern matching
176
+ desire_pattern = r'desires?\s+(?:to\s+)?(\w+)'
177
+ aversion_pattern = r'aversions?\s+(?:to\s+)?(\w+)'
178
+
179
+ desires.extend(re.findall(desire_pattern, text.lower()))
180
+ aversions.extend(re.findall(aversion_pattern, text.lower()))
181
+
182
+ return {'desires': desires, 'aversions': aversions}
183
+
184
+ def _identify_key_symptoms(self, analysis: Dict) -> List[str]:
185
+ """Identify key symptoms for repertorization"""
186
+ key_symptoms = []
187
+
188
+ # Add strong modalities
189
+ if analysis['modalities']['aggravations']:
190
+ key_symptoms.append(f"< aggravations: {', '.join(analysis['modalities']['aggravations'][:3])}")
191
+ if analysis['modalities']['ameliorations']:
192
+ key_symptoms.append(f"> ameliorations: {', '.join(analysis['modalities']['ameliorations'][:3])}")
193
+
194
+ # Add time factors
195
+ if analysis['time_factors']['time_of_day']:
196
+ key_symptoms.append(f"time: {', '.join(analysis['time_factors']['time_of_day'])}")
197
+
198
+ # Add emotional state
199
+ if analysis['emotional_state']['primary_emotions']:
200
+ key_symptoms.append(f"emotion: {', '.join(analysis['emotional_state']['primary_emotions'])}")
201
+
202
+ return key_symptoms
203
+
204
+ def _identify_srp(self, analysis: Dict) -> List[str]:
205
+ """Identify strange, rare, peculiar symptoms"""
206
+ srp_symptoms = []
207
+
208
+ # Look for unusual modalities
209
+ unusual_modalities = ['contradictory', 'paradoxical', 'opposite', 'strange']
210
+ for modality in analysis['modalities']['aggravations'] + analysis['modalities']['ameliorations']:
211
+ if any(word in modality for word in unusual_modalities):
212
+ srp_symptoms.append(f"Unusual modality: {modality}")
213
+
214
+ # Look for contradictory symptoms
215
+ if analysis['emotional_state']['primary_emotions'] and len(analysis['emotional_state']['primary_emotions']) > 1:
216
+ srp_symptoms.append(f"Contradictory emotions: {', '.join(analysis['emotional_state']['primary_emotions'])}")
217
+
218
+ return srp_symptoms