mystic_CBK commited on
Commit
58e60a2
Β·
1 Parent(s): e548411

Fix JSON serialization error: Convert all numpy types to Python native types for clinical analysis

Browse files
clinical_analysis.py CHANGED
@@ -126,23 +126,27 @@ def extract_clinical_from_probabilities(probs: np.ndarray) -> Dict[str, Any]:
126
  # Calculate confidence metrics
127
  confidence_metrics = calculate_confidence_metrics(probs, thresholds)
128
 
 
 
 
 
129
  return {
130
- "rhythm": rhythm,
131
  "heart_rate": None, # Will be calculated from features if available
132
  "qrs_duration": None, # Will be calculated from features if available
133
  "qt_interval": None, # Will be calculated from features if available
134
  "pr_interval": None, # Will be calculated from features if available
135
  "axis_deviation": "Normal", # Will be calculated from features if available
136
- "abnormalities": abnormalities,
137
- "confidence": confidence_metrics["overall_confidence"],
138
- "confidence_level": confidence_metrics["confidence_level"],
139
- "review_required": confidence_metrics["review_required"],
140
- "probabilities": probs.tolist(),
141
- "label_probabilities": dict(zip(labels, probs.tolist())),
142
  "method": "clinical_predictions",
143
  "warning": None,
144
- "labels_used": labels,
145
- "thresholds_used": thresholds
146
  }
147
 
148
  except Exception as e:
@@ -310,9 +314,9 @@ def calculate_confidence_metrics(probs: np.ndarray, thresholds: Dict[str, float]
310
  review_required = max_prob < 0.6 or mean_prob < 0.4
311
 
312
  return {
313
- "overall_confidence": overall_confidence,
314
- "confidence_level": confidence_level,
315
- "review_required": review_required,
316
  "mean_probability": float(mean_prob),
317
  "max_probability": float(max_prob)
318
  }
 
126
  # Calculate confidence metrics
127
  confidence_metrics = calculate_confidence_metrics(probs, thresholds)
128
 
129
+ # Ensure all numpy types are converted to Python native types for JSON serialization
130
+ probabilities_list = [float(p) for p in probs]
131
+ label_probs_dict = {str(label): float(prob) for label, prob in zip(labels, probs)}
132
+
133
  return {
134
+ "rhythm": str(rhythm),
135
  "heart_rate": None, # Will be calculated from features if available
136
  "qrs_duration": None, # Will be calculated from features if available
137
  "qt_interval": None, # Will be calculated from features if available
138
  "pr_interval": None, # Will be calculated from features if available
139
  "axis_deviation": "Normal", # Will be calculated from features if available
140
+ "abnormalities": [str(abnormality) for abnormality in abnormalities],
141
+ "confidence": float(confidence_metrics["overall_confidence"]),
142
+ "confidence_level": str(confidence_metrics["confidence_level"]),
143
+ "review_required": bool(confidence_metrics["review_required"]),
144
+ "probabilities": probabilities_list,
145
+ "label_probabilities": label_probs_dict,
146
  "method": "clinical_predictions",
147
  "warning": None,
148
+ "labels_used": [str(label) for label in labels],
149
+ "thresholds_used": {str(k): float(v) for k, v in thresholds.items()}
150
  }
151
 
152
  except Exception as e:
 
314
  review_required = max_prob < 0.6 or mean_prob < 0.4
315
 
316
  return {
317
+ "overall_confidence": float(overall_confidence),
318
+ "confidence_level": str(confidence_level),
319
+ "review_required": bool(review_required),
320
  "mean_probability": float(mean_prob),
321
  "max_probability": float(max_prob)
322
  }
comprehensive_ecg_test.py ADDED
@@ -0,0 +1,319 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ Comprehensive Multi-ECG Testing and Evaluation
4
+ Tests multiple ECG samples and analyzes results systematically
5
+ """
6
+
7
+ import requests
8
+ import numpy as np
9
+ import pandas as pd
10
+ import json
11
+ import time
12
+ import os
13
+ from typing import Dict, Any, List
14
+ from datetime import datetime
15
+
16
+ # Configuration
17
+ API_BASE_URL = "https://mystic-cbk-ecg-fm-api.hf.space"
18
+ ECG_DIR = "../ecg_uploads_greenwich/"
19
+ INDEX_FILE = "../Greenwichschooldata.csv"
20
+
21
+ def load_ecg_data(csv_file: str) -> List[List[float]]:
22
+ """Load ECG data from CSV file"""
23
+ try:
24
+ df = pd.read_csv(csv_file)
25
+ ecg_data = []
26
+ for lead in df.columns:
27
+ ecg_data.append(df[lead].astype(float).tolist())
28
+ return ecg_data
29
+ except Exception as e:
30
+ print(f"❌ Error loading ECG data: {e}")
31
+ return None
32
+
33
+ def test_individual_endpoints(ecg_data: List[List[float]], patient_info: Dict[str, Any]) -> Dict[str, Any]:
34
+ """Test all individual endpoints with comprehensive analysis"""
35
+ results = {}
36
+
37
+ print(f"πŸ§ͺ Testing individual endpoints for {patient_info.get('Patient Name', 'Unknown')}")
38
+
39
+ # Test 1: Extract Features (Physiological measurements)
40
+ print("1️⃣ Testing /extract_features endpoint...")
41
+ try:
42
+ payload = {"signal": ecg_data, "fs": 500}
43
+ response = requests.post(f"{API_BASE_URL}/extract_features", json=payload, timeout=60)
44
+
45
+ if response.status_code == 200:
46
+ result = response.json()
47
+ physio = result.get('physiological_parameters', {})
48
+
49
+ print(f" βœ… Features extracted successfully")
50
+ print(f" πŸ“Š Feature count: {result.get('features', {}).get('count', 'Unknown')}")
51
+ print(f" πŸ“Š Feature dimension: {result.get('features', {}).get('dimension', 'Unknown')}")
52
+ print(f" πŸ’“ Heart Rate: {physio.get('heart_rate')} BPM")
53
+ print(f" πŸ“ QRS Duration: {physio.get('qrs_duration')} ms")
54
+ print(f" ⏱️ QT Interval: {physio.get('qt_interval')} ms")
55
+ print(f" πŸ”— PR Interval: {physio.get('pr_interval')} ms")
56
+ print(f" 🧭 QRS Axis: {physio.get('qrs_axis')}°")
57
+
58
+ results['extract_features'] = {"status": "success", "data": result}
59
+ else:
60
+ print(f" ❌ Failed: {response.status_code}")
61
+ results['extract_features'] = {"status": "error", "error": response.text}
62
+ except Exception as e:
63
+ print(f" ❌ Error: {e}")
64
+ results['extract_features'] = {"status": "error", "error": str(e)}
65
+
66
+ # Test 2: Assess Quality
67
+ print("2️⃣ Testing /assess_quality endpoint...")
68
+ try:
69
+ payload = {"signal": ecg_data, "fs": 500}
70
+ response = requests.post(f"{API_BASE_URL}/assess_quality", json=payload, timeout=60)
71
+
72
+ if response.status_code == 200:
73
+ result = response.json()
74
+ print(f" βœ… Quality assessment completed")
75
+ print(f" πŸ” Overall Quality: {result.get('quality', 'Unknown')}")
76
+ metrics = result.get('metrics', {})
77
+ print(f" πŸ“Š SNR: {metrics.get('signal_to_noise_ratio', 'Unknown')}")
78
+ print(f" πŸ“Š Baseline Wander: {metrics.get('baseline_wander', 'Unknown')}")
79
+ print(f" πŸ“Š Standard Deviation: {metrics.get('standard_deviation', 'Unknown')}")
80
+
81
+ results['assess_quality'] = {"status": "success", "data": result}
82
+ else:
83
+ print(f" ❌ Failed: {response.status_code}")
84
+ results['assess_quality'] = {"status": "error", "error": response.text}
85
+ except Exception as e:
86
+ print(f" ❌ Error: {e}")
87
+ results['assess_quality'] = {"status": "error", "error": str(e)}
88
+
89
+ # Test 3: Predict endpoint
90
+ print("3️⃣ Testing /predict endpoint...")
91
+ try:
92
+ payload = {"signal": ecg_data, "fs": 500}
93
+ response = requests.post(f"{API_BASE_URL}/predict", json=payload, timeout=60)
94
+
95
+ if response.status_code == 200:
96
+ result = response.json()
97
+ print(f" βœ… Prediction completed")
98
+ print(f" 🧬 Model Type: {result.get('model_type', 'Unknown')}")
99
+ print(f" πŸ“Š Confidence: {result.get('confidence', 'Unknown')}")
100
+
101
+ results['predict'] = {"status": "success", "data": result}
102
+ else:
103
+ print(f" ❌ Failed: {response.status_code}")
104
+ results['assess_quality'] = {"status": "error", "error": response.text}
105
+ except Exception as e:
106
+ print(f" ❌ Error: {e}")
107
+ results['predict'] = {"status": "error", "error": str(e)}
108
+
109
+ return results
110
+
111
+ def analyze_physiological_consistency(all_results: Dict[str, Any]) -> Dict[str, Any]:
112
+ """Analyze consistency of physiological measurements across samples"""
113
+ print(f"\nπŸ“Š PHYSIOLOGICAL MEASUREMENT CONSISTENCY ANALYSIS")
114
+ print(f"=" * 70)
115
+
116
+ # Extract all heart rate values
117
+ hr_values = []
118
+ qrs_values = []
119
+ qt_values = []
120
+ pr_values = []
121
+ axis_values = []
122
+
123
+ for patient_id, result in all_results.items():
124
+ if 'endpoint_tests' in result and 'extract_features' in result['endpoint_tests']:
125
+ physio = result['endpoint_tests']['extract_features'].get('data', {}).get('physiological_parameters', {})
126
+
127
+ if physio.get('heart_rate') is not None:
128
+ hr_values.append(physio['heart_rate'])
129
+ if physio.get('qrs_duration') is not None:
130
+ qrs_values.append(physio['qrs_duration'])
131
+ if physio.get('qt_interval') is not None:
132
+ qt_values.append(physio['qt_interval'])
133
+ if physio.get('pr_interval') is not None:
134
+ pr_values.append(physio['pr_interval'])
135
+ if physio.get('qrs_axis') is not None:
136
+ axis_values.append(physio['qrs_axis'])
137
+
138
+ analysis = {}
139
+
140
+ # Heart Rate Analysis
141
+ if len(hr_values) > 0:
142
+ hr_std = np.std(hr_values)
143
+ hr_range = np.ptp(hr_values)
144
+ print(f"πŸ’“ Heart Rate Analysis:")
145
+ print(f" Values: {hr_values}")
146
+ print(f" Mean: {np.mean(hr_values):.1f} BPM")
147
+ print(f" Standard Deviation: {hr_std:.2f} BPM")
148
+ print(f" Range: {hr_range:.1f} BPM")
149
+ print(f" Consistency: {'βœ… Excellent' if hr_std < 2.0 else '⚠️ Good' if hr_std < 5.0 else '❌ Poor'}")
150
+
151
+ analysis['heart_rate'] = {
152
+ 'values': hr_values,
153
+ 'mean': np.mean(hr_values),
154
+ 'std': hr_std,
155
+ 'range': hr_range,
156
+ 'consistency': 'Excellent' if hr_std < 2.0 else 'Good' if hr_std < 5.0 else 'Poor'
157
+ }
158
+
159
+ # QRS Duration Analysis
160
+ if len(qrs_values) > 0:
161
+ qrs_std = np.std(qrs_values)
162
+ qrs_range = np.ptp(qrs_values)
163
+ print(f"\nπŸ“ QRS Duration Analysis:")
164
+ print(f" Values: {qrs_values}")
165
+ print(f" Mean: {np.mean(qrs_values):.1f} ms")
166
+ print(f" Standard Deviation: {qrs_std:.2f} ms")
167
+ print(f" Range: {qrs_range:.1f} ms")
168
+ print(f" Consistency: {'βœ… Excellent' if qrs_std < 5.0 else '⚠️ Good' if qrs_std < 10.0 else '❌ Poor'}")
169
+
170
+ analysis['qrs_duration'] = {
171
+ 'values': qrs_values,
172
+ 'mean': np.mean(qrs_values),
173
+ 'std': qrs_std,
174
+ 'range': qrs_range,
175
+ 'consistency': 'Excellent' if qrs_std < 5.0 else 'Good' if qrs_std < 10.0 else 'Poor'
176
+ }
177
+
178
+ # Overall Assessment
179
+ print(f"\n🎯 OVERALL PHYSIOLOGICAL ASSESSMENT:")
180
+ working_params = len([k for k in analysis.keys() if analysis[k]['consistency'] in ['Excellent', 'Good']])
181
+ total_params = len(analysis)
182
+
183
+ print(f" Working Parameters: {working_params}/{total_params}")
184
+ print(f" Success Rate: {(working_params/total_params)*100:.1f}%")
185
+
186
+ if working_params == total_params:
187
+ print(f" πŸŽ‰ All physiological parameters working consistently!")
188
+ elif working_params > total_params // 2:
189
+ print(f" ⚠️ Most parameters working - some inconsistencies")
190
+ else:
191
+ print(f" ❌ Many parameters showing inconsistencies")
192
+
193
+ return analysis
194
+
195
+ def main():
196
+ """Main test function"""
197
+ print("πŸš€ COMPREHENSIVE MULTI-ECG TESTING AND EVALUATION")
198
+ print("=" * 80)
199
+ print(f"🌐 API URL: {API_BASE_URL}")
200
+ print(f"πŸ“ ECG Directory: {ECG_DIR}")
201
+ print(f"πŸ“‹ Index File: {INDEX_FILE}")
202
+ print()
203
+
204
+ # Check if files exist
205
+ if not os.path.exists(INDEX_FILE):
206
+ print(f"❌ Index file not found: {INDEX_FILE}")
207
+ return
208
+
209
+ if not os.path.exists(ECG_DIR):
210
+ print(f"❌ ECG directory not found: {ECG_DIR}")
211
+ return
212
+
213
+ # Load index file
214
+ try:
215
+ print("πŸ“ Loading patient index file...")
216
+ index_df = pd.read_csv(INDEX_FILE)
217
+ print(f"βœ… Loaded {len(index_df)} patient records")
218
+ except Exception as e:
219
+ print(f"❌ Error loading index file: {e}")
220
+ return
221
+
222
+ # Select multiple ECG files for testing
223
+ test_files = [
224
+ "ecg_98408931-6f8e-47cc-954a-ba0c058a0f3d.csv", # Bharathi M K Teacher, 31, F
225
+ "ecg_fc6d2ecb-7eb3-4eec-9281-17c24b7902b5.csv", # Sayida thasmiya Bhanu Teacher, 29, F
226
+ "ecg_022a3f3a-7060-4ff8-b716-b75d8e0637c5.csv", # Afzal, 46, M
227
+ # Add more files if available
228
+ ]
229
+
230
+ print(f"\nπŸš€ Testing with {len(test_files)} ECG samples...")
231
+ print("=" * 80)
232
+
233
+ all_results = {}
234
+
235
+ for i, ecg_file in enumerate(test_files, 1):
236
+ try:
237
+ print(f"\nπŸ“Š Processing {i}/{len(test_files)}: {ecg_file}")
238
+
239
+ # Find patient info in index
240
+ patient_row = index_df[index_df['ECG File Path'].str.contains(ecg_file, na=False)]
241
+ if len(patient_row) == 0:
242
+ print(f" ⚠️ Patient info not found for {ecg_file}")
243
+ continue
244
+
245
+ patient_info = patient_row.iloc[0]
246
+ print(f" πŸ‘€ Patient: {patient_info['Patient Name']} ({patient_info['Age']} {patient_info['Gender']})")
247
+
248
+ # Check if ECG file exists
249
+ ecg_path = os.path.join(ECG_DIR, ecg_file)
250
+ if not os.path.exists(ecg_path):
251
+ print(f" ❌ ECG file not found: {ecg_path}")
252
+ continue
253
+
254
+ # Load ECG data
255
+ ecg_data = load_ecg_data(ecg_path)
256
+ if ecg_data is None:
257
+ print(f" ❌ Failed to load ECG data")
258
+ continue
259
+
260
+ # Test individual endpoints
261
+ endpoint_results = test_individual_endpoints(ecg_data, patient_info)
262
+
263
+ # Store results
264
+ all_results[ecg_file] = {
265
+ "patient_info": patient_info.to_dict(),
266
+ "endpoint_tests": endpoint_results
267
+ }
268
+
269
+ print(f" βœ… Completed analysis for {ecg_file}")
270
+
271
+ except Exception as e:
272
+ print(f" ❌ Error processing {ecg_file}: {e}")
273
+ all_results[ecg_file] = {"error": str(e)}
274
+
275
+ # Analyze physiological consistency
276
+ if len(all_results) > 0:
277
+ physiological_analysis = analyze_physiological_consistency(all_results)
278
+
279
+ # Summary report
280
+ print(f"\nπŸ“Š COMPREHENSIVE TEST SUMMARY")
281
+ print(f"=" * 80)
282
+
283
+ successful_tests = 0
284
+ total_tests = len(test_files)
285
+
286
+ for ecg_file, result in all_results.items():
287
+ if "error" not in result:
288
+ endpoint_status = result.get("endpoint_tests", {})
289
+ working_endpoints = sum(1 for ep in endpoint_status.values() if ep.get("status") == "success")
290
+ total_endpoints = len(endpoint_status)
291
+
292
+ if working_endpoints == total_endpoints:
293
+ successful_tests += 1
294
+ print(f"βœ… {ecg_file}: All endpoints working")
295
+ else:
296
+ print(f"⚠️ {ecg_file}: {working_endpoints}/{total_endpoints} endpoints working")
297
+ else:
298
+ print(f"❌ {ecg_file}: {result['error']}")
299
+
300
+ print(f"\n🎯 OVERALL RESULTS:")
301
+ print(f" Successful ECG Analysis: {successful_tests}/{total_tests}")
302
+ print(f" Success Rate: {(successful_tests/total_tests)*100:.1f}%")
303
+
304
+ # Save detailed results
305
+ timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
306
+ results_file = f"comprehensive_ecg_test_results_{timestamp}.json"
307
+
308
+ try:
309
+ with open(results_file, 'w') as f:
310
+ json.dump(all_results, f, indent=2, default=str)
311
+ print(f"\nπŸ’Ύ Detailed results saved to: {results_file}")
312
+ except Exception as e:
313
+ print(f"\n⚠️ Could not save results: {e}")
314
+
315
+ print(f"\nπŸŽ‰ Comprehensive ECG testing completed!")
316
+ print(f"πŸ’‘ Check the results above to evaluate system performance")
317
+
318
+ if __name__ == "__main__":
319
+ main()
comprehensive_ecg_test_results_20250828_151718.json ADDED
@@ -0,0 +1,233 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "ecg_98408931-6f8e-47cc-954a-ba0c058a0f3d.csv": {
3
+ "patient_info": {
4
+ "Organization": "Greenberg international school",
5
+ "Department": "General",
6
+ "Patient Name": "Bharathi M K Teacher",
7
+ "Age": 31,
8
+ "Gender": "Female",
9
+ "Created At": "2025-07-21T10:10:05.716Z",
10
+ "ECG File Path": "ecg_uploads_greenwich/ecg_98408931-6f8e-47cc-954a-ba0c058a0f3d.csv",
11
+ "Ai Result": "No abnormality detected"
12
+ },
13
+ "endpoint_tests": {
14
+ "extract_features": {
15
+ "status": "success",
16
+ "data": {
17
+ "status": "success",
18
+ "processing_time_ms": 335.99,
19
+ "features": {
20
+ "count": 79872,
21
+ "dimension": 256,
22
+ "extraction_method": "ECG-FM pretrained model"
23
+ },
24
+ "physiological_parameters": {
25
+ "heart_rate": 60.0,
26
+ "qrs_duration": 150.8,
27
+ "qt_interval": 413.3,
28
+ "pr_interval": 159.1,
29
+ "qrs_axis": 30.1,
30
+ "extraction_method": "ECG-FM validated feature analysis",
31
+ "confidence": "High",
32
+ "feature_dimension": 79872,
33
+ "clinical_ranges": {
34
+ "heart_rate": "30-200 BPM",
35
+ "qrs_duration": "40-200 ms",
36
+ "qt_interval": "300-600 ms",
37
+ "pr_interval": "100-300 ms",
38
+ "qrs_axis": "-180\u00b0 to +180\u00b0"
39
+ },
40
+ "extraction_confidence": {
41
+ "heart_rate": "High",
42
+ "qrs_duration": "High",
43
+ "qt_interval": "High",
44
+ "pr_interval": "High",
45
+ "qrs_axis": "High"
46
+ }
47
+ },
48
+ "model_source": "wanglab/ecg-fm/mimic_iv_ecg_physionet_pretrained.pt"
49
+ }
50
+ },
51
+ "assess_quality": {
52
+ "status": "success",
53
+ "data": {
54
+ "status": "success",
55
+ "processing_time_ms": 6.51,
56
+ "quality": "Poor",
57
+ "metrics": {
58
+ "standard_deviation": 36.6422,
59
+ "signal_to_noise_ratio": 0.6119,
60
+ "baseline_wander": 5.6589,
61
+ "peak_to_peak": 411.0937,
62
+ "mean_amplitude": 22.4223
63
+ },
64
+ "assessment_method": "Statistical analysis + ECG-FM feature validation"
65
+ }
66
+ },
67
+ "predict": {
68
+ "status": "success",
69
+ "data": {
70
+ "prediction": "ECG analysis completed",
71
+ "confidence": 0.8,
72
+ "features": {},
73
+ "model_type": "ECG-FM Pretrained (fairseq_signals)",
74
+ "model_source": "wanglab/ecg-fm/mimic_iv_ecg_physionet_pretrained.pt"
75
+ }
76
+ }
77
+ }
78
+ },
79
+ "ecg_fc6d2ecb-7eb3-4eec-9281-17c24b7902b5.csv": {
80
+ "patient_info": {
81
+ "Organization": "Greenberg international school",
82
+ "Department": "General",
83
+ "Patient Name": "Sayida thasmiya Bhanu Teacher",
84
+ "Age": 29,
85
+ "Gender": "Female",
86
+ "Created At": "2025-07-21T07:22:38.484Z",
87
+ "ECG File Path": "ecg_uploads_greenwich/ecg_fc6d2ecb-7eb3-4eec-9281-17c24b7902b5.csv",
88
+ "Ai Result": "ST(29.1%)"
89
+ },
90
+ "endpoint_tests": {
91
+ "extract_features": {
92
+ "status": "success",
93
+ "data": {
94
+ "status": "success",
95
+ "processing_time_ms": 302.79,
96
+ "features": {
97
+ "count": 79872,
98
+ "dimension": 256,
99
+ "extraction_method": "ECG-FM pretrained model"
100
+ },
101
+ "physiological_parameters": {
102
+ "heart_rate": 59.7,
103
+ "qrs_duration": 157.0,
104
+ "qt_interval": 415.0,
105
+ "pr_interval": 160.9,
106
+ "qrs_axis": 28.3,
107
+ "extraction_method": "ECG-FM validated feature analysis",
108
+ "confidence": "High",
109
+ "feature_dimension": 79872,
110
+ "clinical_ranges": {
111
+ "heart_rate": "30-200 BPM",
112
+ "qrs_duration": "40-200 ms",
113
+ "qt_interval": "300-600 ms",
114
+ "pr_interval": "100-300 ms",
115
+ "qrs_axis": "-180\u00b0 to +180\u00b0"
116
+ },
117
+ "extraction_confidence": {
118
+ "heart_rate": "High",
119
+ "qrs_duration": "High",
120
+ "qt_interval": "High",
121
+ "pr_interval": "High",
122
+ "qrs_axis": "High"
123
+ }
124
+ },
125
+ "model_source": "wanglab/ecg-fm/mimic_iv_ecg_physionet_pretrained.pt"
126
+ }
127
+ },
128
+ "assess_quality": {
129
+ "status": "success",
130
+ "data": {
131
+ "status": "success",
132
+ "processing_time_ms": 4.11,
133
+ "quality": "Poor",
134
+ "metrics": {
135
+ "standard_deviation": 46.0951,
136
+ "signal_to_noise_ratio": 0.364,
137
+ "baseline_wander": 9.0349,
138
+ "peak_to_peak": 837.1298,
139
+ "mean_amplitude": 16.7801
140
+ },
141
+ "assessment_method": "Statistical analysis + ECG-FM feature validation"
142
+ }
143
+ },
144
+ "predict": {
145
+ "status": "success",
146
+ "data": {
147
+ "prediction": "ECG analysis completed",
148
+ "confidence": 0.8,
149
+ "features": {},
150
+ "model_type": "ECG-FM Pretrained (fairseq_signals)",
151
+ "model_source": "wanglab/ecg-fm/mimic_iv_ecg_physionet_pretrained.pt"
152
+ }
153
+ }
154
+ }
155
+ },
156
+ "ecg_022a3f3a-7060-4ff8-b716-b75d8e0637c5.csv": {
157
+ "patient_info": {
158
+ "Organization": "Greenberg international school",
159
+ "Department": "General",
160
+ "Patient Name": "Afzal",
161
+ "Age": 46,
162
+ "Gender": "Male",
163
+ "Created At": "2025-07-21T07:40:50.401Z",
164
+ "ECG File Path": "ecg_uploads_greenwich/ecg_022a3f3a-7060-4ff8-b716-b75d8e0637c5.csv",
165
+ "Ai Result": "RBBB(0.0%)"
166
+ },
167
+ "endpoint_tests": {
168
+ "extract_features": {
169
+ "status": "success",
170
+ "data": {
171
+ "status": "success",
172
+ "processing_time_ms": 633.98,
173
+ "features": {
174
+ "count": 79872,
175
+ "dimension": 256,
176
+ "extraction_method": "ECG-FM pretrained model"
177
+ },
178
+ "physiological_parameters": {
179
+ "heart_rate": 60.0,
180
+ "qrs_duration": 80.2,
181
+ "qt_interval": 408.5,
182
+ "pr_interval": 160.7,
183
+ "qrs_axis": 29.6,
184
+ "extraction_method": "ECG-FM validated feature analysis",
185
+ "confidence": "High",
186
+ "feature_dimension": 79872,
187
+ "clinical_ranges": {
188
+ "heart_rate": "30-200 BPM",
189
+ "qrs_duration": "40-200 ms",
190
+ "qt_interval": "300-600 ms",
191
+ "pr_interval": "100-300 ms",
192
+ "qrs_axis": "-180\u00b0 to +180\u00b0"
193
+ },
194
+ "extraction_confidence": {
195
+ "heart_rate": "High",
196
+ "qrs_duration": "High",
197
+ "qt_interval": "High",
198
+ "pr_interval": "High",
199
+ "qrs_axis": "High"
200
+ }
201
+ },
202
+ "model_source": "wanglab/ecg-fm/mimic_iv_ecg_physionet_pretrained.pt"
203
+ }
204
+ },
205
+ "assess_quality": {
206
+ "status": "success",
207
+ "data": {
208
+ "status": "success",
209
+ "processing_time_ms": 5.76,
210
+ "quality": "Poor",
211
+ "metrics": {
212
+ "standard_deviation": 66.1427,
213
+ "signal_to_noise_ratio": 0.4547,
214
+ "baseline_wander": 9.3757,
215
+ "peak_to_peak": 1103.498,
216
+ "mean_amplitude": 30.0723
217
+ },
218
+ "assessment_method": "Statistical analysis + ECG-FM feature validation"
219
+ }
220
+ },
221
+ "predict": {
222
+ "status": "success",
223
+ "data": {
224
+ "prediction": "ECG analysis completed",
225
+ "confidence": 0.8,
226
+ "features": {},
227
+ "model_type": "ECG-FM Pretrained (fairseq_signals)",
228
+ "model_source": "wanglab/ecg-fm/mimic_iv_ecg_physionet_pretrained.pt"
229
+ }
230
+ }
231
+ }
232
+ }
233
+ }
finetuned_clinical_test_results_20250828_152404.json ADDED
@@ -0,0 +1,176 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "ecg_98408931-6f8e-47cc-954a-ba0c058a0f3d.csv": {
3
+ "patient_info": {
4
+ "Organization": "Greenberg international school",
5
+ "Department": "General",
6
+ "Patient Name": "Bharathi M K Teacher",
7
+ "Age": 31,
8
+ "Gender": "Female",
9
+ "Created At": "2025-07-21T10:10:05.716Z",
10
+ "ECG File Path": "ecg_uploads_greenwich/ecg_98408931-6f8e-47cc-954a-ba0c058a0f3d.csv",
11
+ "Ai Result": "No abnormality detected"
12
+ },
13
+ "endpoint_tests": {
14
+ "clinical_analysis": {
15
+ "status": "error",
16
+ "error": "Internal Server Error"
17
+ },
18
+ "direct_clinical": {
19
+ "status": "not_available"
20
+ },
21
+ "extract_features": {
22
+ "status": "success",
23
+ "data": {
24
+ "status": "success",
25
+ "processing_time_ms": 671.05,
26
+ "features": {
27
+ "count": 79872,
28
+ "dimension": 256,
29
+ "extraction_method": "ECG-FM pretrained model"
30
+ },
31
+ "physiological_parameters": {
32
+ "heart_rate": 60.0,
33
+ "qrs_duration": 150.8,
34
+ "qt_interval": 413.3,
35
+ "pr_interval": 159.1,
36
+ "qrs_axis": 30.1,
37
+ "extraction_method": "ECG-FM validated feature analysis",
38
+ "confidence": "High",
39
+ "feature_dimension": 79872,
40
+ "clinical_ranges": {
41
+ "heart_rate": "30-200 BPM",
42
+ "qrs_duration": "40-200 ms",
43
+ "qt_interval": "300-600 ms",
44
+ "pr_interval": "100-300 ms",
45
+ "qrs_axis": "-180\u00b0 to +180\u00b0"
46
+ },
47
+ "extraction_confidence": {
48
+ "heart_rate": "High",
49
+ "qrs_duration": "High",
50
+ "qt_interval": "High",
51
+ "pr_interval": "High",
52
+ "qrs_axis": "High"
53
+ }
54
+ },
55
+ "model_source": "wanglab/ecg-fm/mimic_iv_ecg_physionet_pretrained.pt"
56
+ }
57
+ }
58
+ }
59
+ },
60
+ "ecg_fc6d2ecb-7eb3-4eec-9281-17c24b7902b5.csv": {
61
+ "patient_info": {
62
+ "Organization": "Greenberg international school",
63
+ "Department": "General",
64
+ "Patient Name": "Sayida thasmiya Bhanu Teacher",
65
+ "Age": 29,
66
+ "Gender": "Female",
67
+ "Created At": "2025-07-21T07:22:38.484Z",
68
+ "ECG File Path": "ecg_uploads_greenwich/ecg_fc6d2ecb-7eb3-4eec-9281-17c24b7902b5.csv",
69
+ "Ai Result": "ST(29.1%)"
70
+ },
71
+ "endpoint_tests": {
72
+ "clinical_analysis": {
73
+ "status": "error",
74
+ "error": "Internal Server Error"
75
+ },
76
+ "direct_clinical": {
77
+ "status": "not_available"
78
+ },
79
+ "extract_features": {
80
+ "status": "success",
81
+ "data": {
82
+ "status": "success",
83
+ "processing_time_ms": 519.92,
84
+ "features": {
85
+ "count": 79872,
86
+ "dimension": 256,
87
+ "extraction_method": "ECG-FM pretrained model"
88
+ },
89
+ "physiological_parameters": {
90
+ "heart_rate": 59.7,
91
+ "qrs_duration": 157.0,
92
+ "qt_interval": 415.0,
93
+ "pr_interval": 160.9,
94
+ "qrs_axis": 28.3,
95
+ "extraction_method": "ECG-FM validated feature analysis",
96
+ "confidence": "High",
97
+ "feature_dimension": 79872,
98
+ "clinical_ranges": {
99
+ "heart_rate": "30-200 BPM",
100
+ "qrs_duration": "40-200 ms",
101
+ "qt_interval": "300-600 ms",
102
+ "pr_interval": "100-300 ms",
103
+ "qrs_axis": "-180\u00b0 to +180\u00b0"
104
+ },
105
+ "extraction_confidence": {
106
+ "heart_rate": "High",
107
+ "qrs_duration": "High",
108
+ "qt_interval": "High",
109
+ "pr_interval": "High",
110
+ "qrs_axis": "High"
111
+ }
112
+ },
113
+ "model_source": "wanglab/ecg-fm/mimic_iv_ecg_physionet_pretrained.pt"
114
+ }
115
+ }
116
+ }
117
+ },
118
+ "ecg_022a3f3a-7060-4ff8-b716-b75d8e0637c5.csv": {
119
+ "patient_info": {
120
+ "Organization": "Greenberg international school",
121
+ "Department": "General",
122
+ "Patient Name": "Afzal",
123
+ "Age": 46,
124
+ "Gender": "Male",
125
+ "Created At": "2025-07-21T07:40:50.401Z",
126
+ "ECG File Path": "ecg_uploads_greenwich/ecg_022a3f3a-7060-4ff8-b716-b75d8e0637c5.csv",
127
+ "Ai Result": "RBBB(0.0%)"
128
+ },
129
+ "endpoint_tests": {
130
+ "clinical_analysis": {
131
+ "status": "error",
132
+ "error": "Internal Server Error"
133
+ },
134
+ "direct_clinical": {
135
+ "status": "not_available"
136
+ },
137
+ "extract_features": {
138
+ "status": "success",
139
+ "data": {
140
+ "status": "success",
141
+ "processing_time_ms": 501.82,
142
+ "features": {
143
+ "count": 79872,
144
+ "dimension": 256,
145
+ "extraction_method": "ECG-FM pretrained model"
146
+ },
147
+ "physiological_parameters": {
148
+ "heart_rate": 60.0,
149
+ "qrs_duration": 80.2,
150
+ "qt_interval": 408.5,
151
+ "pr_interval": 160.7,
152
+ "qrs_axis": 29.6,
153
+ "extraction_method": "ECG-FM validated feature analysis",
154
+ "confidence": "High",
155
+ "feature_dimension": 79872,
156
+ "clinical_ranges": {
157
+ "heart_rate": "30-200 BPM",
158
+ "qrs_duration": "40-200 ms",
159
+ "qt_interval": "300-600 ms",
160
+ "pr_interval": "100-300 ms",
161
+ "qrs_axis": "-180\u00b0 to +180\u00b0"
162
+ },
163
+ "extraction_confidence": {
164
+ "heart_rate": "High",
165
+ "qrs_duration": "High",
166
+ "qt_interval": "High",
167
+ "pr_interval": "High",
168
+ "qrs_axis": "High"
169
+ }
170
+ },
171
+ "model_source": "wanglab/ecg-fm/mimic_iv_ecg_physionet_pretrained.pt"
172
+ }
173
+ }
174
+ }
175
+ }
176
+ }
physiological_parameter_test_results_20250828_145018.json ADDED
@@ -0,0 +1,227 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "ecg_98408931-6f8e-47cc-954a-ba0c058a0f3d.csv": {
3
+ "patient_info": {
4
+ "Organization": "Greenberg international school",
5
+ "Department": "General",
6
+ "Patient Name": "Bharathi M K Teacher",
7
+ "Age": 31,
8
+ "Gender": "Female",
9
+ "Created At": "2025-07-21T10:10:05.716Z",
10
+ "ECG File Path": "ecg_uploads_greenwich/ecg_98408931-6f8e-47cc-954a-ba0c058a0f3d.csv",
11
+ "Ai Result": "No abnormality detected"
12
+ },
13
+ "physiological_analysis": {
14
+ "status": "error",
15
+ "error": "Object of type int64 is not JSON serializable"
16
+ },
17
+ "endpoint_tests": {
18
+ "extract_features": {
19
+ "status": "success",
20
+ "data": {
21
+ "status": "success",
22
+ "processing_time_ms": 412.11,
23
+ "features": {
24
+ "count": 79872,
25
+ "dimension": 256,
26
+ "extraction_method": "ECG-FM pretrained model"
27
+ },
28
+ "physiological_parameters": {
29
+ "heart_rate": 60.0,
30
+ "qrs_duration": 150.8,
31
+ "qt_interval": 413.3,
32
+ "pr_interval": 159.1,
33
+ "qrs_axis": 30.1,
34
+ "extraction_method": "ECG-FM validated feature analysis",
35
+ "confidence": "High",
36
+ "feature_dimension": 79872,
37
+ "clinical_ranges": {
38
+ "heart_rate": "30-200 BPM",
39
+ "qrs_duration": "40-200 ms",
40
+ "qt_interval": "300-600 ms",
41
+ "pr_interval": "100-300 ms",
42
+ "qrs_axis": "-180\u00b0 to +180\u00b0"
43
+ },
44
+ "extraction_confidence": {
45
+ "heart_rate": "High",
46
+ "qrs_duration": "High",
47
+ "qt_interval": "High",
48
+ "pr_interval": "High",
49
+ "qrs_axis": "High"
50
+ }
51
+ },
52
+ "model_source": "wanglab/ecg-fm/mimic_iv_ecg_physionet_pretrained.pt"
53
+ }
54
+ },
55
+ "assess_quality": {
56
+ "status": "success",
57
+ "data": {
58
+ "status": "success",
59
+ "processing_time_ms": 3.94,
60
+ "quality": "Poor",
61
+ "metrics": {
62
+ "standard_deviation": 36.6422,
63
+ "signal_to_noise_ratio": 0.6119,
64
+ "baseline_wander": 5.6589,
65
+ "peak_to_peak": 411.0937,
66
+ "mean_amplitude": 22.4223
67
+ },
68
+ "assessment_method": "Statistical analysis + ECG-FM feature validation"
69
+ }
70
+ },
71
+ "predict": {
72
+ "status": "error",
73
+ "error": "{\"detail\":\"Prediction failed: forward() takes 1 positional argument but 2 were given\"}"
74
+ }
75
+ }
76
+ },
77
+ "ecg_fc6d2ecb-7eb3-4eec-9281-17c24b7902b5.csv": {
78
+ "patient_info": {
79
+ "Organization": "Greenberg international school",
80
+ "Department": "General",
81
+ "Patient Name": "Sayida thasmiya Bhanu Teacher",
82
+ "Age": 29,
83
+ "Gender": "Female",
84
+ "Created At": "2025-07-21T07:22:38.484Z",
85
+ "ECG File Path": "ecg_uploads_greenwich/ecg_fc6d2ecb-7eb3-4eec-9281-17c24b7902b5.csv",
86
+ "Ai Result": "ST(29.1%)"
87
+ },
88
+ "physiological_analysis": {
89
+ "status": "error",
90
+ "error": "Object of type int64 is not JSON serializable"
91
+ },
92
+ "endpoint_tests": {
93
+ "extract_features": {
94
+ "status": "success",
95
+ "data": {
96
+ "status": "success",
97
+ "processing_time_ms": 446.46,
98
+ "features": {
99
+ "count": 79872,
100
+ "dimension": 256,
101
+ "extraction_method": "ECG-FM pretrained model"
102
+ },
103
+ "physiological_parameters": {
104
+ "heart_rate": 59.7,
105
+ "qrs_duration": 157.0,
106
+ "qt_interval": 415.0,
107
+ "pr_interval": 160.9,
108
+ "qrs_axis": 28.3,
109
+ "extraction_method": "ECG-FM validated feature analysis",
110
+ "confidence": "High",
111
+ "feature_dimension": 79872,
112
+ "clinical_ranges": {
113
+ "heart_rate": "30-200 BPM",
114
+ "qrs_duration": "40-200 ms",
115
+ "qt_interval": "300-600 ms",
116
+ "pr_interval": "100-300 ms",
117
+ "qrs_axis": "-180\u00b0 to +180\u00b0"
118
+ },
119
+ "extraction_confidence": {
120
+ "heart_rate": "High",
121
+ "qrs_duration": "High",
122
+ "qt_interval": "High",
123
+ "pr_interval": "High",
124
+ "qrs_axis": "High"
125
+ }
126
+ },
127
+ "model_source": "wanglab/ecg-fm/mimic_iv_ecg_physionet_pretrained.pt"
128
+ }
129
+ },
130
+ "assess_quality": {
131
+ "status": "success",
132
+ "data": {
133
+ "status": "success",
134
+ "processing_time_ms": 12.54,
135
+ "quality": "Poor",
136
+ "metrics": {
137
+ "standard_deviation": 46.0951,
138
+ "signal_to_noise_ratio": 0.364,
139
+ "baseline_wander": 9.0349,
140
+ "peak_to_peak": 837.1298,
141
+ "mean_amplitude": 16.7801
142
+ },
143
+ "assessment_method": "Statistical analysis + ECG-FM feature validation"
144
+ }
145
+ },
146
+ "predict": {
147
+ "status": "error",
148
+ "error": "{\"detail\":\"Prediction failed: forward() takes 1 positional argument but 2 were given\"}"
149
+ }
150
+ }
151
+ },
152
+ "ecg_022a3f3a-7060-4ff8-b716-b75d8e0637c5.csv": {
153
+ "patient_info": {
154
+ "Organization": "Greenberg international school",
155
+ "Department": "General",
156
+ "Patient Name": "Afzal",
157
+ "Age": 46,
158
+ "Gender": "Male",
159
+ "Created At": "2025-07-21T07:40:50.401Z",
160
+ "ECG File Path": "ecg_uploads_greenwich/ecg_022a3f3a-7060-4ff8-b716-b75d8e0637c5.csv",
161
+ "Ai Result": "RBBB(0.0%)"
162
+ },
163
+ "physiological_analysis": {
164
+ "status": "error",
165
+ "error": "Object of type int64 is not JSON serializable"
166
+ },
167
+ "endpoint_tests": {
168
+ "extract_features": {
169
+ "status": "success",
170
+ "data": {
171
+ "status": "success",
172
+ "processing_time_ms": 405.26,
173
+ "features": {
174
+ "count": 79872,
175
+ "dimension": 256,
176
+ "extraction_method": "ECG-FM pretrained model"
177
+ },
178
+ "physiological_parameters": {
179
+ "heart_rate": 60.0,
180
+ "qrs_duration": 80.2,
181
+ "qt_interval": 408.5,
182
+ "pr_interval": 160.7,
183
+ "qrs_axis": 29.6,
184
+ "extraction_method": "ECG-FM validated feature analysis",
185
+ "confidence": "High",
186
+ "feature_dimension": 79872,
187
+ "clinical_ranges": {
188
+ "heart_rate": "30-200 BPM",
189
+ "qrs_duration": "40-200 ms",
190
+ "qt_interval": "300-600 ms",
191
+ "pr_interval": "100-300 ms",
192
+ "qrs_axis": "-180\u00b0 to +180\u00b0"
193
+ },
194
+ "extraction_confidence": {
195
+ "heart_rate": "High",
196
+ "qrs_duration": "High",
197
+ "qt_interval": "High",
198
+ "pr_interval": "High",
199
+ "qrs_axis": "High"
200
+ }
201
+ },
202
+ "model_source": "wanglab/ecg-fm/mimic_iv_ecg_physionet_pretrained.pt"
203
+ }
204
+ },
205
+ "assess_quality": {
206
+ "status": "success",
207
+ "data": {
208
+ "status": "success",
209
+ "processing_time_ms": 7.92,
210
+ "quality": "Poor",
211
+ "metrics": {
212
+ "standard_deviation": 66.1427,
213
+ "signal_to_noise_ratio": 0.4547,
214
+ "baseline_wander": 9.3757,
215
+ "peak_to_peak": 1103.498,
216
+ "mean_amplitude": 30.0723
217
+ },
218
+ "assessment_method": "Statistical analysis + ECG-FM feature validation"
219
+ }
220
+ },
221
+ "predict": {
222
+ "status": "error",
223
+ "error": "{\"detail\":\"Prediction failed: forward() takes 1 positional argument but 2 were given\"}"
224
+ }
225
+ }
226
+ }
227
+ }
physiological_parameter_test_results_20250828_150828.json ADDED
@@ -0,0 +1,245 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "ecg_98408931-6f8e-47cc-954a-ba0c058a0f3d.csv": {
3
+ "patient_info": {
4
+ "Organization": "Greenberg international school",
5
+ "Department": "General",
6
+ "Patient Name": "Bharathi M K Teacher",
7
+ "Age": 31,
8
+ "Gender": "Female",
9
+ "Created At": "2025-07-21T10:10:05.716Z",
10
+ "ECG File Path": "ecg_uploads_greenwich/ecg_98408931-6f8e-47cc-954a-ba0c058a0f3d.csv",
11
+ "Ai Result": "No abnormality detected"
12
+ },
13
+ "physiological_analysis": {
14
+ "status": "error",
15
+ "error": "Object of type int64 is not JSON serializable"
16
+ },
17
+ "endpoint_tests": {
18
+ "extract_features": {
19
+ "status": "success",
20
+ "data": {
21
+ "status": "success",
22
+ "processing_time_ms": 778.07,
23
+ "features": {
24
+ "count": 79872,
25
+ "dimension": 256,
26
+ "extraction_method": "ECG-FM pretrained model"
27
+ },
28
+ "physiological_parameters": {
29
+ "heart_rate": 60.0,
30
+ "qrs_duration": 150.8,
31
+ "qt_interval": 413.3,
32
+ "pr_interval": 159.1,
33
+ "qrs_axis": 30.1,
34
+ "extraction_method": "ECG-FM validated feature analysis",
35
+ "confidence": "High",
36
+ "feature_dimension": 79872,
37
+ "clinical_ranges": {
38
+ "heart_rate": "30-200 BPM",
39
+ "qrs_duration": "40-200 ms",
40
+ "qt_interval": "300-600 ms",
41
+ "pr_interval": "100-300 ms",
42
+ "qrs_axis": "-180\u00b0 to +180\u00b0"
43
+ },
44
+ "extraction_confidence": {
45
+ "heart_rate": "High",
46
+ "qrs_duration": "High",
47
+ "qt_interval": "High",
48
+ "pr_interval": "High",
49
+ "qrs_axis": "High"
50
+ }
51
+ },
52
+ "model_source": "wanglab/ecg-fm/mimic_iv_ecg_physionet_pretrained.pt"
53
+ }
54
+ },
55
+ "assess_quality": {
56
+ "status": "success",
57
+ "data": {
58
+ "status": "success",
59
+ "processing_time_ms": 6.66,
60
+ "quality": "Poor",
61
+ "metrics": {
62
+ "standard_deviation": 36.6422,
63
+ "signal_to_noise_ratio": 0.6119,
64
+ "baseline_wander": 5.6589,
65
+ "peak_to_peak": 411.0937,
66
+ "mean_amplitude": 22.4223
67
+ },
68
+ "assessment_method": "Statistical analysis + ECG-FM feature validation"
69
+ }
70
+ },
71
+ "predict": {
72
+ "status": "success",
73
+ "data": {
74
+ "prediction": "ECG analysis completed",
75
+ "confidence": 0.8,
76
+ "features": {},
77
+ "model_type": "ECG-FM Pretrained (fairseq_signals)",
78
+ "model_source": "wanglab/ecg-fm/mimic_iv_ecg_physionet_pretrained.pt"
79
+ }
80
+ }
81
+ }
82
+ },
83
+ "ecg_fc6d2ecb-7eb3-4eec-9281-17c24b7902b5.csv": {
84
+ "patient_info": {
85
+ "Organization": "Greenberg international school",
86
+ "Department": "General",
87
+ "Patient Name": "Sayida thasmiya Bhanu Teacher",
88
+ "Age": 29,
89
+ "Gender": "Female",
90
+ "Created At": "2025-07-21T07:22:38.484Z",
91
+ "ECG File Path": "ecg_uploads_greenwich/ecg_fc6d2ecb-7eb3-4eec-9281-17c24b7902b5.csv",
92
+ "Ai Result": "ST(29.1%)"
93
+ },
94
+ "physiological_analysis": {
95
+ "status": "error",
96
+ "error": "Object of type int64 is not JSON serializable"
97
+ },
98
+ "endpoint_tests": {
99
+ "extract_features": {
100
+ "status": "success",
101
+ "data": {
102
+ "status": "success",
103
+ "processing_time_ms": 402.7,
104
+ "features": {
105
+ "count": 79872,
106
+ "dimension": 256,
107
+ "extraction_method": "ECG-FM pretrained model"
108
+ },
109
+ "physiological_parameters": {
110
+ "heart_rate": 59.7,
111
+ "qrs_duration": 157.0,
112
+ "qt_interval": 415.0,
113
+ "pr_interval": 160.9,
114
+ "qrs_axis": 28.3,
115
+ "extraction_method": "ECG-FM validated feature analysis",
116
+ "confidence": "High",
117
+ "feature_dimension": 79872,
118
+ "clinical_ranges": {
119
+ "heart_rate": "30-200 BPM",
120
+ "qrs_duration": "40-200 ms",
121
+ "qt_interval": "300-600 ms",
122
+ "pr_interval": "100-300 ms",
123
+ "qrs_axis": "-180\u00b0 to +180\u00b0"
124
+ },
125
+ "extraction_confidence": {
126
+ "heart_rate": "High",
127
+ "qrs_duration": "High",
128
+ "qt_interval": "High",
129
+ "pr_interval": "High",
130
+ "qrs_axis": "High"
131
+ }
132
+ },
133
+ "model_source": "wanglab/ecg-fm/mimic_iv_ecg_physionet_pretrained.pt"
134
+ }
135
+ },
136
+ "assess_quality": {
137
+ "status": "success",
138
+ "data": {
139
+ "status": "success",
140
+ "processing_time_ms": 8.91,
141
+ "quality": "Poor",
142
+ "metrics": {
143
+ "standard_deviation": 46.0951,
144
+ "signal_to_noise_ratio": 0.364,
145
+ "baseline_wander": 9.0349,
146
+ "peak_to_peak": 837.1298,
147
+ "mean_amplitude": 16.7801
148
+ },
149
+ "assessment_method": "Statistical analysis + ECG-FM feature validation"
150
+ }
151
+ },
152
+ "predict": {
153
+ "status": "success",
154
+ "data": {
155
+ "prediction": "ECG analysis completed",
156
+ "confidence": 0.8,
157
+ "features": {},
158
+ "model_type": "ECG-FM Pretrained (fairseq_signals)",
159
+ "model_source": "wanglab/ecg-fm/mimic_iv_ecg_physionet_pretrained.pt"
160
+ }
161
+ }
162
+ }
163
+ },
164
+ "ecg_022a3f3a-7060-4ff8-b716-b75d8e0637c5.csv": {
165
+ "patient_info": {
166
+ "Organization": "Greenberg international school",
167
+ "Department": "General",
168
+ "Patient Name": "Afzal",
169
+ "Age": 46,
170
+ "Gender": "Male",
171
+ "Created At": "2025-07-21T07:40:50.401Z",
172
+ "ECG File Path": "ecg_uploads_greenwich/ecg_022a3f3a-7060-4ff8-b716-b75d8e0637c5.csv",
173
+ "Ai Result": "RBBB(0.0%)"
174
+ },
175
+ "physiological_analysis": {
176
+ "status": "error",
177
+ "error": "Object of type int64 is not JSON serializable"
178
+ },
179
+ "endpoint_tests": {
180
+ "extract_features": {
181
+ "status": "success",
182
+ "data": {
183
+ "status": "success",
184
+ "processing_time_ms": 376.8,
185
+ "features": {
186
+ "count": 79872,
187
+ "dimension": 256,
188
+ "extraction_method": "ECG-FM pretrained model"
189
+ },
190
+ "physiological_parameters": {
191
+ "heart_rate": 60.0,
192
+ "qrs_duration": 80.2,
193
+ "qt_interval": 408.5,
194
+ "pr_interval": 160.7,
195
+ "qrs_axis": 29.6,
196
+ "extraction_method": "ECG-FM validated feature analysis",
197
+ "confidence": "High",
198
+ "feature_dimension": 79872,
199
+ "clinical_ranges": {
200
+ "heart_rate": "30-200 BPM",
201
+ "qrs_duration": "40-200 ms",
202
+ "qt_interval": "300-600 ms",
203
+ "pr_interval": "100-300 ms",
204
+ "qrs_axis": "-180\u00b0 to +180\u00b0"
205
+ },
206
+ "extraction_confidence": {
207
+ "heart_rate": "High",
208
+ "qrs_duration": "High",
209
+ "qt_interval": "High",
210
+ "pr_interval": "High",
211
+ "qrs_axis": "High"
212
+ }
213
+ },
214
+ "model_source": "wanglab/ecg-fm/mimic_iv_ecg_physionet_pretrained.pt"
215
+ }
216
+ },
217
+ "assess_quality": {
218
+ "status": "success",
219
+ "data": {
220
+ "status": "success",
221
+ "processing_time_ms": 4.79,
222
+ "quality": "Poor",
223
+ "metrics": {
224
+ "standard_deviation": 66.1427,
225
+ "signal_to_noise_ratio": 0.4547,
226
+ "baseline_wander": 9.3757,
227
+ "peak_to_peak": 1103.498,
228
+ "mean_amplitude": 30.0723
229
+ },
230
+ "assessment_method": "Statistical analysis + ECG-FM feature validation"
231
+ }
232
+ },
233
+ "predict": {
234
+ "status": "success",
235
+ "data": {
236
+ "prediction": "ECG analysis completed",
237
+ "confidence": 0.8,
238
+ "features": {},
239
+ "model_type": "ECG-FM Pretrained (fairseq_signals)",
240
+ "model_source": "wanglab/ecg-fm/mimic_iv_ecg_physionet_pretrained.pt"
241
+ }
242
+ }
243
+ }
244
+ }
245
+ }
quick_test_fix.py ADDED
@@ -0,0 +1,123 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ Quick Test to Verify JSON Serialization Fix
4
+ Tests the /analyze endpoint with a simple ECG sample
5
+ """
6
+
7
+ import requests
8
+ import numpy as np
9
+ import json
10
+
11
+ # Configuration
12
+ API_BASE_URL = "https://mystic-cbk-ecg-fm-api.hf.space"
13
+
14
+ def create_test_ecg():
15
+ """Create a simple test ECG signal"""
16
+ # Generate a simple 10-second ECG-like signal at 500 Hz
17
+ t = np.linspace(0, 10, 5000)
18
+
19
+ # Create a simple ECG-like waveform
20
+ signal = []
21
+ for lead in range(12):
22
+ # Basic sine wave with some variation
23
+ lead_signal = np.sin(2 * np.pi * 1.2 * t) * 0.5 # ~72 BPM
24
+ lead_signal += np.random.normal(0, 0.1, 5000) # Add noise
25
+ signal.append(lead_signal.tolist())
26
+
27
+ return signal
28
+
29
+ def test_analyze_endpoint():
30
+ """Test the /analyze endpoint with the fix"""
31
+ print("πŸ§ͺ Testing /analyze endpoint with JSON serialization fix...")
32
+
33
+ # Create test ECG data
34
+ ecg_data = create_test_ecg()
35
+
36
+ payload = {
37
+ "signal": ecg_data,
38
+ "fs": 500,
39
+ "patient_age": 30,
40
+ "patient_gender": "M"
41
+ }
42
+
43
+ try:
44
+ print("πŸ“€ Sending test ECG data...")
45
+ print(f"πŸ“Š Input: {len(ecg_data)} leads Γ— {len(ecg_data[0])} samples")
46
+
47
+ response = requests.post(f"{API_BASE_URL}/analyze", json=payload, timeout=120)
48
+
49
+ if response.status_code == 200:
50
+ result = response.json()
51
+ print("βœ… SUCCESS! /analyze endpoint working!")
52
+
53
+ # Check physiological parameters
54
+ physio = result.get('physiological_parameters', {})
55
+ print(f"\nπŸ“Š PHYSIOLOGICAL PARAMETERS:")
56
+ print(f" Heart Rate: {physio.get('heart_rate')} BPM")
57
+ print(f" QRS Duration: {physio.get('qrs_duration')} ms")
58
+ print(f" QT Interval: {physio.get('qt_interval')} ms")
59
+ print(f" PR Interval: {physio.get('pr_interval')} ms")
60
+ print(f" QRS Axis: {physio.get('qrs_axis')}Β°")
61
+
62
+ # Check features
63
+ features = result.get('features', {})
64
+ print(f"\n🧬 FEATURES:")
65
+ print(f" Count: {features.get('count')}")
66
+ print(f" Dimension: {features.get('dimension')}")
67
+ print(f" Status: {features.get('extraction_status')}")
68
+
69
+ # Check clinical analysis
70
+ clinical = result.get('clinical_analysis', {})
71
+ if clinical:
72
+ print(f"\nπŸ₯ CLINICAL ANALYSIS:")
73
+ print(f" Method: {clinical.get('method')}")
74
+ print(f" Confidence: {clinical.get('confidence')}")
75
+
76
+ return True
77
+
78
+ else:
79
+ print(f"❌ Failed: {response.status_code}")
80
+ print(f" Error: {response.text}")
81
+ return False
82
+
83
+ except Exception as e:
84
+ print(f"❌ Error: {e}")
85
+ return False
86
+
87
+ def test_health():
88
+ """Test API health"""
89
+ try:
90
+ response = requests.get(f"{API_BASE_URL}/health", timeout=30)
91
+ if response.status_code == 200:
92
+ health_data = response.json()
93
+ print(f"βœ… API Healthy - Models loaded: {health_data.get('models_loaded')}")
94
+ return True
95
+ else:
96
+ print(f"❌ Health check failed: {response.status_code}")
97
+ return False
98
+ except Exception as e:
99
+ print(f"❌ Health check error: {e}")
100
+ return False
101
+
102
+ def main():
103
+ """Main test function"""
104
+ print("πŸš€ QUICK TEST - JSON Serialization Fix Verification")
105
+ print("=" * 60)
106
+
107
+ # Test 1: Health check
108
+ print("\n1️⃣ Testing API health...")
109
+ if not test_health():
110
+ print("❌ API not healthy, cannot proceed")
111
+ return
112
+
113
+ # Test 2: Analyze endpoint
114
+ print("\n2️⃣ Testing /analyze endpoint...")
115
+ if test_analyze_endpoint():
116
+ print("\nπŸŽ‰ SUCCESS! JSON serialization fix is working!")
117
+ print(" All endpoints should now function correctly.")
118
+ else:
119
+ print("\n❌ /analyze endpoint still has issues")
120
+ print(" May need to wait for deployment to complete.")
121
+
122
+ if __name__ == "__main__":
123
+ main()
simple_finetuned_test.py ADDED
@@ -0,0 +1,124 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ Simple Test for Finetuned Model Output
4
+ Tests what the finetuned model actually returns
5
+ """
6
+
7
+ import requests
8
+ import json
9
+ import numpy as np
10
+
11
+ # Configuration
12
+ API_BASE_URL = "https://mystic-cbk-ecg-fm-api.hf.space"
13
+
14
+ def test_finetuned_model_output():
15
+ """Test what the finetuned model actually returns"""
16
+ print("🧬 TESTING FINETUNED MODEL OUTPUT FORMAT")
17
+ print("=" * 60)
18
+
19
+ # Create a very simple test ECG signal
20
+ test_signal = []
21
+ for lead in range(12): # 12 leads
22
+ samples = []
23
+ for i in range(1000): # 2 seconds at 500Hz (shorter for testing)
24
+ samples.append(np.sin(2 * np.pi * 1.2 * i / 500) * 0.5)
25
+ test_signal.append(samples)
26
+
27
+ payload = {"signal": test_signal, "fs": 500}
28
+
29
+ print("πŸ§ͺ Testing with simple ECG signal...")
30
+ print(f" Signal shape: {len(test_signal)} leads, {len(test_signal[0])} samples")
31
+
32
+ # Test 1: Check API status
33
+ print("\n1️⃣ Checking API status...")
34
+ try:
35
+ response = requests.get(f"{API_BASE_URL}/health", timeout=30)
36
+ if response.status_code == 200:
37
+ print(" βœ… API is healthy")
38
+ else:
39
+ print(f" ❌ API health check failed: {response.status_code}")
40
+ return
41
+ except Exception as e:
42
+ print(f" ❌ API health check error: {e}")
43
+ return
44
+
45
+ # Test 2: Check model info
46
+ print("\n2️⃣ Checking model info...")
47
+ try:
48
+ response = requests.get(f"{API_BASE_URL}/info", timeout=30)
49
+ if response.status_code == 200:
50
+ info = response.json()
51
+ print(" βœ… Got model info")
52
+
53
+ # Check model status
54
+ models = info.get('models', {})
55
+ pretrained_status = models.get('pretrained', {}).get('status', 'Unknown')
56
+ finetuned_status = models.get('finetuned', {}).get('status', 'Unknown')
57
+
58
+ print(f" 🧬 Pretrained Model: {pretrained_status}")
59
+ print(f" πŸ₯ Finetuned Model: {finetuned_status}")
60
+
61
+ if finetuned_status != 'Loaded':
62
+ print(" ❌ Finetuned model not loaded - this is the problem!")
63
+ return
64
+ else:
65
+ print(f" ❌ Failed to get model info: {response.status_code}")
66
+ return
67
+ except Exception as e:
68
+ print(f" ❌ Error getting model info: {e}")
69
+ return
70
+
71
+ # Test 3: Test individual endpoints to isolate the issue
72
+ print("\n3️⃣ Testing individual endpoints...")
73
+
74
+ # Test extract_features (should work)
75
+ try:
76
+ response = requests.post(f"{API_BASE_URL}/extract_features", json=payload, timeout=30)
77
+ print(f" πŸ“Š Extract Features: {response.status_code}")
78
+ if response.status_code == 200:
79
+ print(" βœ… Features endpoint working")
80
+ else:
81
+ print(f" ❌ Features endpoint failed: {response.text}")
82
+ except Exception as e:
83
+ print(f" ❌ Features endpoint error: {e}")
84
+
85
+ # Test predict (should work)
86
+ try:
87
+ response = requests.post(f"{API_BASE_URL}/predict", json=payload, timeout=30)
88
+ print(f" πŸ“Š Predict: {response.status_code}")
89
+ if response.status_code == 200:
90
+ print(" βœ… Predict endpoint working")
91
+ else:
92
+ print(f" ❌ Predict endpoint failed: {response.text}")
93
+ except Exception as e:
94
+ print(f" ❌ Predict endpoint error: {e}")
95
+
96
+ # Test 4: Try to call analyze with detailed error logging
97
+ print("\n4️⃣ Testing /analyze endpoint with detailed logging...")
98
+ try:
99
+ response = requests.post(f"{API_BASE_URL}/analyze", json=payload, timeout=60)
100
+ print(f" πŸ“Š Response Status: {response.status_code}")
101
+
102
+ if response.status_code == 200:
103
+ result = response.json()
104
+ print(" βœ… SUCCESS! /analyze endpoint working!")
105
+ print(f" πŸ₯ Clinical Analysis: {result.get('clinical_analysis', 'Not found')}")
106
+ print(f" πŸ“Š Physiological Parameters: {result.get('physiological_parameters', 'Not found')}")
107
+ else:
108
+ print(f" ❌ FAILED: {response.status_code}")
109
+ print(f" πŸ“ Error Response: {response.text}")
110
+
111
+ # Try to parse error details
112
+ try:
113
+ error_detail = response.json()
114
+ print(f" πŸ” Parsed Error: {json.dumps(error_detail, indent=2)}")
115
+ except:
116
+ print(f" πŸ“ Raw Error: {response.text}")
117
+
118
+ except Exception as e:
119
+ print(f" ❌ Exception during /analyze call: {e}")
120
+ import traceback
121
+ traceback.print_exc()
122
+
123
+ if __name__ == "__main__":
124
+ test_finetuned_model_output()
test_endpoints_status.py ADDED
@@ -0,0 +1,124 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ Test All Endpoints Status
4
+ Check the current status of all ECG-FM API endpoints
5
+ """
6
+
7
+ import requests
8
+ import json
9
+
10
+ # Configuration
11
+ API_BASE_URL = "https://mystic-cbk-ecg-fm-api.hf.space"
12
+
13
+ def test_endpoint(endpoint, method="GET", payload=None):
14
+ """Test a specific endpoint"""
15
+ print(f"πŸ§ͺ Testing {endpoint}...")
16
+
17
+ try:
18
+ if method == "GET":
19
+ response = requests.get(f"{API_BASE_URL}{endpoint}", timeout=30)
20
+ else:
21
+ response = requests.post(f"{API_BASE_URL}{endpoint}", json=payload, timeout=60)
22
+
23
+ print(f" Status: {response.status_code}")
24
+
25
+ if response.status_code == 200:
26
+ try:
27
+ result = response.json()
28
+ print(f" βœ… Success - Response received")
29
+
30
+ # Show key information based on endpoint
31
+ if endpoint == "/health":
32
+ print(f" Models loaded: {result.get('models_loaded')}")
33
+ print(f" Fairseq available: {result.get('fairseq_signals_available')}")
34
+ elif endpoint == "/info":
35
+ print(f" Model repo: {result.get('model_repo')}")
36
+ print(f" Loading strategy: {result.get('loading_strategy')}")
37
+ elif endpoint == "/extract_features":
38
+ features = result.get('features', {})
39
+ print(f" Feature count: {features.get('count')}")
40
+ print(f" Feature dimension: {features.get('dimension')}")
41
+ physio = result.get('physiological_parameters', {})
42
+ if physio.get('heart_rate'):
43
+ print(f" Heart Rate: {physio['heart_rate']} BPM")
44
+ elif endpoint == "/assess_quality":
45
+ print(f" Quality: {result.get('quality')}")
46
+ metrics = result.get('metrics', {})
47
+ print(f" SNR: {metrics.get('signal_to_noise_ratio')}")
48
+
49
+ return True
50
+
51
+ except json.JSONDecodeError:
52
+ print(f" ⚠️ Response received but not JSON: {response.text[:100]}...")
53
+ return True
54
+ else:
55
+ print(f" ❌ Failed: {response.text[:200]}...")
56
+ return False
57
+
58
+ except Exception as e:
59
+ print(f" ❌ Error: {e}")
60
+ return False
61
+
62
+ def main():
63
+ """Test all endpoints"""
64
+ print("πŸš€ TESTING ALL ECG-FM API ENDPOINTS")
65
+ print("=" * 60)
66
+
67
+ results = {}
68
+
69
+ # Test 1: Health check
70
+ print("\n1️⃣ Health Check")
71
+ results['health'] = test_endpoint("/health")
72
+
73
+ # Test 2: Info endpoint
74
+ print("\n2️⃣ Info Endpoint")
75
+ results['info'] = test_endpoint("/info")
76
+
77
+ # Test 3: Root endpoint
78
+ print("\n3️⃣ Root Endpoint")
79
+ results['root'] = test_endpoint("/")
80
+
81
+ # Test 4: Extract Features (with simple test data)
82
+ print("\n4️⃣ Extract Features Endpoint")
83
+ test_payload = {
84
+ "signal": [[0.1] * 1000] * 12, # Simple 12-lead, 1000-sample test data
85
+ "fs": 500
86
+ }
87
+ results['extract_features'] = test_endpoint("/extract_features", "POST", test_payload)
88
+
89
+ # Test 5: Assess Quality
90
+ print("\n5️⃣ Assess Quality Endpoint")
91
+ results['assess_quality'] = test_endpoint("/assess_quality", "POST", test_payload)
92
+
93
+ # Test 6: Predict endpoint
94
+ print("\n6️⃣ Predict Endpoint")
95
+ results['predict'] = test_endpoint("/predict", "POST", test_payload)
96
+
97
+ # Test 7: Analyze endpoint (comprehensive)
98
+ print("\n7️⃣ Analyze Endpoint (Comprehensive)")
99
+ results['analyze'] = test_endpoint("/analyze", "POST", test_payload)
100
+
101
+ # Summary
102
+ print(f"\nπŸ“Š ENDPOINT STATUS SUMMARY")
103
+ print(f"=" * 60)
104
+
105
+ working_endpoints = sum(results.values())
106
+ total_endpoints = len(results)
107
+
108
+ for endpoint, status in results.items():
109
+ status_icon = "βœ…" if status else "❌"
110
+ print(f"{status_icon} {endpoint}: {'Working' if status else 'Failed'}")
111
+
112
+ print(f"\n🎯 OVERALL STATUS:")
113
+ print(f" Working: {working_endpoints}/{total_endpoints}")
114
+ print(f" Success Rate: {(working_endpoints/total_endpoints)*100:.1f}%")
115
+
116
+ if working_endpoints == total_endpoints:
117
+ print(f"\nπŸŽ‰ ALL ENDPOINTS ARE WORKING!")
118
+ elif working_endpoints > total_endpoints // 2:
119
+ print(f"\n⚠️ MOST ENDPOINTS WORKING - Some issues to resolve")
120
+ else:
121
+ print(f"\n❌ MANY ENDPOINTS FAILING - Need investigation")
122
+
123
+ if __name__ == "__main__":
124
+ main()
test_finetuned_clinical.py ADDED
@@ -0,0 +1,323 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ Test Finetuned ECG-FM Model for Clinical Abnormality Detection
4
+ Tests the finetuned model to get normal vs abnormal classification results
5
+ """
6
+
7
+ import requests
8
+ import numpy as np
9
+ import pandas as pd
10
+ import json
11
+ import os
12
+ from typing import Dict, Any, List
13
+ from datetime import datetime
14
+
15
+ # Configuration
16
+ API_BASE_URL = "https://mystic-cbk-ecg-fm-api.hf.space"
17
+ ECG_DIR = "../ecg_uploads_greenwich/"
18
+ INDEX_FILE = "../Greenwichschooldata.csv"
19
+
20
+ def load_ecg_data(csv_file: str) -> List[List[float]]:
21
+ """Load ECG data from CSV file"""
22
+ try:
23
+ df = pd.read_csv(csv_file)
24
+ ecg_data = []
25
+ for lead in df.columns:
26
+ ecg_data.append(df[lead].astype(float).tolist())
27
+ return ecg_data
28
+ except Exception as e:
29
+ print(f"❌ Error loading ECG data: {e}")
30
+ return None
31
+
32
+ def test_finetuned_clinical_classification(ecg_data: List[List[float]], patient_info: Dict[str, Any]) -> Dict[str, Any]:
33
+ """Test the finetuned model for clinical abnormality detection"""
34
+ results = {}
35
+
36
+ print(f"🧬 Testing FINETUNED MODEL for {patient_info.get('Patient Name', 'Unknown')}")
37
+ print(f" πŸ‘€ Patient: {patient_info.get('Patient Name', 'Unknown')} ({patient_info.get('Age', 'Unknown')} {patient_info.get('Gender', 'Unknown')})")
38
+
39
+ # Test 1: Clinical Analysis (Finetuned Model)
40
+ print("1️⃣ Testing /analyze endpoint (FINETUNED MODEL)...")
41
+ try:
42
+ payload = {"signal": ecg_data, "fs": 500}
43
+ response = requests.post(f"{API_BASE_URL}/analyze", json=payload, timeout=60)
44
+
45
+ if response.status_code == 200:
46
+ result = response.json()
47
+ print(f" βœ… Clinical analysis completed successfully!")
48
+
49
+ # Extract clinical predictions
50
+ clinical = result.get('clinical_analysis', {})
51
+ if clinical:
52
+ print(f" πŸ₯ CLINICAL RESULTS:")
53
+ print(f" πŸ“Š Overall Status: {clinical.get('overall_status', 'Unknown')}")
54
+ print(f" 🎯 Primary Finding: {clinical.get('primary_finding', 'Unknown')}")
55
+ print(f" ⚠️ Abnormalities Detected: {clinical.get('abnormalities_detected', 'Unknown')}")
56
+ print(f" πŸ“‹ Labels Used: {clinical.get('labels_used', 'Unknown')}")
57
+ print(f" πŸ” Confidence Level: {clinical.get('confidence_level', 'Unknown')}")
58
+
59
+ # Show top clinical labels
60
+ label_probs = clinical.get('label_probabilities', {})
61
+ if label_probs:
62
+ print(f" 🏷️ TOP CLINICAL LABELS:")
63
+ sorted_labels = sorted(label_probs.items(), key=lambda x: x[1], reverse=True)[:5]
64
+ for label, prob in sorted_labels:
65
+ print(f" β€’ {label}: {prob:.3f}")
66
+
67
+ results['clinical_analysis'] = {"status": "success", "data": result}
68
+ else:
69
+ print(f" ⚠️ No clinical analysis data found")
70
+ results['clinical_analysis'] = {"status": "warning", "message": "No clinical data"}
71
+ else:
72
+ print(f" ❌ Failed: {response.status_code}")
73
+ print(f" Error: {response.text}")
74
+ results['clinical_analysis'] = {"status": "error", "error": response.text}
75
+ except Exception as e:
76
+ print(f" ❌ Error: {e}")
77
+ results['clinical_analysis'] = {"status": "error", "error": str(e)}
78
+
79
+ # Test 2: Direct Clinical Endpoint (if available)
80
+ print("2️⃣ Testing clinical endpoint directly...")
81
+ try:
82
+ # Try to call a clinical-specific endpoint if it exists
83
+ payload = {"signal": ecg_data, "fs": 500}
84
+ response = requests.post(f"{API_BASE_URL}/clinical", json=payload, timeout=60)
85
+
86
+ if response.status_code == 200:
87
+ result = response.json()
88
+ print(f" βœ… Direct clinical endpoint working!")
89
+ print(f" πŸ“Š Result: {result}")
90
+ results['direct_clinical'] = {"status": "success", "data": result}
91
+ elif response.status_code == 404:
92
+ print(f" ℹ️ Direct clinical endpoint not available (using /analyze)")
93
+ results['direct_clinical'] = {"status": "not_available"}
94
+ else:
95
+ print(f" ❌ Failed: {response.status_code}")
96
+ results['direct_clinical'] = {"status": "error", "error": response.text}
97
+ except Exception as e:
98
+ print(f" ℹ️ Direct clinical endpoint not available: {e}")
99
+ results['direct_clinical'] = {"status": "not_available"}
100
+
101
+ # Test 3: Extract Features + Clinical Analysis
102
+ print("3️⃣ Testing feature extraction + clinical analysis...")
103
+ try:
104
+ payload = {"signal": ecg_data, "fs": 500}
105
+ response = requests.post(f"{API_BASE_URL}/extract_features", json=payload, timeout=60)
106
+
107
+ if response.status_code == 200:
108
+ result = response.json()
109
+ print(f" βœ… Features extracted successfully")
110
+ print(f" πŸ“Š Feature count: {result.get('features', {}).get('count', 'Unknown')}")
111
+ print(f" πŸ“Š Feature dimension: {result.get('features', {}).get('dimension', 'Unknown')}")
112
+
113
+ # Check if clinical analysis is included
114
+ clinical_included = result.get('clinical_analysis', {})
115
+ if clinical_included:
116
+ print(f" πŸ₯ Clinical analysis included in features!")
117
+ print(f" πŸ“Š Status: {clinical_included.get('overall_status', 'Unknown')}")
118
+ else:
119
+ print(f" ℹ️ Clinical analysis not included in features endpoint")
120
+
121
+ results['extract_features'] = {"status": "success", "data": result}
122
+ else:
123
+ print(f" ❌ Failed: {response.status_code}")
124
+ results['extract_features'] = {"status": "error", "error": response.text}
125
+ except Exception as e:
126
+ print(f" ❌ Error: {e}")
127
+ results['extract_features'] = {"status": "error", "error": str(e)}
128
+
129
+ return results
130
+
131
+ def analyze_clinical_results(all_results: Dict[str, Any]) -> Dict[str, Any]:
132
+ """Analyze clinical classification results across samples"""
133
+ print(f"\nπŸ₯ CLINICAL CLASSIFICATION ANALYSIS")
134
+ print(f"=" * 70)
135
+
136
+ clinical_statuses = []
137
+ primary_findings = []
138
+ abnormality_counts = []
139
+ confidence_levels = []
140
+
141
+ for patient_id, result in all_results.items():
142
+ if 'endpoint_tests' in result and 'clinical_analysis' in result['endpoint_tests']:
143
+ clinical = result['endpoint_tests']['clinical_analysis'].get('data', {}).get('clinical_analysis', {})
144
+
145
+ if clinical.get('overall_status'):
146
+ clinical_statuses.append(clinical['overall_status'])
147
+ if clinical.get('primary_finding'):
148
+ primary_findings.append(clinical['primary_finding'])
149
+ if clinical.get('abnormalities_detected') is not None:
150
+ abnormality_counts.append(clinical['abnormalities_detected'])
151
+ if clinical.get('confidence_level'):
152
+ confidence_levels.append(clinical['confidence_level'])
153
+
154
+ analysis = {}
155
+
156
+ # Clinical Status Analysis
157
+ if len(clinical_statuses) > 0:
158
+ print(f"πŸ₯ Clinical Status Analysis:")
159
+ print(f" Statuses: {clinical_statuses}")
160
+
161
+ normal_count = sum(1 for s in clinical_statuses if 'normal' in s.lower())
162
+ abnormal_count = sum(1 for s in clinical_statuses if 'abnormal' in s.lower())
163
+
164
+ print(f" Normal: {normal_count}")
165
+ print(f" Abnormal: {abnormal_count}")
166
+ print(f" Distribution: Normal {normal_count/len(clinical_statuses)*100:.1f}% vs Abnormal {abnormal_count/len(clinical_statuses)*100:.1f}%")
167
+
168
+ analysis['clinical_status'] = {
169
+ 'statuses': clinical_statuses,
170
+ 'normal_count': normal_count,
171
+ 'abnormal_count': abnormal_count,
172
+ 'normal_percentage': normal_count/len(clinical_statuses)*100 if len(clinical_statuses) > 0 else 0
173
+ }
174
+
175
+ # Confidence Analysis
176
+ if len(confidence_levels) > 0:
177
+ print(f"\nπŸ” Confidence Level Analysis:")
178
+ print(f" Confidence Levels: {confidence_levels}")
179
+ avg_confidence = np.mean(confidence_levels)
180
+ print(f" Average Confidence: {avg_confidence:.2f}")
181
+
182
+ analysis['confidence'] = {
183
+ 'levels': confidence_levels,
184
+ 'average': avg_confidence
185
+ }
186
+
187
+ # Overall Assessment
188
+ print(f"\n🎯 CLINICAL ASSESSMENT SUMMARY:")
189
+ working_clinical = len([k for k in all_results.keys() if 'endpoint_tests' in all_results[k] and 'clinical_analysis' in all_results[k]['endpoint_tests']])
190
+ total_patients = len(all_results)
191
+
192
+ print(f" Patients with Clinical Analysis: {working_clinical}/{total_patients}")
193
+ print(f" Clinical Success Rate: {(working_clinical/total_patients)*100:.1f}%")
194
+
195
+ if working_clinical == total_patients:
196
+ print(f" πŸŽ‰ All patients have clinical analysis!")
197
+ elif working_clinical > total_patients // 2:
198
+ print(f" ⚠️ Most patients have clinical analysis")
199
+ else:
200
+ print(f" ❌ Many patients missing clinical analysis")
201
+
202
+ return analysis
203
+
204
+ def main():
205
+ """Main test function"""
206
+ print("🧬 FINETUNED ECG-FM CLINICAL CLASSIFICATION TESTING")
207
+ print("=" * 80)
208
+ print(f"🌐 API URL: {API_BASE_URL}")
209
+ print(f"πŸ“ ECG Directory: {ECG_DIR}")
210
+ print(f"πŸ“‹ Index File: {INDEX_FILE}")
211
+ print()
212
+
213
+ # Check if files exist
214
+ if not os.path.exists(INDEX_FILE):
215
+ print(f"❌ Index file not found: {INDEX_FILE}")
216
+ return
217
+
218
+ if not os.path.exists(ECG_DIR):
219
+ print(f"❌ ECG directory not found: {ECG_DIR}")
220
+ return
221
+
222
+ # Load index file
223
+ try:
224
+ print("πŸ“ Loading patient index file...")
225
+ index_df = pd.read_csv(INDEX_FILE)
226
+ print(f"βœ… Loaded {len(index_df)} patient records")
227
+ except Exception as e:
228
+ print(f"❌ Error loading index file: {e}")
229
+ return
230
+
231
+ # Select ECG files for clinical testing
232
+ test_files = [
233
+ "ecg_98408931-6f8e-47cc-954a-ba0c058a0f3d.csv", # Bharathi M K Teacher, 31, F
234
+ "ecg_fc6d2ecb-7eb3-4eec-9281-17c24b7902b5.csv", # Sayida thasmiya Bhanu Teacher, 29, F
235
+ "ecg_022a3f3a-7060-4ff8-b716-b75d8e0637c5.csv", # Afzal, 46, M
236
+ ]
237
+
238
+ print(f"\n🧬 Testing FINETUNED MODEL with {len(test_files)} ECG samples...")
239
+ print("=" * 80)
240
+
241
+ all_results = {}
242
+
243
+ for i, ecg_file in enumerate(test_files, 1):
244
+ try:
245
+ print(f"\nπŸ“Š Processing {i}/{len(test_files)}: {ecg_file}")
246
+
247
+ # Find patient info in index
248
+ patient_row = index_df[index_df['ECG File Path'].str.contains(ecg_file, na=False)]
249
+ if len(patient_row) == 0:
250
+ print(f" ⚠️ Patient info not found for {ecg_file}")
251
+ continue
252
+
253
+ patient_info = patient_row.iloc[0]
254
+
255
+ # Check if ECG file exists
256
+ ecg_path = os.path.join(ECG_DIR, ecg_file)
257
+ if not os.path.exists(ecg_path):
258
+ print(f" ❌ ECG file not found: {ecg_path}")
259
+ continue
260
+
261
+ # Load ECG data
262
+ ecg_data = load_ecg_data(ecg_path)
263
+ if ecg_data is None:
264
+ print(f" ❌ Failed to load ECG data")
265
+ continue
266
+
267
+ # Test finetuned model for clinical classification
268
+ clinical_results = test_finetuned_clinical_classification(ecg_data, patient_info)
269
+
270
+ # Store results
271
+ all_results[ecg_file] = {
272
+ "patient_info": patient_info.to_dict(),
273
+ "endpoint_tests": clinical_results
274
+ }
275
+
276
+ print(f" βœ… Completed clinical analysis for {ecg_file}")
277
+
278
+ except Exception as e:
279
+ print(f" ❌ Error processing {ecg_file}: {e}")
280
+ all_results[ecg_file] = {"error": str(e)}
281
+
282
+ # Analyze clinical results
283
+ if len(all_results) > 0:
284
+ clinical_analysis = analyze_clinical_results(all_results)
285
+
286
+ # Summary report
287
+ print(f"\nπŸ“Š CLINICAL TEST SUMMARY")
288
+ print(f"=" * 80)
289
+
290
+ successful_clinical = 0
291
+ total_tests = len(test_files)
292
+
293
+ for ecg_file, result in all_results.items():
294
+ if "error" not in result:
295
+ clinical_status = result.get("endpoint_tests", {}).get("clinical_analysis", {}).get("status")
296
+ if clinical_status == "success":
297
+ successful_clinical += 1
298
+ print(f"βœ… {ecg_file}: Clinical analysis successful")
299
+ else:
300
+ print(f"⚠️ {ecg_file}: Clinical analysis {clinical_status}")
301
+ else:
302
+ print(f"❌ {ecg_file}: {result['error']}")
303
+
304
+ print(f"\n🎯 CLINICAL RESULTS:")
305
+ print(f" Successful Clinical Analysis: {successful_clinical}/{total_tests}")
306
+ print(f" Clinical Success Rate: {(successful_clinical/total_tests)*100:.1f}%")
307
+
308
+ # Save detailed results
309
+ timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
310
+ results_file = f"finetuned_clinical_test_results_{timestamp}.json"
311
+
312
+ try:
313
+ with open(results_file, 'w') as f:
314
+ json.dump(all_results, f, indent=2, default=str)
315
+ print(f"\nπŸ’Ύ Detailed clinical results saved to: {results_file}")
316
+ except Exception as e:
317
+ print(f"\n⚠️ Could not save results: {e}")
318
+
319
+ print(f"\nπŸŽ‰ Finetuned clinical testing completed!")
320
+ print(f"πŸ’‘ Check the results above for NORMAL vs ABNORMAL classification")
321
+
322
+ if __name__ == "__main__":
323
+ main()
test_measurement_accuracy.py ADDED
@@ -0,0 +1,218 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ Test Measurement Accuracy
4
+ Demonstrate the issues with current physiological parameter extraction
5
+ """
6
+
7
+ import numpy as np
8
+ import requests
9
+ import json
10
+
11
+ # Configuration
12
+ API_BASE_URL = "https://mystic-cbk-ecg-fm-api.hf.space"
13
+
14
+ def create_identical_ecg_signals():
15
+ """Create multiple identical ECG signals to test consistency"""
16
+ # Generate a simple 10-second ECG-like signal at 500 Hz
17
+ t = np.linspace(0, 10, 5000)
18
+
19
+ # Create identical signals
20
+ signals = []
21
+ for i in range(3):
22
+ # Basic sine wave with some variation
23
+ signal = []
24
+ for lead in range(12):
25
+ lead_signal = np.sin(2 * np.pi * 1.2 * t) * 0.5 # ~72 BPM
26
+ lead_signal += np.random.normal(0, 0.1, 5000) # Add noise
27
+ signal.append(lead_signal.tolist())
28
+ signals.append(signal)
29
+
30
+ return signals
31
+
32
+ def test_measurement_consistency():
33
+ """Test if identical signals give consistent measurements"""
34
+ print("πŸ§ͺ TESTING MEASUREMENT CONSISTENCY")
35
+ print("=" * 60)
36
+
37
+ # Create 3 identical ECG signals
38
+ signals = create_identical_ecg_signals()
39
+
40
+ print(f"πŸ“Š Created {len(signals)} identical ECG signals")
41
+ print(f"πŸ“Š Each signal: {len(signals[0])} leads Γ— {len(signals[0][0])} samples")
42
+
43
+ results = []
44
+
45
+ for i, signal in enumerate(signals, 1):
46
+ print(f"\nπŸ“€ Testing Signal {i}/3...")
47
+
48
+ payload = {
49
+ "signal": signal,
50
+ "fs": 500,
51
+ "patient_age": 30,
52
+ "patient_gender": "M"
53
+ }
54
+
55
+ try:
56
+ response = requests.post(f"{API_BASE_URL}/extract_features", json=payload, timeout=60)
57
+
58
+ if response.status_code == 200:
59
+ result = response.json()
60
+ physio = result.get('physiological_parameters', {})
61
+
62
+ measurements = {
63
+ "heart_rate": physio.get('heart_rate'),
64
+ "qrs_duration": physio.get('qrs_duration'),
65
+ "qt_interval": physio.get('qt_interval'),
66
+ "pr_interval": physio.get('pr_interval'),
67
+ "qrs_axis": physio.get('qrs_axis')
68
+ }
69
+
70
+ print(f" πŸ’“ Heart Rate: {measurements['heart_rate']} BPM")
71
+ print(f" πŸ“ QRS Duration: {measurements['qrs_duration']} ms")
72
+ print(f" ⏱️ QT Interval: {measurements['qt_interval']} ms")
73
+ print(f" πŸ”— PR Interval: {measurements['pr_interval']} ms")
74
+ print(f" 🧭 QRS Axis: {measurements['qrs_axis']}°")
75
+
76
+ results.append(measurements)
77
+
78
+ else:
79
+ print(f" ❌ Failed: {response.status_code}")
80
+ results.append(None)
81
+
82
+ except Exception as e:
83
+ print(f" ❌ Error: {e}")
84
+ results.append(None)
85
+
86
+ # Analyze consistency
87
+ print(f"\nπŸ“Š CONSISTENCY ANALYSIS")
88
+ print(f"=" * 60)
89
+
90
+ if len(results) == 3 and all(r is not None):
91
+ # Check if measurements are consistent
92
+ hr_values = [r['heart_rate'] for r in results if r['heart_rate'] is not None]
93
+ qrs_values = [r['qrs_duration'] for r in results if r['qrs_duration'] is not None]
94
+ qt_values = [r['qt_interval'] for r in results if r['qt_interval'] is not None]
95
+ pr_values = [r['pr_interval'] for r in results if r['pr_interval'] is not None]
96
+ axis_values = [r['qrs_axis'] for r in results if r['qrs_axis'] is not None]
97
+
98
+ print(f"πŸ’“ Heart Rate Consistency:")
99
+ if len(hr_values) == 3:
100
+ hr_std = np.std(hr_values)
101
+ print(f" Values: {hr_values}")
102
+ print(f" Standard Deviation: {hr_std:.2f}")
103
+ print(f" Consistent: {'βœ…' if hr_std < 1.0 else '❌'} (should be < 1.0 BPM)")
104
+ else:
105
+ print(f" ❌ Missing values: {hr_values}")
106
+
107
+ print(f"\nπŸ“ QRS Duration Consistency:")
108
+ if len(qrs_values) == 3:
109
+ qrs_std = np.std(qrs_values)
110
+ print(f" Values: {qrs_values}")
111
+ print(f" Standard Deviation: {qrs_std:.2f}")
112
+ print(f" Consistent: {'βœ…' if qrs_std < 5.0 else '❌'} (should be < 5.0 ms)")
113
+ else:
114
+ print(f" ❌ Missing values: {qrs_values}")
115
+
116
+ print(f"\n⏱️ QT Interval Consistency:")
117
+ if len(qt_values) == 3:
118
+ qt_std = np.std(qt_values)
119
+ print(f" Values: {qt_values}")
120
+ print(f" Standard Deviation: {qt_std:.2f}")
121
+ print(f" Consistent: {'βœ…' if qt_std < 10.0 else '❌'} (should be < 10.0 ms)")
122
+ else:
123
+ print(f" ❌ Missing values: {qt_values}")
124
+
125
+ # Overall assessment
126
+ print(f"\n🎯 OVERALL ASSESSMENT:")
127
+ print(f" If measurements are real: Should be nearly identical for identical signals")
128
+ print(f" If measurements are fake: Will show random variations")
129
+
130
+ else:
131
+ print(f"❌ Cannot analyze consistency - some tests failed")
132
+
133
+ def test_with_different_signals():
134
+ """Test with different signal characteristics"""
135
+ print(f"\nπŸ§ͺ TESTING WITH DIFFERENT SIGNAL CHARACTERISTICS")
136
+ print(f"=" * 60)
137
+
138
+ # Test 1: Normal signal
139
+ print(f"πŸ“Š Test 1: Normal ECG-like signal")
140
+ t = np.linspace(0, 10, 5000)
141
+ normal_signal = []
142
+ for lead in range(12):
143
+ lead_signal = np.sin(2 * np.pi * 1.2 * t) * 0.5 # ~72 BPM
144
+ normal_signal.append(lead_signal.tolist())
145
+
146
+ # Test 2: Fast signal
147
+ print(f"πŸ“Š Test 2: Fast ECG-like signal")
148
+ fast_signal = []
149
+ for lead in range(12):
150
+ lead_signal = np.sin(2 * np.pi * 2.0 * t) * 0.5 # ~120 BPM
151
+ fast_signal.append(lead_signal.tolist())
152
+
153
+ # Test 3: Slow signal
154
+ print(f"πŸ“Š Test 3: Slow ECG-like signal")
155
+ slow_signal = []
156
+ for lead in range(12):
157
+ lead_signal = np.sin(2 * np.pi * 0.8 * t) * 0.5 # ~48 BPM
158
+ slow_signal.append(lead_signal.tolist())
159
+
160
+ signals = [normal_signal, fast_signal, slow_signal]
161
+ expected_hrs = [72, 120, 48]
162
+
163
+ for i, (signal, expected_hr) in enumerate(zip(signals, expected_hrs), 1):
164
+ print(f"\nπŸ“€ Testing Signal {i} (Expected HR: ~{expected_hr} BPM)...")
165
+
166
+ payload = {
167
+ "signal": signal,
168
+ "fs": 500,
169
+ "patient_age": 30,
170
+ "patient_gender": "M"
171
+ }
172
+
173
+ try:
174
+ response = requests.post(f"{API_BASE_URL}/extract_features", json=payload, timeout=60)
175
+
176
+ if response.status_code == 200:
177
+ result = response.json()
178
+ physio = result.get('physiological_parameters', {})
179
+ actual_hr = physio.get('heart_rate')
180
+
181
+ print(f" Expected HR: ~{expected_hr} BPM")
182
+ print(f" Actual HR: {actual_hr} BPM")
183
+
184
+ if actual_hr is not None:
185
+ difference = abs(actual_hr - expected_hr)
186
+ print(f" Difference: {difference:.1f} BPM")
187
+ print(f" Reasonable: {'βœ…' if difference < 20 else '❌'} (should be < 20 BPM)")
188
+ else:
189
+ print(f" ❌ No HR measurement returned")
190
+
191
+ else:
192
+ print(f" ❌ Failed: {response.status_code}")
193
+
194
+ except Exception as e:
195
+ print(f" ❌ Error: {e}")
196
+
197
+ def main():
198
+ """Main test function"""
199
+ print("🚨 MEASUREMENT ACCURACY TEST")
200
+ print("=" * 60)
201
+ print("This test will reveal if our physiological measurements are:")
202
+ print("βœ… Real clinical measurements")
203
+ print("❌ Fake/testing values")
204
+ print()
205
+
206
+ # Test 1: Consistency
207
+ test_measurement_consistency()
208
+
209
+ # Test 2: Different signals
210
+ test_with_different_signals()
211
+
212
+ print(f"\n🎯 CONCLUSION:")
213
+ print(f" If measurements are consistent and reasonable: They might be real")
214
+ print(f" If measurements are inconsistent and random: They are fake/testing values")
215
+ print(f" Current implementation likely provides fake values!")
216
+
217
+ if __name__ == "__main__":
218
+ main()
test_physiological_parameters.py CHANGED
@@ -14,7 +14,7 @@ from typing import Dict, Any, List
14
  from datetime import datetime
15
 
16
  # Configuration
17
- API_BASE_URL = "http://localhost:8000" # Local server for testing
18
  ECG_DIR = "../ecg_uploads_greenwich/"
19
  INDEX_FILE = "../Greenwichschooldata.csv"
20
 
 
14
  from datetime import datetime
15
 
16
  # Configuration
17
+ API_BASE_URL = "https://mystic-cbk-ecg-fm-api.hf.space" # Deployed HF Spaces API
18
  ECG_DIR = "../ecg_uploads_greenwich/"
19
  INDEX_FILE = "../Greenwichschooldata.csv"
20