Skip to content

UN-GCPDS/python-pycollect

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

PyCollect

PyCollect is a software package for collecting data from the GE patient monitors, for the purpose of conducting research and preparing training materials.

%pylab inline
Populating the interactive namespace from numpy and matplotlib

Install

From source

git clone git clone [email protected]:gcpds/pycollect.git
cd pycollect
python setup.py install

From PyPi (not available yet)

pip install pycollect

Usage

There are two main modules, GEDevice that handle the connection and data recollecting, and GEDecode that parse and sort the received data strings.

from pycollect import GEDevice, GEDecode

Collect data

Connection

device = GEDevice()
device.connect('/dev/ttyUSB0')
True
device.stop()

Send request

Subrecords

There are three subrecord types for the actual measurement data:

  • device.DISPL for the displayed values.
  • device.TREND_10S for the 10 s trended values.
  • device.TREND_60S for the 60 s trended values.
import time
# device.request(subtype=device.DISPL) 
# time.sleep(1)
device.request(subtype=device.TREND_10S)
# time.sleep(1)
# device.request(subtype=device.TREND_60S) 
Waveforms

Depending on the total number of samples per second the monitor sends a waveform packet every 1000 ms, 500 ms or 250 ms.
Request up to 8 waveforms but total sample rate should be less than 600 samples/sec, sample rate for ECG is 300, INVP 100, EEG 100, PLETH 100, respiratory (CO2, O2, NO2...) 25 each.

device.request(interval=1, waveform_set=['PLETH', 'ECG1'])
#request more that 600 samples/sec generate an exception
try:
    device.request(waveform_set=['ECG1', 'ECG2', 'ECG3'])
except Exception as error:
    print(error)
Sample rate must be less than 600
from pycollect.modules import WAVEFORMS_DICT

for wave in WAVEFORMS_DICT:
    print("{label}: {samps}".format(**WAVEFORMS_DICT[wave]))
ECG1: 300
ECG2: 300
ECG3: 300
INVP1: 100
INVP2: 100
INVP3: 100
INVP4: 1
INVP5: 100
INVP6: 100
PLETH: 100
CO2: 25
NO2: 25
AA: 25
AWP: 25
FLOW: 1
VOL: 25
RESP: 25
EEG1: 100
EEG2: 100
EEG3: 1
EEG4: 100
TONO_PRESS: 1
SPI_LOOP_STATUS: 1
ENT_100: 1
EEG_BIS: 1

Read data

The transmitted data is recollected asynchronously with a background thread and appended to the BUFFER list.

device.collect(True)

Is possible to check the status of BUFFER with:

print('Length: {} bytes'.format(len(device.BUFFER)))
print(device.BUFFER[:43])
# print(bytes(device.BUFFER))
# (device.READING)
import struct

# struct.unpack('>h', bytes([14, 10]))
[int(_) for _ in struct.pack('>h', 3660)]
Length: 3356 bytes
[126, 40, 0, 164, 10, 0, 0, 95, 178, 51, 91, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 126]





[14, 76]



Exception in thread Thread-9:
Traceback (most recent call last):
  File "/usr/lib/python3.6/site-packages/serial/serialposix.py", line 501, in read
    'device reports readiness to read but returned no data '
serial.serialutil.SerialException: device reports readiness to read but returned no data (device disconnected or multiple access on port?)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib/python3.6/threading.py", line 916, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.6/threading.py", line 864, in run
    self._target(*self._args, **self._kwargs)
  File "/home/yeison/Development/gcpds/pycollect/pycollect/device.py", line 258, in read
    data = self.device.read(size)
  File "/usr/lib/python3.6/site-packages/serial/serialposix.py", line 509, in read
    raise SerialException('read failed: {}'.format(e))
serial.serialutil.SerialException: read failed: device reports readiness to read but returned no data (device disconnected or multiple access on port?)
from datetime import datetime
file = open('{}.raw'.format(datetime.now()), 'wb')
file.write(bytes(device.BUFFER))
file.close()

for clear the buffer just:

device.clear_buffer()

for stop the reading:

device.collect(False)

Decode data

decoder = GEDecode()
decoder.process(device.BUFFER)
print("Modules: ", decoder.MODULES)
print("Active modules: ", decoder.MODULES_ACTIVE)
Modules:  ['INV-BP:p1', 'INV-BP:p2', 'TEMP:t1', 'ECG', 'NINV-BP', 'SpO2', 'NMT', 'ECG-EXTRA', 'ECG-ARRH', 'ECG-12', 'NMT2', 'ENTROPY']
Active modules:  ['TEMP', 'ECG', 'NINV-BP', 'SpO2', 'NMT', 'ECG-EXTRA', 'ECG-ARRH', 'ECG-12', 'NMT2', 'ENTROPY']

The DATA_SUBRECORD will contain the displayed values

decoder.DATA_SUBRECORD
<style scoped> .dataframe tbody tr th:only-of-type { vertical-align: middle; }
.dataframe tbody tr th {
    vertical-align: top;
}

.dataframe thead th {
    text-align: right;
}
</style>
date TEMP TEMP LBL ECG HR ECG ST1 ECG ST2 ECG ST3 ECG IMP-RR ECG: ASY ECG HR SRC ... ECG-12 LEAD CH1 ECG-12 LEAD CH2 ECG-12 LEAD CH3 NMT2 T1 NMT2 T2 NMT2 T3 NMT2 T4 ENTROPY EEG ENTROPY EMG ENTROPY BSR
0 2018-06-27 15:43:00 None T4 71 None None None None False Not selected ... ECG I ECG II Not selected None None None None None None None
1 2018-06-27 15:44:00 None T4 74 None None None None False Not selected ... ECG I ECG II Not selected None None None None None None None
2 2018-06-27 15:45:00 None T4 69 None None None None False Not selected ... ECG I ECG II Not selected None None None None None None None

3 rows × 75 columns

decoder.DATA_SUBRECORD.columns;
decoder.DATA_SUBRECORD[['date', 'ECG HR', 'SpO2', 'TEMP', 'TEMP LBL']]
<style scoped> .dataframe tbody tr th:only-of-type { vertical-align: middle; }
.dataframe tbody tr th {
    vertical-align: top;
}

.dataframe thead th {
    text-align: right;
}
</style>
date ECG HR SpO2 TEMP TEMP LBL
0 2018-06-27 15:43:00 71 94.54 None T4

DATA_WAVE_SUBRECORD will contain the waveforms requested

decoder.DATA_WAVE_SUBRECORD.keys()
dict_keys([])
data = decoder.DATA_WAVE_SUBRECORD['PLETH']

pyplot.figure(None, figsize=(20, 7), dpi=100)
pyplot.plot(data)
pyplot.show()

png

Exception in thread Thread-23:
Traceback (most recent call last):
  File "/usr/lib/python3.6/site-packages/serial/serialposix.py", line 501, in read
    'device reports readiness to read but returned no data '
serial.serialutil.SerialException: device reports readiness to read but returned no data (device disconnected or multiple access on port?)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib/python3.6/threading.py", line 916, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.6/threading.py", line 864, in run
    self._target(*self._args, **self._kwargs)
  File "/home/yeison/Development/gcpds/pycollect/pycollect/device.py", line 258, in read
    data = self.device.read(size)
  File "/usr/lib/python3.6/site-packages/serial/serialposix.py", line 509, in read
    raise SerialException('read failed: {}'.format(e))
serial.serialutil.SerialException: read failed: device reports readiness to read but returned no data (device disconnected or multiple access on port?)

Save data

The data can be saved in two differents formats csv and edf, each type of data will be saved with their own sufix: .wave for waveforms, .trend10s and .trend60s for trends.

Save data as CSV

decoder.save_as_csv('data_out')

Save data as EDF+

The edf format need extra patient information.

decoder.set_edf_header(
    admincode = '',
    birthdate = date(1900, 1, 1), #datetime object
    equipment = '',
    gender = 0, #0 for male, 1 for female
    patientcode = '',
    patientname = '',
    patient_additional = '',
    recording_additional = '',
    technician = '',
)

decoder.save_as_edf('data_out')

Output

References

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published