Spaces:
Sleeping
Sleeping
mystic_CBK
Fix JSON serialization error: Convert all numpy types to Python native types for clinical analysis
58e60a2
| #!/usr/bin/env python3 | |
| """ | |
| Comprehensive Multi-ECG Testing and Evaluation | |
| Tests multiple ECG samples and analyzes results systematically | |
| """ | |
| import requests | |
| import numpy as np | |
| import pandas as pd | |
| import json | |
| import time | |
| import os | |
| from typing import Dict, Any, List | |
| from datetime import datetime | |
| # Configuration | |
| API_BASE_URL = "https://mystic-cbk-ecg-fm-api.hf.space" | |
| ECG_DIR = "../ecg_uploads_greenwich/" | |
| INDEX_FILE = "../Greenwichschooldata.csv" | |
| def load_ecg_data(csv_file: str) -> List[List[float]]: | |
| """Load ECG data from CSV file""" | |
| try: | |
| df = pd.read_csv(csv_file) | |
| ecg_data = [] | |
| for lead in df.columns: | |
| ecg_data.append(df[lead].astype(float).tolist()) | |
| return ecg_data | |
| except Exception as e: | |
| print(f"β Error loading ECG data: {e}") | |
| return None | |
| def test_individual_endpoints(ecg_data: List[List[float]], patient_info: Dict[str, Any]) -> Dict[str, Any]: | |
| """Test all individual endpoints with comprehensive analysis""" | |
| results = {} | |
| print(f"π§ͺ Testing individual endpoints for {patient_info.get('Patient Name', 'Unknown')}") | |
| # Test 1: Extract Features (Physiological measurements) | |
| print("1οΈβ£ Testing /extract_features endpoint...") | |
| try: | |
| payload = {"signal": ecg_data, "fs": 500} | |
| response = requests.post(f"{API_BASE_URL}/extract_features", json=payload, timeout=60) | |
| if response.status_code == 200: | |
| result = response.json() | |
| physio = result.get('physiological_parameters', {}) | |
| print(f" β Features extracted successfully") | |
| print(f" π Feature count: {result.get('features', {}).get('count', 'Unknown')}") | |
| print(f" π Feature dimension: {result.get('features', {}).get('dimension', 'Unknown')}") | |
| print(f" π Heart Rate: {physio.get('heart_rate')} BPM") | |
| print(f" π QRS Duration: {physio.get('qrs_duration')} ms") | |
| print(f" β±οΈ QT Interval: {physio.get('qt_interval')} ms") | |
| print(f" π PR Interval: {physio.get('pr_interval')} ms") | |
| print(f" π§ QRS Axis: {physio.get('qrs_axis')}Β°") | |
| results['extract_features'] = {"status": "success", "data": result} | |
| else: | |
| print(f" β Failed: {response.status_code}") | |
| results['extract_features'] = {"status": "error", "error": response.text} | |
| except Exception as e: | |
| print(f" β Error: {e}") | |
| results['extract_features'] = {"status": "error", "error": str(e)} | |
| # Test 2: Assess Quality | |
| print("2οΈβ£ Testing /assess_quality endpoint...") | |
| try: | |
| payload = {"signal": ecg_data, "fs": 500} | |
| response = requests.post(f"{API_BASE_URL}/assess_quality", json=payload, timeout=60) | |
| if response.status_code == 200: | |
| result = response.json() | |
| print(f" β Quality assessment completed") | |
| print(f" π Overall Quality: {result.get('quality', 'Unknown')}") | |
| metrics = result.get('metrics', {}) | |
| print(f" π SNR: {metrics.get('signal_to_noise_ratio', 'Unknown')}") | |
| print(f" π Baseline Wander: {metrics.get('baseline_wander', 'Unknown')}") | |
| print(f" π Standard Deviation: {metrics.get('standard_deviation', 'Unknown')}") | |
| results['assess_quality'] = {"status": "success", "data": result} | |
| else: | |
| print(f" β Failed: {response.status_code}") | |
| results['assess_quality'] = {"status": "error", "error": response.text} | |
| except Exception as e: | |
| print(f" β Error: {e}") | |
| results['assess_quality'] = {"status": "error", "error": str(e)} | |
| # Test 3: Predict endpoint | |
| print("3οΈβ£ Testing /predict endpoint...") | |
| try: | |
| payload = {"signal": ecg_data, "fs": 500} | |
| response = requests.post(f"{API_BASE_URL}/predict", json=payload, timeout=60) | |
| if response.status_code == 200: | |
| result = response.json() | |
| print(f" β Prediction completed") | |
| print(f" 𧬠Model Type: {result.get('model_type', 'Unknown')}") | |
| print(f" π Confidence: {result.get('confidence', 'Unknown')}") | |
| results['predict'] = {"status": "success", "data": result} | |
| else: | |
| print(f" β Failed: {response.status_code}") | |
| results['assess_quality'] = {"status": "error", "error": response.text} | |
| except Exception as e: | |
| print(f" β Error: {e}") | |
| results['predict'] = {"status": "error", "error": str(e)} | |
| return results | |
| def analyze_physiological_consistency(all_results: Dict[str, Any]) -> Dict[str, Any]: | |
| """Analyze consistency of physiological measurements across samples""" | |
| print(f"\nπ PHYSIOLOGICAL MEASUREMENT CONSISTENCY ANALYSIS") | |
| print(f"=" * 70) | |
| # Extract all heart rate values | |
| hr_values = [] | |
| qrs_values = [] | |
| qt_values = [] | |
| pr_values = [] | |
| axis_values = [] | |
| for patient_id, result in all_results.items(): | |
| if 'endpoint_tests' in result and 'extract_features' in result['endpoint_tests']: | |
| physio = result['endpoint_tests']['extract_features'].get('data', {}).get('physiological_parameters', {}) | |
| if physio.get('heart_rate') is not None: | |
| hr_values.append(physio['heart_rate']) | |
| if physio.get('qrs_duration') is not None: | |
| qrs_values.append(physio['qrs_duration']) | |
| if physio.get('qt_interval') is not None: | |
| qt_values.append(physio['qt_interval']) | |
| if physio.get('pr_interval') is not None: | |
| pr_values.append(physio['pr_interval']) | |
| if physio.get('qrs_axis') is not None: | |
| axis_values.append(physio['qrs_axis']) | |
| analysis = {} | |
| # Heart Rate Analysis | |
| if len(hr_values) > 0: | |
| hr_std = np.std(hr_values) | |
| hr_range = np.ptp(hr_values) | |
| print(f"π Heart Rate Analysis:") | |
| print(f" Values: {hr_values}") | |
| print(f" Mean: {np.mean(hr_values):.1f} BPM") | |
| print(f" Standard Deviation: {hr_std:.2f} BPM") | |
| print(f" Range: {hr_range:.1f} BPM") | |
| print(f" Consistency: {'β Excellent' if hr_std < 2.0 else 'β οΈ Good' if hr_std < 5.0 else 'β Poor'}") | |
| analysis['heart_rate'] = { | |
| 'values': hr_values, | |
| 'mean': np.mean(hr_values), | |
| 'std': hr_std, | |
| 'range': hr_range, | |
| 'consistency': 'Excellent' if hr_std < 2.0 else 'Good' if hr_std < 5.0 else 'Poor' | |
| } | |
| # QRS Duration Analysis | |
| if len(qrs_values) > 0: | |
| qrs_std = np.std(qrs_values) | |
| qrs_range = np.ptp(qrs_values) | |
| print(f"\nπ QRS Duration Analysis:") | |
| print(f" Values: {qrs_values}") | |
| print(f" Mean: {np.mean(qrs_values):.1f} ms") | |
| print(f" Standard Deviation: {qrs_std:.2f} ms") | |
| print(f" Range: {qrs_range:.1f} ms") | |
| print(f" Consistency: {'β Excellent' if qrs_std < 5.0 else 'β οΈ Good' if qrs_std < 10.0 else 'β Poor'}") | |
| analysis['qrs_duration'] = { | |
| 'values': qrs_values, | |
| 'mean': np.mean(qrs_values), | |
| 'std': qrs_std, | |
| 'range': qrs_range, | |
| 'consistency': 'Excellent' if qrs_std < 5.0 else 'Good' if qrs_std < 10.0 else 'Poor' | |
| } | |
| # Overall Assessment | |
| print(f"\nπ― OVERALL PHYSIOLOGICAL ASSESSMENT:") | |
| working_params = len([k for k in analysis.keys() if analysis[k]['consistency'] in ['Excellent', 'Good']]) | |
| total_params = len(analysis) | |
| print(f" Working Parameters: {working_params}/{total_params}") | |
| print(f" Success Rate: {(working_params/total_params)*100:.1f}%") | |
| if working_params == total_params: | |
| print(f" π All physiological parameters working consistently!") | |
| elif working_params > total_params // 2: | |
| print(f" β οΈ Most parameters working - some inconsistencies") | |
| else: | |
| print(f" β Many parameters showing inconsistencies") | |
| return analysis | |
| def main(): | |
| """Main test function""" | |
| print("π COMPREHENSIVE MULTI-ECG TESTING AND EVALUATION") | |
| print("=" * 80) | |
| print(f"π API URL: {API_BASE_URL}") | |
| print(f"π ECG Directory: {ECG_DIR}") | |
| print(f"π Index File: {INDEX_FILE}") | |
| print() | |
| # Check if files exist | |
| if not os.path.exists(INDEX_FILE): | |
| print(f"β Index file not found: {INDEX_FILE}") | |
| return | |
| if not os.path.exists(ECG_DIR): | |
| print(f"β ECG directory not found: {ECG_DIR}") | |
| return | |
| # Load index file | |
| try: | |
| print("π Loading patient index file...") | |
| index_df = pd.read_csv(INDEX_FILE) | |
| print(f"β Loaded {len(index_df)} patient records") | |
| except Exception as e: | |
| print(f"β Error loading index file: {e}") | |
| return | |
| # Select multiple ECG files for testing | |
| test_files = [ | |
| "ecg_98408931-6f8e-47cc-954a-ba0c058a0f3d.csv", # Bharathi M K Teacher, 31, F | |
| "ecg_fc6d2ecb-7eb3-4eec-9281-17c24b7902b5.csv", # Sayida thasmiya Bhanu Teacher, 29, F | |
| "ecg_022a3f3a-7060-4ff8-b716-b75d8e0637c5.csv", # Afzal, 46, M | |
| # Add more files if available | |
| ] | |
| print(f"\nπ Testing with {len(test_files)} ECG samples...") | |
| print("=" * 80) | |
| all_results = {} | |
| for i, ecg_file in enumerate(test_files, 1): | |
| try: | |
| print(f"\nπ Processing {i}/{len(test_files)}: {ecg_file}") | |
| # Find patient info in index | |
| patient_row = index_df[index_df['ECG File Path'].str.contains(ecg_file, na=False)] | |
| if len(patient_row) == 0: | |
| print(f" β οΈ Patient info not found for {ecg_file}") | |
| continue | |
| patient_info = patient_row.iloc[0] | |
| print(f" π€ Patient: {patient_info['Patient Name']} ({patient_info['Age']} {patient_info['Gender']})") | |
| # Check if ECG file exists | |
| ecg_path = os.path.join(ECG_DIR, ecg_file) | |
| if not os.path.exists(ecg_path): | |
| print(f" β ECG file not found: {ecg_path}") | |
| continue | |
| # Load ECG data | |
| ecg_data = load_ecg_data(ecg_path) | |
| if ecg_data is None: | |
| print(f" β Failed to load ECG data") | |
| continue | |
| # Test individual endpoints | |
| endpoint_results = test_individual_endpoints(ecg_data, patient_info) | |
| # Store results | |
| all_results[ecg_file] = { | |
| "patient_info": patient_info.to_dict(), | |
| "endpoint_tests": endpoint_results | |
| } | |
| print(f" β Completed analysis for {ecg_file}") | |
| except Exception as e: | |
| print(f" β Error processing {ecg_file}: {e}") | |
| all_results[ecg_file] = {"error": str(e)} | |
| # Analyze physiological consistency | |
| if len(all_results) > 0: | |
| physiological_analysis = analyze_physiological_consistency(all_results) | |
| # Summary report | |
| print(f"\nπ COMPREHENSIVE TEST SUMMARY") | |
| print(f"=" * 80) | |
| successful_tests = 0 | |
| total_tests = len(test_files) | |
| for ecg_file, result in all_results.items(): | |
| if "error" not in result: | |
| endpoint_status = result.get("endpoint_tests", {}) | |
| working_endpoints = sum(1 for ep in endpoint_status.values() if ep.get("status") == "success") | |
| total_endpoints = len(endpoint_status) | |
| if working_endpoints == total_endpoints: | |
| successful_tests += 1 | |
| print(f"β {ecg_file}: All endpoints working") | |
| else: | |
| print(f"β οΈ {ecg_file}: {working_endpoints}/{total_endpoints} endpoints working") | |
| else: | |
| print(f"β {ecg_file}: {result['error']}") | |
| print(f"\nπ― OVERALL RESULTS:") | |
| print(f" Successful ECG Analysis: {successful_tests}/{total_tests}") | |
| print(f" Success Rate: {(successful_tests/total_tests)*100:.1f}%") | |
| # Save detailed results | |
| timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") | |
| results_file = f"comprehensive_ecg_test_results_{timestamp}.json" | |
| try: | |
| with open(results_file, 'w') as f: | |
| json.dump(all_results, f, indent=2, default=str) | |
| print(f"\nπΎ Detailed results saved to: {results_file}") | |
| except Exception as e: | |
| print(f"\nβ οΈ Could not save results: {e}") | |
| print(f"\nπ Comprehensive ECG testing completed!") | |
| print(f"π‘ Check the results above to evaluate system performance") | |
| if __name__ == "__main__": | |
| main() | |