qlsdk2 0.5.1.1__py3-none-any.whl → 0.6.0__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/persist/rsc_edf.py CHANGED
@@ -15,7 +15,7 @@ EDF_FILE_TYPE = {
15
15
  }
16
16
 
17
17
  class EDFStreamWriter(Thread):
18
- def __init__(self, channels, sample_frequency, physical_max, digital_min, file_type, file_path, record_duration=None):
18
+ def __init__(self, channels, sample_frequency, physical_max, physical_min, file_type, file_path, record_duration=None):
19
19
 
20
20
  super().__init__()
21
21
  self._writer : EdfWriter = None
@@ -32,7 +32,7 @@ class EDFStreamWriter(Thread):
32
32
  self._n_channels = len(channels)
33
33
  self.sample_frequency = sample_frequency
34
34
  self.physical_max = physical_max
35
- self.physical_min = digital_min
35
+ self.physical_min = physical_min
36
36
  # 和位数相关,edf 16 bits/bdf 24 bits
37
37
  self.digital_max = 8388607 if file_type == EDF_FILE_TYPE['bdf'] else 32767
38
38
  self.digital_min = -8388608 if file_type == EDF_FILE_TYPE['bdf'] else -32768
@@ -46,6 +46,7 @@ class EDFStreamWriter(Thread):
46
46
  self.equipment = "equipment"
47
47
  self.patient_code = "patient_code"
48
48
  self.patient_name = "patient_name"
49
+ logger.info(f'digital_max:{self.digital_max}, digital_min:{self.digital_min}, physical_max:{self.physical_max}, physical_min:{self.physical_min}')
49
50
 
50
51
  def set_channels(self, channels):
51
52
  self._channels = channels
@@ -61,7 +62,7 @@ class EDFStreamWriter(Thread):
61
62
  self._recording = False
62
63
 
63
64
  def append(self, data):
64
- if data:
65
+ if data is not None:
65
66
  # 数据
66
67
  self.data_queue.put(data)
67
68
 
@@ -127,6 +128,7 @@ class EDFStreamWriter(Thread):
127
128
 
128
129
  # 配置通道参数
129
130
  signal_headers = []
131
+ logger.trace(f"sf: {self.sample_frequency}, pm: {self.physical_max}, pn: {self.physical_min}, dm: {self.digital_max}, dn: {self.digital_min}")
130
132
  for ch in range(self._n_channels):
131
133
  signal_headers.append({
132
134
  "label": f'channels {self._channels[ch]}',
@@ -169,14 +171,16 @@ class EDFStreamWriter(Thread):
169
171
  # 写入1秒的数据
170
172
  def _write_block(self, block):
171
173
  logger.trace(f"写入数据: {block}")
172
- # 转换数据类型为float64
173
- data_float64 = block.astype(np.float64)
174
+ # 转换数据类型为float64-物理信号uV int32-数字信号
175
+ data_input = block.astype(np.int32)
176
+ logger.trace(f"写入数据-real: {data_input}")
174
177
  # 写入时转置为(样本数, 通道数)格式
175
- self._writer.writeSamples(data_float64)
178
+ self._writer.writeSamples(data_input, digital=True)
176
179
  self._duration += 1
177
180
 
178
181
  if self._duration % 10 == 0: # 每10秒打印一次进度
179
182
  logger.info(f"数据记录中... 文件名:{self.file_path}, 已记录时长: {self._duration}秒")
183
+
180
184
 
181
185
  # 用作数据结构一致化处理,通过调用公共类写入edf文件
182
186
  # 入参包含写入edf的全部前置参数
@@ -200,7 +204,7 @@ class RscEDFHandler(object):
200
204
  self.physical_max = physical_max
201
205
  self.physical_min = physical_min
202
206
  self.digital_max = 8388607 if resolution == 24 else 32767
203
- self.digital_min = -8388607 if resolution == 24 else - 32768
207
+ self.digital_min = -8388608 if resolution == 24 else - 32768
204
208
  self.file_type = EDF_FILE_TYPE["bdf"] if resolution == 24 else EDF_FILE_TYPE["edf"]
205
209
  # 点分辨率
206
210
  self.resolution = resolution
@@ -226,8 +230,8 @@ class RscEDFHandler(object):
226
230
  self._end_time = None
227
231
  self._patient_code = "patient_code"
228
232
  self._patient_name = "patient_name"
229
- self._device_type = "24130032"
230
- self._device_no = "24130032"
233
+ self._device_type = "0000"
234
+ self._device_no = "00000000"
231
235
  self._total_packets = 0
232
236
  self._lost_packets = 0
233
237
  self._storage_path = storage_path
@@ -242,7 +246,7 @@ class RscEDFHandler(object):
242
246
  suffix = "bdf" if self.resolution == 24 else "edf"
243
247
 
244
248
  # 文件名称
245
- file_name = f"{self._file_prefix}_{self._device_no}_{self._start_time.strftime('%y%m%d%H%I%M')}.{suffix}" if self._file_prefix else f"{self._device_no}_{self._start_time.strftime('%y%m%d%H%I%M')}.{suffix}"
249
+ file_name = f"{self._file_prefix}_{self._device_no}_{self._start_time.strftime('%y%m%d%H%M%S')}.{suffix}" if self._file_prefix else f"{self._device_no}_{self._start_time.strftime('%y%m%d%H%I%M')}.{suffix}"
246
250
 
247
251
  if self._storage_path:
248
252
  try:
@@ -260,6 +264,10 @@ class RscEDFHandler(object):
260
264
  self._device_type = "C64RS"
261
265
  elif device_type == 0x40:
262
266
  self._device_type = "LJ64S1"
267
+ elif device_type == 0x45:
268
+ self._device_type = "C256RS"
269
+ elif device_type == 0x51:
270
+ self._device_type = "C256RS"
263
271
  elif device_type == 0x60:
264
272
  self._device_type = "ARSKindling"
265
273
  elif device_type == 0x339:
@@ -288,6 +296,8 @@ class RscEDFHandler(object):
288
296
  logger.info(f"收到结束信号,即将停止写入数据:{self.file_name}")
289
297
  self._edf_writer_thread.stop_recording()
290
298
  return
299
+
300
+ logger.debug(f"packet: {packet}")
291
301
 
292
302
  with self._lock:
293
303
  if self.channels is None:
@@ -310,6 +320,7 @@ class RscEDFHandler(object):
310
320
  self._edf_writer_thread.set_start_time(self._start_time)
311
321
  self._edf_writer_thread.start()
312
322
  logger.info(f"开始写入数据: {self.file_name}")
323
+ self._edf_writer_thread.equipment = f'{self._device_type}_{self._device_no}'
313
324
 
314
325
  self._edf_writer_thread.append(packet.eeg)
315
326
 
@@ -329,5 +340,4 @@ class RscEDFHandler(object):
329
340
  else: onset = 0
330
341
  else:
331
342
  onset = cur_time - self._first_timestamp
332
- self._edf_writer_thread.trigger(onset, desc)
333
-
343
+ self._edf_writer_thread.trigger(onset, desc)
@@ -48,8 +48,9 @@ class DeviceCommand(abc.ABC):
48
48
  """构建消息体"""
49
49
  return b''
50
50
  def pack_header(self, body_len: int) -> bytes:
51
- device_id = int(self.device.device_id) if self.device and self.device.device_id else 0
51
+ # device_id = int(self.device.device_id) if self.device and self.device.device_id else 0
52
52
  device_type = int(self.device.device_type) if self.device and self.device.device_type else 0
53
+ device_id = bytes.fromhex(self.device.device_id)[::-1] if self.device.device_id else bytes.fromhex('00000000')
53
54
 
54
55
  #兼容设计
55
56
  b_device_type = None
@@ -61,7 +62,7 @@ class DeviceCommand(abc.ABC):
61
62
  DeviceCommand.HEADER_PREFIX
62
63
  + int(2).to_bytes(1, 'little') # pkgType
63
64
  + device_type.to_bytes(1, 'little')
64
- + device_id.to_bytes(4, 'little')
65
+ + device_id
65
66
  + (DeviceCommand.HEADER_LEN + body_len + 2).to_bytes(4, 'little') # +1 for checksum
66
67
  + self.cmd_code.to_bytes(2, 'little')
67
68
  )
@@ -204,6 +205,15 @@ class StopAcquisitionCommand(DeviceCommand):
204
205
  class SetImpedanceParamCommand(DeviceCommand):
205
206
  cmd_code = 0x411
206
207
  cmd_desc = "设置阻抗测量参数"
208
+ def pack_body(self):
209
+
210
+ return self.device.gen_set_impedance_param()
211
+ def parse_body(self, body):
212
+ result = body[8]
213
+ if result == 0x00:
214
+ logger.info("阻抗测量参数设置成功")
215
+ else:
216
+ logger.warning(f"阻抗测量参数设置失败: {int(result)}")
207
217
 
208
218
  # 启动阻抗测量
209
219
  class StartImpedanceCommand(DeviceCommand):
@@ -211,13 +221,16 @@ class StartImpedanceCommand(DeviceCommand):
211
221
  cmd_desc = "启动阻抗测量"
212
222
  def pack_body(self):
213
223
  body = bytes.fromhex('0000')
214
- body += to_bytes(self.device.acq_channels)
224
+ body += to_bytes(self.device.get_impedance_channels())
215
225
  body += bytes.fromhex('0000000000000000') # 8字节占位符
216
226
  return body
217
227
 
218
228
  def parse_body(self, body):
219
- logger.info(f"Received StartImpedance response: {body.hex()}")
220
- return super().parse_body(body)
229
+ result = body[8]
230
+ if result == 0x00:
231
+ logger.info("阻抗测量启动成功")
232
+ else:
233
+ logger.warning(f"阻抗测量启动失败: {int(result)}")
221
234
 
222
235
 
223
236
  # 停止阻抗测量
@@ -233,7 +246,7 @@ class StartStimulationCommand(DeviceCommand):
233
246
  cmd_code = 0x48C
234
247
  cmd_desc = "启动刺激"
235
248
  def pack_body(self):
236
- return self.device.stim_paradigm.to_bytes()
249
+ return self.device.get_stim_param()
237
250
  # return bytes.fromhex('01000000000000008813000000000000010000000000000000000140420f00640064000000803f0000010000000000000000000000000000000000000000008813000000000000')
238
251
  def parse_body(self, body: bytes):
239
252
  # time - 8B
@@ -243,8 +256,9 @@ class StartStimulationCommand(DeviceCommand):
243
256
  # error_channel - 8B
244
257
  # error_channel= int.from_bytes(body[9:17], 'big')
245
258
  channels = to_channels(body[9:17])
246
- logger.success(f"通道 {channels} 刺激开始")
247
- self.device.trigger(f"通道 {channels} 刺激开始")
259
+ logger.info(f"通道 {channels} 刺激开始")
260
+ if self.device:
261
+ self.device.trigger(f"通道 {channels} 刺激开始")
248
262
  # error_type - 1B
249
263
  error_type = body[17]
250
264
 
@@ -268,8 +282,9 @@ class StopStimulationNotifyCommand(DeviceCommand):
268
282
  # error_channel - 8B
269
283
  # error_channel= int.from_bytes(body[9:17], 'big')
270
284
  channels = to_channels(body[9:17])
271
- logger.success(f"通道 {channels} 刺激结束")
272
- self.device.trigger(f"通道 {channels} 刺激结束", time)
285
+ logger.info(f"通道 {channels} 刺激结束")
286
+ if self.device:
287
+ self.device.trigger(f"通道 {channels} 刺激结束", time)
273
288
  # error_type - 1B
274
289
  error_type = body[17]
275
290
  # 刺激信息
@@ -297,8 +312,7 @@ class ImpedanceDataCommand(DeviceCommand):
297
312
  cmd_desc = "阻抗数据"
298
313
 
299
314
  def parse_body(self, body: bytes):
300
- # logger.info(f"Received impedance data: {body.hex()}")
301
- packet = ImpedancePacket().transfer(body)
315
+ self.device.produce(body, type="impedance")
302
316
 
303
317
  # 信号数据
304
318
  class SignalDataCommand(DeviceCommand):
@@ -309,11 +323,11 @@ class SignalDataCommand(DeviceCommand):
309
323
  return super().unpack(payload)
310
324
 
311
325
  def parse_body(self, body: bytes):
312
- # 解析数据包
313
- packet = RscPacket()
314
- packet.transfer(body)
326
+ # # 解析数据包
327
+ # packet = RscPacket()
328
+ # packet.transfer(body)
315
329
  # 将数据包传递给设备
316
- self.device.produce(packet)
330
+ self.device.produce(body)
317
331
 
318
332
 
319
333
 
@@ -4,4 +4,5 @@ from .device_factory import DeviceFactory
4
4
  # import devices
5
5
  from .c64_rs import C64RS
6
6
  from .c16_rs import C16RS
7
- from .arskindling import ARSKindling
7
+ from .arskindling import ARSKindling
8
+ from .c256_rs import C256RS