Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/env python3
- # -*- coding: utf-8 -*-
- """
- EEG Paradox Clinical Insight Report System v1.0
- Advanced EDF Processing
- Copyright (C) 2024 EEG Paradox Project
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
- Specialized tool for processing EDF files to generate clinical Insight
- focused on Executive Control Network (Fz, Cz, Pz) and symptom domain analysis.
- """
- import os
- import sys
- import numpy as np
- import pandas as pd
- from pathlib import Path
- import json
- import logging
- from datetime import datetime
- from typing import Dict, List, Tuple, Optional, Union
- from dataclasses import dataclass, asdict
- from enum import Enum
- import warnings
- # Try to import MNE for advanced EEG processing
- try:
- import mne
- from mne import create_info
- from mne.io import read_raw_edf
- MNE_AVAILABLE = True
- except ImportError:
- MNE_AVAILABLE = False
- print("⚠️ MNE-Python not available - Limited functionality")
- # Try to import additional analysis libraries
- try:
- from scipy import signal, stats
- from scipy.fft import fft, fftfreq
- SCIPY_AVAILABLE = True
- except ImportError:
- SCIPY_AVAILABLE = False
- print("⚠️ SciPy not available - Limited spectral analysis")
- try:
- import matplotlib.pyplot as plt
- import seaborn as sns
- MATPLOTLIB_AVAILABLE = True
- except ImportError:
- MATPLOTLIB_AVAILABLE = False
- print("⚠️ Matplotlib not available - No visualization")
- # Configure logging
- logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
- logger = logging.getLogger(__name__)
- class SymptomDomain(Enum):
- """Clinical symptom domains for Insight generation"""
- IMPULSIVITY_AROUSAL = "impulsivity_arousal_regulation"
- ATTENTION_EXECUTIVE = "attention_executive_function"
- SOCIAL_INTERPERSONAL = "social_interpersonal_function"
- MOOD_EMOTIONAL = "mood_emotional_regulation"
- COGNITIVE_PROCESSING = "cognitive_processing"
- SENSORY_MOTOR = "sensory_motor_function"
- SLEEP_VIGILANCE = "sleep_vigilance"
- AUTONOMIC_REGULATION = "autonomic_regulation"
- class EEGSite(Enum):
- """Key EEG sites for Executive Control Network analysis"""
- FZ = "Fz" # Frontal midline - Executive control
- CZ = "Cz" # Central midline - Motor control, attention
- PZ = "Pz" # Parietal midline - Attention, working memory
- class FrequencyBand(Enum):
- """EEG frequency bands"""
- DELTA = "delta" # 0.5-4 Hz
- THETA = "theta" # 4-8 Hz
- ALPHA = "alpha" # 8-13 Hz
- BETA = "beta" # 13-30 Hz
- GAMMA = "gamma" # 30-100 Hz
- @dataclass
- class ClinicalInsight :
- """Clinical Insight data structure"""
- symptom_domain: SymptomDomain
- primary_sites: List[EEGSite]
- qeeg_markers: List[str]
- erp_components: List[str]
- network_dynamics: List[str]
- confidence_score: float
- clinical_implications: str
- assessment_recommendations: List[str]
- references: List[str]
- @dataclass
- class EEGMetrics:
- """EEG metrics for specific sites and bands"""
- site: EEGSite
- band: FrequencyBand
- power: float
- relative_power: float
- asymmetry: Optional[float] = None
- coherence: Optional[float] = None
- phase_lag: Optional[float] = None
- @dataclass
- class ClinicalReport:
- """Complete clinical Insight report"""
- patient_id: str
- analysis_timestamp: datetime
- symptom_ranking: List[Tuple[SymptomDomain, float]]
- hypotheses: List[ClinicalInsight ]
- eeg_metrics: List[EEGMetrics]
- brain_map_data: Dict
- confidence_summary: Dict
- recommendations: List[str]
- class ClinicalInsight Analyzer:
- """
- Advanced Clinical Insight Report System
- Processes EDF files to generate structured clinical hypotheses
- """
- def __init__(self):
- self.symptom_domain_weights = {
- SymptomDomain.IMPULSIVITY_AROUSAL: 0.25,
- SymptomDomain.ATTENTION_EXECUTIVE: 0.30,
- SymptomDomain.SOCIAL_INTERPERSONAL: 0.15,
- SymptomDomain.MOOD_EMOTIONAL: 0.20,
- SymptomDomain.COGNITIVE_PROCESSING: 0.10
- }
- # Executive Control Network site priorities
- self.executive_sites = [EEGSite.FZ, EEGSite.CZ, EEGSite.PZ]
- # Frequency band definitions
- self.frequency_bands = {
- FrequencyBand.DELTA: (0.5, 4),
- FrequencyBand.THETA: (4, 8),
- FrequencyBand.ALPHA: (8, 13),
- FrequencyBand.BETA: (13, 30),
- FrequencyBand.GAMMA: (30, 100)
- }
- # Clinical Insight templates
- self.Insight _templates = self._initialize_Insight _templates()
- def _initialize_Insight _templates(self) -> Dict:
- """Initialize clinical Insight templates based on Gunkelman/Gattis methodology"""
- return {
- SymptomDomain.IMPULSIVITY_AROUSAL: {
- 'primary_sites': [EEGSite.FZ, EEGSite.CZ],
- 'qeeg_markers': [
- 'Frontal slowing (increased theta)',
- 'Beta hyperarousal patterns',
- 'Theta/Beta ratio elevation',
- 'Frontal alpha asymmetry'
- ],
- 'erp_components': ['N200', 'P300', 'Error-related negativity'],
- 'network_dynamics': [
- 'Salience network dysfunction',
- 'Executive control network imbalance',
- 'Frontal-parietal connectivity issues'
- ],
- 'clinical_implications': 'Patterns suggest difficulties with impulse control and arousal regulation, potentially indicating ADHD, anxiety, or trauma-related symptoms.',
- 'assessment_recommendations': [
- 'Comprehensive qEEG with eyes closed/eyes open protocols',
- 'ERP assessment for attention and inhibitory control',
- 'Behavioral assessment for impulsivity measures',
- 'Consider medication effects on arousal patterns'
- ],
- 'references': [
- 'Gunkelman, J. & Johnstone, J. (2005). Neurofeedback and the Brain.',
- 'Arns, M. et al. (2013). EEG-based ADHD diagnosis: A review.'
- ]
- },
- SymptomDomain.ATTENTION_EXECUTIVE: {
- 'primary_sites': [EEGSite.FZ, EEGSite.CZ, EEGSite.PZ],
- 'qeeg_markers': [
- 'Central theta elevation',
- 'Theta/Beta ratio (TBR) patterns',
- 'Executive Control Network markers',
- 'Frontal-parietal coherence'
- ],
- 'erp_components': ['P300', 'N2pc', 'Contingent negative variation'],
- 'network_dynamics': [
- 'Executive Control Network dysfunction',
- 'Default Mode Network interference',
- 'Frontal-parietal attention network',
- 'Cingulo-opercular network'
- ],
- 'clinical_implications': 'Executive control network patterns suggest attention regulation difficulties, working memory issues, and potential ADHD or executive dysfunction.',
- 'assessment_recommendations': [
- 'TBR analysis across executive sites (Fz, Cz, Pz)',
- 'Working memory task with EEG monitoring',
- 'Continuous performance test with ERP',
- 'Executive function behavioral assessment'
- ],
- 'references': [
- 'Gunkelman, J. (2019). The Clinical Use of QEEG.',
- 'Posner, M.I. & Petersen, S.E. (1990). The attention system of the human brain.'
- ]
- },
- SymptomDomain.SOCIAL_INTERPERSONAL: {
- 'primary_sites': [EEGSite.FZ, EEGSite.CZ],
- 'qeeg_markers': [
- 'Right-hemisphere beta activity',
- 'Frontal alpha asymmetry',
- 'Social brain network markers',
- 'Mirror neuron system indicators'
- ],
- 'erp_components': ['N170', 'P300', 'Late positive potential'],
- 'network_dynamics': [
- 'Social brain network dysfunction',
- 'Theory of mind network',
- 'Empathy network connectivity',
- 'Social attention network'
- ],
- 'clinical_implications': 'Social processing patterns may indicate difficulties with social cognition, empathy, or interpersonal relationships.',
- 'assessment_recommendations': [
- 'Social cognition assessment',
- 'Theory of mind testing',
- 'Social anxiety evaluation',
- 'Interpersonal relationship assessment'
- ],
- 'references': [
- 'Gattis, M. (2018). Social Brain Networks in Clinical Practice.',
- 'Frith, C.D. & Frith, U. (2006). The neural basis of mentalizing.'
- ]
- }
- }
- def analyze_edf_file(self, edf_path: Union[str, Path]) -> ClinicalReport:
- """
- Main analysis function - processes EDF file and generates clinical hypotheses
- Args:
- edf_path: Path to EDF file
- Returns:
- ClinicalReport object with complete analysis
- """
- edf_path = Path(edf_path)
- if not edf_path.exists():
- raise FileNotFoundError(f"EDF file not found: {edf_path}")
- logger.info(f"Starting clinical Insight analysis for: {edf_path.name}")
- # Load and preprocess EDF data
- raw_data = self._load_edf_data(edf_path)
- # Extract key metrics for executive sites
- eeg_metrics = self._extract_executive_metrics(raw_data)
- # Generate symptom domain rankings
- symptom_ranking = self._rank_symptom_domains(eeg_metrics)
- # Generate clinical hypotheses
- hypotheses = self._generate_clinical_hypotheses(symptom_ranking, eeg_metrics)
- # Create brain map data
- brain_map_data = self._create_brain_map_data(eeg_metrics)
- # Generate confidence summary
- confidence_summary = self._calculate_confidence_summary(hypotheses, eeg_metrics)
- # Generate recommendations
- recommendations = self._generate_recommendations(hypotheses)
- # Create final report
- report = ClinicalReport(
- patient_id=edf_path.stem,
- analysis_timestamp=datetime.now(),
- symptom_ranking=symptom_ranking,
- hypotheses=hypotheses,
- eeg_metrics=eeg_metrics,
- brain_map_data=brain_map_data,
- confidence_summary=confidence_summary,
- recommendations=recommendations
- )
- logger.info("Clinical Insight analysis completed successfully")
- return report
- def _load_edf_data(self, edf_path: Path):
- """Load and preprocess EDF data"""
- if not MNE_AVAILABLE:
- raise ImportError("MNE-Python is required for EDF processing")
- try:
- # Load EDF file
- raw = read_raw_edf(edf_path, preload=True, verbose=False)
- # Apply standard preprocessing
- raw.filter(0.5, 100, fir_design='firwin', verbose=False)
- raw.notch_filter(60, verbose=False) # Remove line noise
- # Resample to standard frequency if needed
- if raw.info['sfreq'] > 500:
- raw.resample(500, verbose=False)
- logger.info(f"Loaded EDF: {len(raw.ch_names)} channels, {raw.info['sfreq']:.1f} Hz")
- return raw
- except Exception as e:
- logger.error(f"Error loading EDF file: {e}")
- raise
- def _extract_executive_metrics(self, raw_data) -> List[EEGMetrics]:
- """Extract EEG metrics for executive control network sites"""
- metrics = []
- # Get available channel names
- available_channels = [ch.upper() for ch in raw_data.ch_names]
- for site in self.executive_sites:
- site_name = site.value.upper()
- # Find matching channel (handle variations like FZ, Fz, Fpz-Fz, etc.)
- matching_channel = None
- for ch in raw_data.ch_names:
- if site_name in ch.upper() or ch.upper() in site_name:
- matching_channel = ch
- break
- if not matching_channel:
- logger.warning(f"Channel {site_name} not found in data")
- continue
- # Extract data for this channel
- channel_data = raw_data.get_data(picks=[matching_channel])[0]
- # Calculate metrics for each frequency band
- for band, (low_freq, high_freq) in self.frequency_bands.items():
- try:
- # Calculate power spectral density
- freqs, psd = signal.welch(
- channel_data,
- fs=raw_data.info['sfreq'],
- nperseg=int(2 * raw_data.info['sfreq']),
- noverlap=int(raw_data.info['sfreq'])
- )
- # Extract band power
- band_mask = (freqs >= low_freq) & (freqs <= high_freq)
- band_power = np.trapz(psd[band_mask], freqs[band_mask])
- # Calculate relative power
- total_power = np.trapz(psd, freqs)
- relative_power = band_power / total_power if total_power > 0 else 0
- # Create metrics object
- metric = EEGMetrics(
- site=site,
- band=band,
- power=band_power,
- relative_power=relative_power
- )
- metrics.append(metric)
- except Exception as e:
- logger.warning(f"Error calculating metrics for {site.value} {band.value}: {e}")
- continue
- return metrics
- def _rank_symptom_domains(self, eeg_metrics: List[EEGMetrics]) -> List[Tuple[SymptomDomain, float]]:
- """Rank symptom domains based on EEG patterns"""
- domain_scores = {}
- for domain in SymptomDomain:
- score = 0.0
- # Get template for this domain
- template = self.Insight _templates.get(domain, {})
- primary_sites = template.get('primary_sites', [])
- # Calculate score based on relevant metrics
- for metric in eeg_metrics:
- if metric.site in primary_sites:
- # Weight different frequency bands based on clinical relevance
- if domain == SymptomDomain.IMPULSIVITY_AROUSAL:
- if metric.band == FrequencyBand.THETA:
- score += metric.relative_power * 2.0
- elif metric.band == FrequencyBand.BETA:
- score += metric.relative_power * 1.5
- elif metric.band == FrequencyBand.ALPHA:
- score += metric.relative_power * 1.0
- elif domain == SymptomDomain.ATTENTION_EXECUTIVE:
- if metric.band == FrequencyBand.THETA:
- score += metric.relative_power * 2.5
- elif metric.band == FrequencyBand.BETA:
- score += metric.relative_power * 1.0
- elif metric.band == FrequencyBand.ALPHA:
- score += metric.relative_power * 0.5
- elif domain == SymptomDomain.SOCIAL_INTERPERSONAL:
- if metric.band == FrequencyBand.BETA:
- score += metric.relative_power * 2.0
- elif metric.band == FrequencyBand.ALPHA:
- score += metric.relative_power * 1.5
- # Apply domain weight
- score *= self.symptom_domain_weights.get(domain, 0.1)
- domain_scores[domain] = score
- # Sort by score (highest first)
- ranked_domains = sorted(domain_scores.items(), key=lambda x: x[1], reverse=True)
- return ranked_domains
- def _generate_clinical_hypotheses(self, symptom_ranking: List[Tuple[SymptomDomain, float]],
- eeg_metrics: List[EEGMetrics]) -> List[ClinicalInsight ]:
- """Generate clinical hypotheses based on symptom rankings and EEG metrics"""
- hypotheses = []
- for domain, score in symptom_ranking[:3]: # Top 3 domains
- if score > 0.1: # Only generate hypotheses for significant scores
- template = self.Insight _templates.get(domain, {})
- # Calculate confidence based on score and metric consistency
- confidence = min(score * 2, 1.0) # Scale to 0-1
- Insight = ClinicalInsight (
- symptom_domain=domain,
- primary_sites=template.get('primary_sites', []),
- qeeg_markers=template.get('qeeg_markers', []),
- erp_components=template.get('erp_components', []),
- network_dynamics=template.get('network_dynamics', []),
- confidence_score=confidence,
- clinical_implications=template.get('clinical_implications', ''),
- assessment_recommendations=template.get('assessment_recommendations', []),
- references=template.get('references', [])
- )
- hypotheses.append(Insight )
- return hypotheses
- def _create_brain_map_data(self, eeg_metrics: List[EEGMetrics]) -> Dict:
- """Create brain map visualization data"""
- brain_map = {
- 'executive_sites': {},
- 'network_connectivity': {},
- 'frequency_analysis': {}
- }
- # Organize metrics by site
- for metric in eeg_metrics:
- site_name = metric.site.value
- if site_name not in brain_map['executive_sites']:
- brain_map['executive_sites'][site_name] = {}
- brain_map['executive_sites'][site_name][metric.band.value] = {
- 'power': float(metric.power),
- 'relative_power': float(metric.relative_power)
- }
- # Calculate network connectivity (simplified)
- fz_metrics = [m for m in eeg_metrics if m.site == EEGSite.FZ]
- cz_metrics = [m for m in eeg_metrics if m.site == EEGSite.CZ]
- pz_metrics = [m for m in eeg_metrics if m.site == EEGSite.PZ]
- # Calculate correlations between sites (simplified approach)
- if fz_metrics and cz_metrics:
- fz_powers = [m.power for m in fz_metrics]
- cz_powers = [m.power for m in cz_metrics]
- if len(fz_powers) == len(cz_powers):
- correlation = np.corrcoef(fz_powers, cz_powers)[0, 1]
- brain_map['network_connectivity']['Fz-Cz'] = float(correlation)
- return brain_map
- def _calculate_confidence_summary(self, hypotheses: List[ClinicalInsight ],
- eeg_metrics: List[EEGMetrics]) -> Dict:
- """Calculate overall confidence summary"""
- if not hypotheses:
- return {'overall_confidence': 0.0, 'data_quality': 'poor'}
- # Calculate average confidence
- avg_confidence = np.mean([h.confidence_score for h in hypotheses])
- # Assess data quality based on metrics
- data_quality = 'good'
- if len(eeg_metrics) < 10:
- data_quality = 'limited'
- elif avg_confidence < 0.3:
- data_quality = 'poor'
- return {
- 'overall_confidence': float(avg_confidence),
- 'data_quality': data_quality,
- 'Insight _count': len(hypotheses),
- 'metrics_count': len(eeg_metrics)
- }
- def _generate_recommendations(self, hypotheses: List[ClinicalInsight ]) -> List[str]:
- """Generate clinical recommendations based on hypotheses"""
- recommendations = []
- if not hypotheses:
- recommendations.append("Insufficient data for clinical Insight generation")
- return recommendations
- # General recommendations
- recommendations.append("Comprehensive qEEG assessment recommended")
- recommendations.append("Consider ERP assessment for attention and executive function")
- # Specific recommendations based on top Insight
- top_Insight = hypotheses[0]
- recommendations.extend(top_Insight .assessment_recommendations[:3])
- # Additional recommendations
- if any(h.symptom_domain == SymptomDomain.ATTENTION_EXECUTIVE for h in hypotheses):
- recommendations.append("TBR analysis across executive sites (Fz, Cz, Pz)")
- if any(h.symptom_domain == SymptomDomain.IMPULSIVITY_AROUSAL for h in hypotheses):
- recommendations.append("Behavioral assessment for impulsivity measures")
- return recommendations
- def save_report(self, report: ClinicalReport, output_path: Union[str, Path]):
- """Save clinical report to JSON file"""
- output_path = Path(output_path)
- # Convert report to dictionary
- report_dict = asdict(report)
- # Convert datetime to string
- report_dict['analysis_timestamp'] = report.analysis_timestamp.isoformat()
- # Convert enums to strings
- def convert_enums(obj):
- if isinstance(obj, dict):
- return {k: convert_enums(v) for k, v in obj.items()}
- elif isinstance(obj, list):
- return [convert_enums(item) for item in obj]
- elif isinstance(obj, Enum):
- return obj.value
- elif hasattr(obj, '__dict__'):
- return {k: convert_enums(v) for k, v in obj.__dict__.items()}
- else:
- return obj
- report_dict = convert_enums(report_dict)
- # Save to JSON
- with open(output_path, 'w', encoding='utf-8') as f:
- json.dump(report_dict, f, indent=2, ensure_ascii=False)
- logger.info(f"Clinical report saved to: {output_path}")
- def generate_visual_report(self, report: ClinicalReport, output_path: Union[str, Path]):
- """Generate visual brain map and report"""
- if not MATPLOTLIB_AVAILABLE:
- logger.warning("Matplotlib not available - skipping visual report")
- return
- output_path = Path(output_path)
- # Create figure with subplots
- fig, axes = plt.subplots(2, 2, figsize=(15, 12))
- fig.suptitle(f'Clinical Insight Report - {report.patient_id}', fontsize=16, fontweight='bold')
- # Plot 1: Brain map visualization
- self._plot_brain_map(axes[0, 0], report.brain_map_data)
- # Plot 2: Symptom domain rankings
- self._plot_symptom_rankings(axes[0, 1], report.symptom_ranking)
- # Plot 3: EEG metrics by site
- self._plot_eeg_metrics(axes[1, 0], report.eeg_metrics)
- # Plot 4: Confidence summary
- self._plot_confidence_summary(axes[1, 1], report.confidence_summary)
- plt.tight_layout()
- plt.savefig(output_path, dpi=300, bbox_inches='tight')
- plt.close()
- logger.info(f"Visual report saved to: {output_path}")
- def _plot_brain_map(self, ax, brain_map_data):
- """Plot brain map visualization"""
- ax.set_title('Executive Control Network', fontweight='bold')
- # Create simplified brain map
- sites = ['Fz', 'Cz', 'Pz']
- colors = ['red', 'blue', 'green']
- for i, site in enumerate(sites):
- if site in brain_map_data['executive_sites']:
- site_data = brain_map_data['executive_sites'][site]
- # Calculate average relative power across bands
- avg_power = np.mean([data['relative_power'] for data in site_data.values()])
- # Plot site with size proportional to power
- ax.scatter(i, 0, s=avg_power*1000, c=colors[i], alpha=0.7, label=site)
- ax.text(i, 0.1, f'{avg_power:.3f}', ha='center', fontsize=8)
- ax.set_xlim(-0.5, 2.5)
- ax.set_ylim(-0.5, 0.5)
- ax.set_xticks(range(3))
- ax.set_xticklabels(sites)
- ax.legend()
- ax.grid(True, alpha=0.3)
- def _plot_symptom_rankings(self, ax, symptom_ranking):
- """Plot symptom domain rankings"""
- ax.set_title('Symptom Domain Rankings', fontweight='bold')
- domains = [domain.value.replace('_', ' ').title() for domain, _ in symptom_ranking]
- scores = [score for _, score in symptom_ranking]
- bars = ax.barh(range(len(domains)), scores, color='steelblue', alpha=0.7)
- ax.set_yticks(range(len(domains)))
- ax.set_yticklabels(domains)
- ax.set_xlabel('Score')
- # Add value labels on bars
- for i, (bar, score) in enumerate(zip(bars, scores)):
- ax.text(bar.get_width() + 0.01, bar.get_y() + bar.get_height()/2,
- f'{score:.3f}', va='center', fontsize=8)
- ax.grid(True, alpha=0.3)
- def _plot_eeg_metrics(self, ax, eeg_metrics):
- """Plot EEG metrics by site and band"""
- ax.set_title('EEG Metrics by Site and Band', fontweight='bold')
- # Organize data for plotting
- sites = ['Fz', 'Cz', 'Pz']
- bands = ['delta', 'theta', 'alpha', 'beta', 'gamma']
- data_matrix = np.zeros((len(sites), len(bands)))
- for metric in eeg_metrics:
- site_idx = sites.index(metric.site.value)
- band_idx = bands.index(metric.band.value)
- data_matrix[site_idx, band_idx] = metric.relative_power
- # Create heatmap
- im = ax.imshow(data_matrix, cmap='viridis', aspect='auto')
- # Set labels
- ax.set_xticks(range(len(bands)))
- ax.set_xticklabels(bands)
- ax.set_yticks(range(len(sites)))
- ax.set_yticklabels(sites)
- # Add colorbar
- plt.colorbar(im, ax=ax, label='Relative Power')
- # Add text annotations
- for i in range(len(sites)):
- for j in range(len(bands)):
- text = ax.text(j, i, f'{data_matrix[i, j]:.3f}',
- ha="center", va="center", color="white", fontsize=8)
- def _plot_confidence_summary(self, ax, confidence_summary):
- """Plot confidence summary"""
- ax.set_title('Analysis Confidence', fontweight='bold')
- # Create pie chart for confidence levels
- confidence = confidence_summary['overall_confidence']
- data_quality = confidence_summary['data_quality']
- # Define confidence levels
- if confidence >= 0.7:
- level = 'High'
- color = 'green'
- elif confidence >= 0.4:
- level = 'Medium'
- color = 'orange'
- else:
- level = 'Low'
- color = 'red'
- # Create pie chart
- sizes = [confidence, 1-confidence]
- labels = [f'{level} ({confidence:.1%})', f'Uncertainty ({1-confidence:.1%})']
- colors = [color, 'lightgray']
- wedges, texts, autotexts = ax.pie(sizes, labels=labels, colors=colors, autopct='%1.1f%%', startangle=90)
- # Add data quality info
- ax.text(0, -1.3, f'Data Quality: {data_quality.title()}', ha='center', fontweight='bold')
- ax.text(0, -1.5, f'Hypotheses: {confidence_summary["Insight _count"]}', ha='center')
- ax.text(0, -1.7, f'Metrics: {confidence_summary["metrics_count"]}', ha='center')
- def main():
- """Main function for command-line usage"""
- import argparse
- parser = argparse.ArgumentParser(description='EEG Paradox Clinical Insight Report System')
- parser.add_argument('edf_file', help='Path to EDF file to analyze')
- parser.add_argument('-o', '--output', help='Output directory for reports', default='.')
- parser.add_argument('-v', '--visual', action='store_true', help='Generate visual report')
- parser.add_argument('--verbose', action='store_true', help='Verbose logging')
- args = parser.parse_args()
- if args.verbose:
- logging.getLogger().setLevel(logging.DEBUG)
- # Initialize analyzer
- analyzer = ClinicalInsight Analyzer()
- try:
- # Analyze EDF file
- report = analyzer.analyze_edf_file(args.edf_file)
- # Save JSON report
- output_dir = Path(args.output)
- output_dir.mkdir(exist_ok=True)
- json_path = output_dir / f"{report.patient_id}_clinical_Insight .json"
- analyzer.save_report(report, json_path)
- # Generate visual report if requested
- if args.visual:
- visual_path = output_dir / f"{report.patient_id}_clinical_Insight .png"
- analyzer.generate_visual_report(report, visual_path)
- print(f"✅ Analysis completed successfully!")
- print(f"📊 Report saved to: {json_path}")
- if args.visual:
- print(f"📈 Visual report saved to: {visual_path}")
- # Print summary
- print(f"\n🔍 Top Symptom Domains:")
- for i, (domain, score) in enumerate(report.symptom_ranking[:3], 1):
- print(f" {i}. {domain.value.replace('_', ' ').title()}: {score:.3f}")
- print(f"\n🧠 Clinical Hypotheses Generated: {len(report.hypotheses)}")
- print(f"📈 Overall Confidence: {report.confidence_summary['overall_confidence']:.1%}")
- except Exception as e:
- logger.error(f"Analysis failed: {e}")
- sys.exit(1)
- if __name__ == "__main__":
- main()
Advertisement
Add Comment
Please, Sign In to add comment