sig_save.py 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. """保存数据为bdf格式"""
  2. import logging
  3. import pyedflib
  4. logger = logging.getLogger(__name__)
  5. class SigSaveHigh():
  6. """数据保存类:使用highlevel API,简化了保存代码,
  7. 一次保存一个文件"""
  8. def __init__(self, mne_raw_data):
  9. """初始化SigSave
  10. Args:
  11. mne_raw_data (class): mne.io.array.array.RawArray
  12. """
  13. self.raw_data = mne_raw_data
  14. def save(self, file_name, name, gender):
  15. """保存
  16. Args:
  17. file_name (str): 保存的文件名
  18. name (Optional[str], optional): bdf头信息中的姓名. Defaults to None.
  19. gender (Optional[str], optional): bdf头信息中的性别. Defaults to None.
  20. """
  21. signals = self.raw_data.get_data()
  22. channel_names = self.raw_data.info.get_montage().ch_names
  23. signal_headers = pyedflib.highlevel.make_signal_headers(
  24. channel_names, sample_frequency=self.raw_data.info["sfreq"])
  25. header = pyedflib.highlevel.make_header(patientname=name, gender=gender)
  26. pyedflib.highlevel.write_edf(file_name, signals, signal_headers, header)
  27. class SigSave():
  28. """数据保存类: 使用基本的保存API,可以持续将数据写入一个文件"""
  29. def __init__(self, channel_labels, sample_rate, physical_max, physical_min):
  30. """初始化保存数据类
  31. Args:
  32. channel_labels (list): 导联标签,例如:['C3','C4']
  33. sample_rate (int): 采样率
  34. physical_max (int): 最大物理值,与设备相关, 例如pony:375000 neo:200000
  35. physical_min (int): 最小物理值,与设备相关, 例如pony:-375000 neo:-200000
  36. """
  37. self.channel_labels = channel_labels
  38. self.sample_rate = sample_rate
  39. self.physical_max = physical_max
  40. self.physical_min = physical_min
  41. self.is_ready = False
  42. self.is_first = False
  43. def set_edf_header(self, subject, filename, task_per_run, path):
  44. """ 用于设置EDF头部信息
  45. Args:
  46. subject (class): 受试数据库实体
  47. path (str): 存储数据路径
  48. """
  49. channel_info = []
  50. channel_count = len(self.channel_labels)
  51. self.path = path + "/" + filename
  52. self.edf_w = pyedflib.EdfWriter(self.path,
  53. channel_count,
  54. file_type=pyedflib.FILETYPE_BDFPLUS)
  55. for label_num in range(channel_count):
  56. ch_dict = {
  57. "label": self.channel_labels[label_num],
  58. "dimension": "uV",
  59. "sample_frequency": self.sample_rate,
  60. "physical_max": self.physical_max,
  61. "physical_min": self.physical_min,
  62. "digital_max": 8388607,
  63. "digital_min": -8388608,
  64. }
  65. channel_info.append(ch_dict)
  66. self.edf_w.setSignalHeaders(channel_info)
  67. self.edf_w.setPatientName(subject.name)
  68. if subject.gender == "男":
  69. self.edf_w.setGender(1)
  70. elif subject.gender == "女":
  71. self.edf_w.setGender(0)
  72. self.edf_w.setBirthdate(subject.birthday)
  73. self.edf_w.setPatientCode(subject.id_card)
  74. self.edf_w.setRecordingAdditional(str(task_per_run))
  75. self.is_ready = True
  76. self.is_first = True
  77. self.start_record_timestamp = 0
  78. def save_raw_data(self, signals, timestamp=None):
  79. """向打开的文件写入数据,可以持续写入,直到调用close_edf_file时则无法写入
  80. Args:
  81. signals (np array): 需要保存的数据,channels*samples
  82. """
  83. if self.is_ready:
  84. if self.is_first and timestamp:
  85. self.start_record_timestamp = timestamp
  86. self.is_first = False
  87. self.edf_w.writeSamples(signals)
  88. else:
  89. logger.info(
  90. "not ready for save, maybe edf/bdf header has not been set")
  91. def edf_data_mark(self, timestamp, mark: str):
  92. """给数据打标记
  93. Args:
  94. timestamp (int): 标记的时间点
  95. mark (str): 标记的信息
  96. """
  97. if self.is_ready:
  98. time_seconds = (timestamp - self.start_record_timestamp) / 1000
  99. self.edf_w.writeAnnotation(time_seconds, -1, mark)
  100. else:
  101. logger.info(
  102. "not ready for save, maybe edf/bdf header has not been set")
  103. def close_edf_file(self):
  104. """关闭BDF文件
  105. """
  106. self.edf_w.close()
  107. self.is_ready = False