qlsdk2 0.6.0__py3-none-any.whl → 0.6.0a1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- qlsdk/core/entity/__init__.py +32 -90
- qlsdk/persist/ars_edf.py +101 -80
- qlsdk/persist/rsc_edf.py +12 -20
- qlsdk/rsc/command/__init__.py +12 -26
- qlsdk/rsc/device/arskindling.py +310 -248
- qlsdk/rsc/device/base.py +82 -158
- qlsdk/rsc/device/c16_rs.py +5 -1
- qlsdk/rsc/device/c256_rs.py +330 -16
- qlsdk/rsc/device/c64_rs.py +332 -2
- qlsdk/rsc/device/c64s1.py +340 -4
- qlsdk/rsc/interface/device.py +1 -22
- qlsdk/rsc/paradigm.py +6 -127
- qlsdk/rsc/parser/base.py +6 -11
- {qlsdk2-0.6.0.dist-info → qlsdk2-0.6.0a1.dist-info}/METADATA +16 -12
- {qlsdk2-0.6.0.dist-info → qlsdk2-0.6.0a1.dist-info}/RECORD +17 -17
- {qlsdk2-0.6.0.dist-info → qlsdk2-0.6.0a1.dist-info}/WHEEL +1 -1
- {qlsdk2-0.6.0.dist-info → qlsdk2-0.6.0a1.dist-info}/top_level.txt +0 -0
qlsdk/rsc/device/base.py
CHANGED
|
@@ -5,30 +5,13 @@ from typing import Any, Dict, Literal
|
|
|
5
5
|
|
|
6
6
|
from loguru import logger
|
|
7
7
|
import numpy as np
|
|
8
|
-
from qlsdk.core.entity import RscPacket
|
|
8
|
+
from qlsdk.core.entity import RscPacket
|
|
9
9
|
from qlsdk.core.utils import to_bytes
|
|
10
10
|
from qlsdk.rsc.interface import IDevice, IParser
|
|
11
|
-
from qlsdk.rsc.command import
|
|
12
|
-
from qlsdk.rsc.paradigm import StimulationParadigm
|
|
11
|
+
from qlsdk.rsc.command import StartImpedanceCommand, StopImpedanceCommand, StartStimulationCommand, StopStimulationCommand, SetAcquisitionParamCommand, StartAcquisitionCommand, StopAcquisitionCommand
|
|
13
12
|
from qlsdk.rsc.parser.base import TcpMessageParser
|
|
14
13
|
|
|
15
|
-
|
|
16
|
-
def intersection_positions(A, B):
|
|
17
|
-
setB = set(B)
|
|
18
|
-
seen = set()
|
|
19
|
-
return [idx for idx, elem in enumerate(A)
|
|
20
|
-
if elem in setB and elem not in seen and not seen.add(elem)]
|
|
21
|
-
|
|
22
14
|
class QLBaseDevice(IDevice):
|
|
23
|
-
|
|
24
|
-
__TRIGGER_MAPPING = {
|
|
25
|
-
0x3E8: "Start of stimulation",
|
|
26
|
-
0x3E9: "End of stimulation",
|
|
27
|
-
0x3EA: "Ascending end of stimulation",
|
|
28
|
-
0x3EB: "Descending start of stimulation ",
|
|
29
|
-
0x3EC: "刺激参数有误",
|
|
30
|
-
0x3ED: "End of stimulation (by force)",
|
|
31
|
-
}
|
|
32
15
|
def __init__(self, socket):
|
|
33
16
|
self.socket = socket
|
|
34
17
|
|
|
@@ -78,11 +61,52 @@ class QLBaseDevice(IDevice):
|
|
|
78
61
|
"channels": [],
|
|
79
62
|
}
|
|
80
63
|
|
|
81
|
-
self._stim_param =
|
|
82
|
-
|
|
83
|
-
|
|
64
|
+
self._stim_param = {
|
|
65
|
+
"stim_type": 0, # 刺激类型:0-所有通道参数相同, 1: 通道参数不同
|
|
66
|
+
"channels": [],
|
|
67
|
+
"param": [{
|
|
68
|
+
"channel_id": 0, #通道号 从0开始 -- 必填
|
|
69
|
+
"waveform": 3, #波形类型:0-直流,1-交流 2-方波 3-脉冲 -- 必填
|
|
70
|
+
"current": 1, #电流强度(mA) -- 必填
|
|
71
|
+
"duration": 30, #平稳阶段持续时间(s) -- 必填
|
|
72
|
+
"ramp_up": 5, #上升时间(s) 默认0
|
|
73
|
+
"ramp_down": 5, #下降时间(s) 默认0
|
|
74
|
+
"frequency": 500, #频率(Hz) -- 非直流必填
|
|
75
|
+
"phase_position": 0, #相位 -- 默认0
|
|
76
|
+
"duration_delay": "0", #延迟启动时间(s) -- 默认0
|
|
77
|
+
"pulse_width": 0, #脉冲宽度(us) -- 仅脉冲类型电流有效, 默认100us
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"channel_id": 1, #通道号 从0开始 -- 必填
|
|
81
|
+
"waveform": 3, #波形类型:0-直流,1-交流 2-方波 3-脉冲 -- 必填
|
|
82
|
+
"current": 1, #电流强度(mA) -- 必填
|
|
83
|
+
"duration": 30, #平稳阶段持续时间(s) -- 必填
|
|
84
|
+
"ramp_up": 5, #上升时间(s) 默认0
|
|
85
|
+
"ramp_down": 5, #下降时间(s) 默认0
|
|
86
|
+
"frequency": 500, #频率(Hz) -- 非直流必填
|
|
87
|
+
"phase_position": 0, #相位 -- 默认0
|
|
88
|
+
"duration_delay": "0", #延迟启动时间(s) -- 默认0
|
|
89
|
+
"pulse_width": 0, #脉冲宽度(us) -- 仅脉冲类型电流有效, 默认100us
|
|
90
|
+
}
|
|
91
|
+
]
|
|
92
|
+
}
|
|
84
93
|
|
|
85
|
-
self.stim_paradigm
|
|
94
|
+
self.stim_paradigm = None
|
|
95
|
+
|
|
96
|
+
signal_info = {
|
|
97
|
+
"param" : None,
|
|
98
|
+
"start_time" : None,
|
|
99
|
+
"finished_time" : None,
|
|
100
|
+
"packet_total" : None,
|
|
101
|
+
"last_packet_time" : None,
|
|
102
|
+
"state" : 0
|
|
103
|
+
}
|
|
104
|
+
stim_info = {
|
|
105
|
+
|
|
106
|
+
}
|
|
107
|
+
Impedance_info = {
|
|
108
|
+
|
|
109
|
+
}
|
|
86
110
|
# 信号采集状态
|
|
87
111
|
# 信号数据包总数(一个信号采集周期内)
|
|
88
112
|
# 信号采集参数
|
|
@@ -103,9 +127,6 @@ class QLBaseDevice(IDevice):
|
|
|
103
127
|
self.storage_enable = True
|
|
104
128
|
self._listening = False
|
|
105
129
|
# self.ready()
|
|
106
|
-
self._signal_cache: Queue = None
|
|
107
|
-
self._recording = False
|
|
108
|
-
|
|
109
130
|
|
|
110
131
|
def parser(self) -> IParser:
|
|
111
132
|
return self._parser
|
|
@@ -115,54 +136,24 @@ class QLBaseDevice(IDevice):
|
|
|
115
136
|
|
|
116
137
|
# 数据包处理
|
|
117
138
|
def produce(self, body: bytes, type:Literal['signal', 'impedance']="signal"):
|
|
118
|
-
if body is None: return
|
|
119
|
-
|
|
120
|
-
if type == "signal":
|
|
121
|
-
self._produce_signal(body)
|
|
122
|
-
elif type == "impedance":
|
|
123
|
-
self._produce_impedance(body)
|
|
124
|
-
|
|
125
|
-
def _produce_impedance(self, body: bytes):
|
|
126
|
-
# 分发阻抗数据包给订阅者
|
|
127
|
-
if len(self._impedance_consumer) > 0:
|
|
128
|
-
packet = self._impedance_wrapper(body)
|
|
129
|
-
for topic, q in self._impedance_consumer.items():
|
|
130
|
-
try:
|
|
131
|
-
# 队列满了就丢弃最早的数据
|
|
132
|
-
if q.full():
|
|
133
|
-
q.get()
|
|
134
|
-
q.put(packet, timeout=1)
|
|
135
|
-
except Exception as e:
|
|
136
|
-
logger.error(f"impedance data put to queue exception: {str(e)}")
|
|
137
|
-
|
|
138
|
-
def _produce_signal(self, body: bytes):
|
|
139
|
+
if body is None: return
|
|
139
140
|
|
|
140
141
|
# 处理信号数据
|
|
141
|
-
data = self._signal_wrapper(body)
|
|
142
|
+
data = self._signal_wrapper(body)
|
|
142
143
|
# logger.debug("pkg_id: {}, eeg len: {}".format(data.pkg_id, len(data.eeg)))
|
|
143
144
|
#
|
|
144
145
|
trigger_positions = [index for index, value in enumerate(data.trigger) if value != 0]
|
|
145
146
|
if len(trigger_positions) > 0:
|
|
146
147
|
# logger.debug(f"Trigger触发点位置: {trigger_positions}, 触发点时间戳: {[data.time_stamp + int(pos * 1000 / data.sample_rate) for pos in trigger_positions]}")
|
|
147
148
|
for pos in trigger_positions:
|
|
148
|
-
self.trigger(
|
|
149
|
+
self.trigger(data.trigger[pos])
|
|
149
150
|
# 存储
|
|
150
|
-
if self.storage_enable:
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
self._start_recording()
|
|
154
|
-
|
|
155
|
-
# 写入文件的缓存队列
|
|
156
|
-
if self._signal_cache is None:
|
|
157
|
-
self._signal_cache = Queue(256 * 1024 * 1024) # 256MB缓存
|
|
158
|
-
tmp = data.copy()
|
|
159
|
-
self._signal_cache.put(tmp)
|
|
160
|
-
|
|
151
|
+
if self.storage_enable:
|
|
152
|
+
self._write_signal(data)
|
|
153
|
+
|
|
161
154
|
if len(self.signal_consumers) > 0 :
|
|
162
|
-
logger.trace(f"dg eeg: {data.eeg}")
|
|
163
155
|
# 信号数字值转物理值
|
|
164
156
|
data.eeg = self.eeg2phy(np.array(data.eeg))
|
|
165
|
-
logger.trace(f"ph eeg: {data.eeg}")
|
|
166
157
|
|
|
167
158
|
# 发送数据包到订阅者
|
|
168
159
|
for q in list(self.signal_consumers.values()):
|
|
@@ -170,51 +161,20 @@ class QLBaseDevice(IDevice):
|
|
|
170
161
|
if q.full():
|
|
171
162
|
q.get()
|
|
172
163
|
|
|
173
|
-
q.put(data)
|
|
174
|
-
|
|
175
|
-
def _impedance_wrapper(self, body: bytes):
|
|
176
|
-
packet = ImpedancePacket().transfer(body)
|
|
177
|
-
if self._impedance_channels is not None and len(self._impedance_channels) > 0:
|
|
178
|
-
# 只保留设置的阻抗通道
|
|
179
|
-
channel_pos = intersection_positions(packet.channels, self._impedance_channels)
|
|
180
|
-
packet.impedance = [packet.impedance[i] for i in channel_pos]
|
|
181
|
-
packet.channels = [packet.channels[i] for i in channel_pos]
|
|
182
|
-
|
|
183
|
-
return packet
|
|
164
|
+
q.put(data)
|
|
184
165
|
|
|
185
166
|
# 信号数据转换
|
|
186
167
|
def _signal_wrapper(self, body: bytes):
|
|
187
168
|
return RscPacket().transfer(body)
|
|
188
169
|
|
|
189
|
-
def _write_signal(self):
|
|
170
|
+
def _write_signal(self, data: RscPacket):
|
|
190
171
|
# 文件写入到edf
|
|
191
172
|
if self._edf_handler is None:
|
|
192
173
|
logger.debug("Initializing EDF handler for data storage")
|
|
193
174
|
self.init_edf_handler()
|
|
194
175
|
|
|
195
|
-
|
|
196
|
-
data = self._signal_cache.get()
|
|
176
|
+
if self._edf_handler:
|
|
197
177
|
self._edf_handler.write(data)
|
|
198
|
-
if data is None:
|
|
199
|
-
break
|
|
200
|
-
|
|
201
|
-
self._recording = False
|
|
202
|
-
def _start_recording(self):
|
|
203
|
-
if self.storage_enable is False:
|
|
204
|
-
logger.trace("Storage is disabled, will not start recording")
|
|
205
|
-
return
|
|
206
|
-
|
|
207
|
-
if self._signal_cache is None:
|
|
208
|
-
self._signal_cache = Queue(256 * 1024 * 1024) # 256MB缓存
|
|
209
|
-
|
|
210
|
-
try:
|
|
211
|
-
self._recording = True
|
|
212
|
-
t = Thread(target=self._write_signal, daemon=True)
|
|
213
|
-
t.start()
|
|
214
|
-
logger.info(f"开启记录")
|
|
215
|
-
except Exception as e:
|
|
216
|
-
logger.error(f"开启记录失败: {str(e)}")
|
|
217
|
-
return
|
|
218
178
|
|
|
219
179
|
def start_listening(self):
|
|
220
180
|
|
|
@@ -254,12 +214,6 @@ class QLBaseDevice(IDevice):
|
|
|
254
214
|
def device_type(self) -> int:
|
|
255
215
|
return self._device_type
|
|
256
216
|
|
|
257
|
-
def set_impedance_channels(self, channels):
|
|
258
|
-
self._impedance_channels = channels
|
|
259
|
-
|
|
260
|
-
def get_impedance_channels(self):
|
|
261
|
-
return self._impedance_channels
|
|
262
|
-
|
|
263
217
|
def start_message_parser(self) -> None:
|
|
264
218
|
self._parser = TcpMessageParser(self)
|
|
265
219
|
self._parser.start()
|
|
@@ -331,7 +285,7 @@ class QLBaseDevice(IDevice):
|
|
|
331
285
|
@property
|
|
332
286
|
def edf_handler(self):
|
|
333
287
|
if not self.storage_enable:
|
|
334
|
-
logger.
|
|
288
|
+
logger.warning("EDF storage is disabled, no edf handler available")
|
|
335
289
|
return None
|
|
336
290
|
|
|
337
291
|
if self._edf_handler is None:
|
|
@@ -365,12 +319,8 @@ class QLBaseDevice(IDevice):
|
|
|
365
319
|
return self._impedance_consumer
|
|
366
320
|
|
|
367
321
|
# 设置记录文件路径
|
|
368
|
-
def set_storage_path(self,
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
abs_path = os.path.abspath(dir)
|
|
372
|
-
os.makedirs(abs_path, exist_ok=True)
|
|
373
|
-
self._storage_path = abs_path
|
|
322
|
+
def set_storage_path(self, path):
|
|
323
|
+
self._storage_path = path
|
|
374
324
|
|
|
375
325
|
# 设置记录文件名称前缀
|
|
376
326
|
def set_file_prefix(self, prefix):
|
|
@@ -385,27 +335,23 @@ class QLBaseDevice(IDevice):
|
|
|
385
335
|
self.stim_paradigm = param
|
|
386
336
|
|
|
387
337
|
# 设置采集参数
|
|
388
|
-
def set_acq_param(self, channels, sample_rate
|
|
338
|
+
def set_acq_param(self, channels, sample_rate = 500, sample_range = 188):
|
|
389
339
|
self._acq_param["channels"] = channels
|
|
390
340
|
self._acq_param["sample_rate"] = sample_rate
|
|
391
341
|
self._acq_param["sample_range"] = sample_range
|
|
392
342
|
self._acq_channels = channels
|
|
393
343
|
self._sample_rate = sample_rate
|
|
394
344
|
self._sample_range = sample_range
|
|
345
|
+
|
|
346
|
+
# 通用配置-TODO
|
|
347
|
+
def set_config(self, key:str, val: str):
|
|
348
|
+
pass
|
|
395
349
|
|
|
396
350
|
def start_impedance(self):
|
|
397
351
|
logger.info(f"[设备-{self.device_no}]启动阻抗测量")
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
set_param_msg = bytes.fromhex(f'5aa50239{device_id}3f0000001104ffffffffffffffff000000000000000000000000000000000000000000000000e8030000fa00000010000164000000745c5aa50239390045243a00000012040000000000000000000000000000000000000000000000000000000000000000000001000000000000004c2a')
|
|
402
|
-
logger.debug(f"set_param_msg message is {set_param_msg.hex()}")
|
|
403
|
-
self.socket.sendall(set_param_msg)
|
|
404
|
-
sleep(0.5)
|
|
405
|
-
|
|
406
|
-
impedance_start_msg = StartImpedanceCommand.build(self).pack()
|
|
407
|
-
logger.debug(f"start_impedance message is {impedance_start_msg.hex()}")
|
|
408
|
-
self.socket.sendall(impedance_start_msg)
|
|
352
|
+
msg = StartImpedanceCommand.build(self).pack()
|
|
353
|
+
logger.trace(f"start_impedance message is {msg.hex()}")
|
|
354
|
+
self.socket.sendall(msg)
|
|
409
355
|
|
|
410
356
|
def stop_impedance(self):
|
|
411
357
|
logger.info(f"[设备{self.device_no}]停止阻抗测量")
|
|
@@ -421,11 +367,8 @@ class QLBaseDevice(IDevice):
|
|
|
421
367
|
msg = StartStimulationCommand.build(self).pack()
|
|
422
368
|
logger.trace(f"start_stimulation message is {msg.hex()}")
|
|
423
369
|
self.socket.sendall(msg)
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
def get_stim_param(self) -> bytes:
|
|
428
|
-
return self.stim_paradigm.to_bytes()
|
|
370
|
+
t = Thread(target=self._stop_stimulation_trigger, args=(self.stim_paradigm.duration,), daemon=True)
|
|
371
|
+
t.start()
|
|
429
372
|
|
|
430
373
|
def _stop_stimulation_trigger(self, duration):
|
|
431
374
|
delay = duration
|
|
@@ -433,22 +376,23 @@ class QLBaseDevice(IDevice):
|
|
|
433
376
|
sleep(1)
|
|
434
377
|
delay -= 1
|
|
435
378
|
logger.debug(f"_stop_stimulation_trigger duration: {duration}")
|
|
436
|
-
if self.
|
|
437
|
-
self.
|
|
379
|
+
if self._edf_handler:
|
|
380
|
+
self._edf_handler.trigger("stimulation should be stopped")
|
|
438
381
|
else:
|
|
439
382
|
logger.warning("stop stim trigger fail. no edf writer alive")
|
|
440
383
|
|
|
441
384
|
def stop_stimulation(self):
|
|
442
385
|
logger.info(f"[设备-{self.device_no}]停止电刺激")
|
|
443
|
-
msg = StopStimulationCommand.
|
|
386
|
+
msg = StopStimulationCommand.pack()
|
|
444
387
|
logger.trace(f"stop_stimulation message is {msg.hex()}")
|
|
445
388
|
self.socket.sendall(msg)
|
|
446
389
|
|
|
447
390
|
# 启动采集
|
|
448
|
-
def start_acquisition(self):
|
|
391
|
+
def start_acquisition(self, recording = True):
|
|
449
392
|
logger.info(f"[设备-{self.device_no}]启动信号采集")
|
|
450
|
-
|
|
451
|
-
|
|
393
|
+
self._recording = recording
|
|
394
|
+
# 初始化EDF处理器
|
|
395
|
+
self.init_edf_handler()
|
|
452
396
|
# 设置数据采集参数
|
|
453
397
|
param_bytes = SetAcquisitionParamCommand.build(self).pack()
|
|
454
398
|
# 启动数据采集
|
|
@@ -463,10 +407,9 @@ class QLBaseDevice(IDevice):
|
|
|
463
407
|
msg = StopAcquisitionCommand.build(self).pack()
|
|
464
408
|
logger.trace(f"stop_acquisition message is {msg.hex()}")
|
|
465
409
|
self.socket.sendall(msg)
|
|
466
|
-
|
|
467
|
-
if self._signal_cache:
|
|
410
|
+
if self._edf_handler:
|
|
468
411
|
# 发送结束标识
|
|
469
|
-
self.
|
|
412
|
+
self.edf_handler.write(None)
|
|
470
413
|
|
|
471
414
|
'''
|
|
472
415
|
订阅数据
|
|
@@ -484,7 +427,7 @@ class QLBaseDevice(IDevice):
|
|
|
484
427
|
|
|
485
428
|
# 数据队列
|
|
486
429
|
if q is None:
|
|
487
|
-
q = Queue(maxsize=
|
|
430
|
+
q = Queue(maxsize=1000)
|
|
488
431
|
|
|
489
432
|
# 订阅生理电信号数据
|
|
490
433
|
if type == "signal":
|
|
@@ -504,12 +447,11 @@ class QLBaseDevice(IDevice):
|
|
|
504
447
|
return topic, q
|
|
505
448
|
|
|
506
449
|
def trigger(self, desc):
|
|
507
|
-
if self.
|
|
450
|
+
if self._edf_handler:
|
|
508
451
|
self.edf_handler.trigger(desc)
|
|
509
452
|
else:
|
|
510
|
-
logger.
|
|
453
|
+
logger.warning("没有开启文件记录时,无法记录trigger信息")
|
|
511
454
|
|
|
512
|
-
# 设置信号采集参数
|
|
513
455
|
def gen_set_acquirement_param(self) -> bytes:
|
|
514
456
|
|
|
515
457
|
body = to_bytes(self.acq_channels)
|
|
@@ -520,19 +462,7 @@ class QLBaseDevice(IDevice):
|
|
|
520
462
|
body += bytes.fromhex('00')
|
|
521
463
|
|
|
522
464
|
return body
|
|
523
|
-
|
|
524
|
-
def gen_set_impedance_param(self) -> bytes:
|
|
525
|
-
|
|
526
|
-
# 仅通道生效 32字节,其他不生效-272字节,实际73字节
|
|
527
|
-
body = to_bytes(self._impedance_channels)
|
|
528
|
-
# 100 bytes
|
|
529
|
-
# body += bytes.fromhex('00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000')
|
|
530
|
-
# # 100 bytes
|
|
531
|
-
# body += bytes.fromhex('00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000')
|
|
532
|
-
# 73 bytes
|
|
533
|
-
body += bytes.fromhex('00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000')
|
|
534
|
-
|
|
535
|
-
return bytes.fromhex('ffffffffffffffff000000000000000000000000000000000000000000000000e8030000fa00000010000164000000745c5aa50239390045243a0000001204000000000000000000000000000000000000000000000000000000000000000000000100000000000000')
|
|
465
|
+
|
|
536
466
|
def disconnect(self):
|
|
537
467
|
logger.info(f"[断开设备-{self.device_no}]的连接...")
|
|
538
468
|
self._listening = False
|
|
@@ -546,12 +476,6 @@ class QLBaseDevice(IDevice):
|
|
|
546
476
|
|
|
547
477
|
# 关闭解析器
|
|
548
478
|
self._parser.stop()
|
|
549
|
-
|
|
550
|
-
def enable_storage(self, enable: bool = True):
|
|
551
|
-
self.storage_enable = enable
|
|
552
|
-
|
|
553
|
-
def trigger_info(self, code: int) -> str:
|
|
554
|
-
return QLBaseDevice.__TRIGGER_MAPPING.get(code, hex(code))
|
|
555
479
|
|
|
556
480
|
def __str__(self):
|
|
557
481
|
return f'''
|
qlsdk/rsc/device/c16_rs.py
CHANGED
|
@@ -115,7 +115,11 @@ class C16RS(QLBaseDevice):
|
|
|
115
115
|
self._edf_handler.set_device_no(self.device_no)
|
|
116
116
|
self._edf_handler.set_storage_path(self._storage_path)
|
|
117
117
|
self._edf_handler.set_file_prefix(self._file_prefix if self._file_prefix else 'C16R')
|
|
118
|
-
|
|
118
|
+
|
|
119
|
+
# 设置刺激参数
|
|
120
|
+
def set_stim_param(self, param):
|
|
121
|
+
self.stim_paradigm = param
|
|
122
|
+
|
|
119
123
|
# 设置采集参数
|
|
120
124
|
def set_acq_param(self, channels, sample_rate = 500, sample_range = 188):
|
|
121
125
|
# 保存原始通道参数
|