readrawnix.py 3.5 KB

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