├── README.md └── ECGXMLReader.py /README.md: -------------------------------------------------------------------------------- 1 | # ECGXMLReader 2 | 3 | Python class for reading ECG XML files. Extracts lead voltages, and optionally augments 12L from 8L (common in GE MUSE XML). 4 | 5 | ## Dependencies 6 | Requires the following libraries: 7 | 8 | - xmltodict 9 | - numpy 10 | 11 | ## Usage 12 | ECGXMLReader can be called by other Python scripts and used to get raw voltage values from compressed formats. 13 | ``` 14 | from ECGXMLReader import ECGXMLReader 15 | 16 | ecg = ECGXMLReader('ecg_file.xml', augmentLeads=True) 17 | 18 | print( ecg.getLeadVoltages('I') ) 19 | ``` 20 | 21 | ## Structure 22 | * ECGXMLReader 23 | * PatientDemographics 24 | * PatientID 25 | * DateOfBirth 26 | * Gender 27 | * HeightCM 28 | * WeightKG 29 | * PatientLastName 30 | * TestDemographics 31 | * DataType 32 | * Site 33 | * AcquisitionDevice 34 | * Status 35 | * AcquisitionTime 36 | * AcquisitionDate 37 | * CartNumber 38 | * AcquisitionSoftwareVersion 39 | * RestingECGMeasurements 40 | * ECGSampleBase 41 | * ECGSampleExponent 42 | * Waveform 43 | * WaveformType 44 | * WaveformStartTime 45 | * NumberOfLeads 46 | * SampleType 47 | * SampleBase 48 | * SampleExponent 49 | * LeadData 50 | * LeadByteCountTotal 51 | * LeadTimeOffset 52 | * LeadSampleCountTotal 53 | * LeadAmplitudeUnitsPerBit 54 | * LeadAmplitudeUnits 55 | * LeadHighLimit 56 | * LeadLowLimit 57 | * LeadID 58 | * LeadOffsetFirstSample 59 | * FirstSampleBaseline 60 | * LeadSampleSize 61 | * LeadOff 62 | * BaselineSway 63 | * LeadDataCRC32 64 | * WaveFormData 65 | -------------------------------------------------------------------------------- /ECGXMLReader.py: -------------------------------------------------------------------------------- 1 | import os 2 | import csv 3 | import array 4 | import base64 5 | import xmltodict 6 | 7 | import numpy as np 8 | 9 | __author__ = "Will Hewitt" 10 | __credits__ = ["Will Hewitt"] 11 | __version__ = "1.0.0" 12 | __maintainer__ = "Will Hewitt" 13 | __email__ = "me@hewittwill.com" 14 | __status__ = "Development" 15 | 16 | class ECGXMLReader: 17 | """ Extract voltage data from a ECG XML file """ 18 | def __init__(self, path, augmentLeads=False): 19 | try: 20 | with open(path, 'rb') as xml: 21 | self.ECG = xmltodict.parse(xml.read().decode('utf8')) 22 | 23 | self.augmentLeads = augmentLeads 24 | self.path = path 25 | 26 | self.PatientDemographics = self.ECG['RestingECG']['PatientDemographics'] 27 | self.TestDemographics = self.ECG['RestingECG']['TestDemographics'] 28 | self.RestingECGMeasurements = self.ECG['RestingECG']['RestingECGMeasurements'] 29 | self.Waveforms = self.ECG['RestingECG']['Waveform'] 30 | 31 | self.LeadVoltages = self.makeLeadVoltages() 32 | 33 | except Exception as e: 34 | print(str(e)) 35 | 36 | def makeLeadVoltages(self): 37 | 38 | num_leads = 0 39 | 40 | leads = {} 41 | 42 | for lead in self.Waveforms['LeadData']: 43 | num_leads += 1 44 | 45 | lead_data = lead['WaveFormData'] 46 | lead_b64 = base64.b64decode(lead_data) 47 | lead_vals = np.array(array.array('h', lead_b64)) 48 | 49 | leads[ lead['LeadID'] ] = lead_vals 50 | 51 | if num_leads == 8 and self.augmentLeads: 52 | 53 | leads['III'] = np.subtract(leads['II'], leads['I']) 54 | leads['aVR'] = np.add(leads['I'], leads['II'])*(-0.5) 55 | leads['aVL'] = np.subtract(leads['I'], 0.5*leads['II']) 56 | leads['aVF'] = np.subtract(leads['II'], 0.5*leads['I']) 57 | 58 | return leads 59 | 60 | def getLeadVoltages(self, LeadID): 61 | return self.LeadVoltages[LeadID] 62 | 63 | def getAllVoltages(self): 64 | return self.LeadVoltages --------------------------------------------------------------------------------