readrawnix.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. import os
  2. import sys
  3. import numpy as np
  4. import nixio as nix
  5. import mne
  6. DATA_BLOCK_NAME = "EEG Data Block"
  7. DATA_BLOCK_TYPE = "Recording"
  8. RAW_DATA_GROUP_NAME = "Raw Data Group"
  9. RAW_DATA_GROUP_TYPE = "EEG Channels"
  10. RAW_DATA_TYPE = "Raw Data"
  11. typemap = {
  12. "str": str,
  13. "int": int,
  14. "float": float,
  15. "bool": bool,
  16. "tuple": tuple,
  17. "list": list,
  18. "numpy.float64": np.float64,
  19. "numpy.ndarray": np.array,
  20. }
  21. def convert_prop_type(prop):
  22. pt = prop.type[8:-2]
  23. pv = prop.values
  24. if len(pv) == 1:
  25. pv = pv[0]
  26. return typemap[pt](pv)
  27. def md_to_dict(section):
  28. sdict = dict()
  29. for prop in section.props:
  30. sdict[prop.name] = convert_prop_type(prop)
  31. if section.type[8:-2] == "mne.transforms.Transform":
  32. to = sdict["to"]
  33. fro = sdict["from"]
  34. trans = sdict["trans"]
  35. trans = section.referring_data_arrays[0][:]
  36. return mne.Transform(fro=fro, to=to, trans=trans)
  37. for sec in section.sections:
  38. if sec.name == "chs":
  39. # make a list of dictionaries for the channels
  40. chlist = list()
  41. for chsec in sec.sections:
  42. chlist.append(md_to_dict(chsec))
  43. sdict[sec.name] = chlist
  44. else:
  45. sdict[sec.name] = md_to_dict(sec)
  46. return sdict
  47. def merge_data_arrays(arrays):
  48. rows = [a[:] for a in arrays]
  49. return np.array(rows)
  50. def create_mne_annotations(mtags):
  51. onset = list()
  52. duration = list()
  53. description = list()
  54. for mtag in mtags:
  55. posshape = mtag.positions.shape
  56. if len(posshape) == 1:
  57. onset.extend(mtag.positions)
  58. duration.extend(mtag.extents)
  59. else:
  60. onset.extend([p[1] for p in mtag.positions])
  61. duration.extend([e[1] for e in mtag.extents])
  62. description.extend(mtag.positions.dimensions[0].labels)
  63. return mne.Annotations(onset=onset,
  64. duration=duration,
  65. description=description)
  66. def import_nix(nixfilename):
  67. nixfile = nix.File(nixfilename, mode=nix.FileMode.ReadOnly)
  68. root, ext = os.path.splitext(nixfilename)
  69. bvfilename = root + os.extsep + "edf"
  70. bvfile = mne.io.read_raw_edf(bvfilename, stim_channel=False)
  71. # Create MNE Info object
  72. infosec = nixfile.sections["Info"]
  73. nchan = infosec["nchan"]
  74. sfreq = infosec["sfreq"]
  75. info = mne.create_info(nchan, sfreq)
  76. nixinfodict = md_to_dict(infosec)
  77. info.update(nixinfodict)
  78. # Read raw data into MNE objects
  79. datagroup = nixfile.blocks[DATA_BLOCK_NAME].groups[RAW_DATA_GROUP_NAME]
  80. if len(datagroup.data_arrays) > 1:
  81. # Data split: One DataArray per channel. Merging
  82. nixrawdata = merge_data_arrays(datagroup.data_arrays)
  83. else:
  84. nixrawdata = datagroup.data_arrays[0][:]
  85. # Create MNE RawArray
  86. mnerawdata = mne.io.RawArray(nixrawdata, info)
  87. # Add annotations: Stimuli from MultiTags
  88. mtags = datagroup.multi_tags
  89. annotations = create_mne_annotations(mtags)
  90. mnerawdata.set_annotations(annotations)
  91. # print("NIX")
  92. # print(nixfile.sections["Extras"].props)
  93. # print("=============\n\nEDF")
  94. # print(bvfile._raw_extras)
  95. nixfile.close()
  96. return mnerawdata
  97. def main():
  98. if len(sys.argv) < 2:
  99. print("Please provide either a NIX filename as the first argument")
  100. sys.exit(1)
  101. nixfilename = sys.argv[1]
  102. import_nix(nixfilename)
  103. if __name__ == "__main__":
  104. main()