-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathraw2xdf.py
More file actions
112 lines (100 loc) · 3.82 KB
/
Copy pathraw2xdf.py
File metadata and controls
112 lines (100 loc) · 3.82 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# -*- coding: utf-8 -*-
"""
Created on Wed Dec 5 12:56:31 2018
@author: skjerns
Gist to save a mne.io.Raw object to an EDF file using pyEDFlib
(https://github.com/holgern/pyedflib)
Disclaimer:
- Saving your data this way will result in slight
loss of precision (magnitude +-1e-09).
- It is assumed that the data is presented in Volt (V),
it will be internally converted to microvolt
- BDF or EDF+ is selected based on the filename extension
- Annotations are lost in the process.
Let me know if you need them, should be easy to add.
"""
import pyedflib # pip install pyedflib
from pyedflib import highlevel # new high-level interface
from pyedflib import FILETYPE_BDF, FILETYPE_BDFPLUS, FILETYPE_EDF, FILETYPE_EDFPLUS
from datetime import datetime, timezone, timedelta
import mne
import os
import traceback
def _stamp_to_dt(utc_stamp):
"""Convert timestamp to datetime object in Windows-friendly way."""
# The min on windows is 86400
stamp = [int(s) for s in utc_stamp]
if len(stamp) == 1: # In case there is no microseconds information
stamp.append(0)
return (datetime.fromtimestamp(0, tz=timezone.utc) +
timedelta(0, stamp[0], stamp[1])) # day, sec, μs
def write_npy_edf(array, info, fname, overwrite=False):
"""
Saves the raw content of an MNE.io.Raw and its subclasses to
a file using the EDF+/BDF filetype
pyEDFlib is used to save the raw contents of the RawArray to disk
Parameters
----------
array : np.ndarray
numpy array (nchan;nsamples)
info : mne.Info
An object containing
fname : string
File name of the new dataset. This has to be a new filename
unless data have been preloaded. Filenames should end with .edf
overwrite : bool
If True, the destination file (if it exists) will be overwritten.
If False (default), an error will be raised if the file exists.
"""
if not overwrite and os.path.exists(fname):
raise OSError('File already exists. No overwrite.')
# static settings
has_annotations = False
if os.path.splitext(fname)[-1] == '.edf':
file_type = FILETYPE_EDFPLUS if has_annotations else FILETYPE_EDF
dmin, dmax = -32768, 32767
else:
file_type = FILETYPE_BDFPLUS if has_annotations else FILETYPE_BDF
dmin, dmax = -8388608, 8388607
print('saving to {}, filetype {}'.format(fname, file_type))
sfreq = info['sfreq']
date = _stamp_to_dt(info['meas_date'])
date = date.strftime('%d %b %Y %H:%M:%S')
first_sample = 0
last_sample = max(array.shape)
# convert data
channels = array
# convert to microvolts to scale up precision
channels *= 1e6
# set conversion parameters
n_channels = len(channels)
print (n_channels)
# create channel from this
try:
f = pyedflib.EdfWriter(fname,
n_channels=n_channels,
file_type=file_type)
channel_info = []
ch_idx = range(n_channels)
for i in ch_idx:
ch_dict = {'label': info['ch_names'][i],
'dimension': 'uV',
'sample_rate': info['sfreq'],
'physical_min': channels.min(),
'physical_max': channels.max(),
'digital_min': dmin,
'digital_max': dmax,
'transducer': '',
'prefilter': ''}
channel_info.append(ch_dict)
f.setTechnician('ak')
f.setSignalHeaders(channel_info)
f.setStartdatetime(date)
print(channels.shape)
f.writeSamples(channels)
except Exception:
print (traceback.format_exc())
return False
finally:
f.close()
return True