readrawnix.py 4.0 KB

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