Skip to content

Commit 74c6d72

Browse files
authored
Merge pull request #422 from Mentalab-hub/APIS-1349-live-impedance-measurement
Apis 1349 live impedance measurement
2 parents 878a9ae + 9d57833 commit 74c6d72

3 files changed

Lines changed: 38 additions & 10 deletions

File tree

src/explorepy/explore.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -182,13 +182,15 @@ def record_data(
182182
if file_type not in ['edf', 'csv']:
183183
raise ValueError(
184184
'{} is not a supported file extension!'.format(file_type))
185+
185186
if imp_mode:
187+
if not self.stream_processor.is_imp_running():
188+
raise ValueError('Impedance measurement not running!')
186189
if file_type == 'edf':
187190
raise ValueError(
188191
'{} is not a supported file extension for recording impedance!'.format(file_type))
189-
if notch_freq is None:
190-
raise ValueError(
191-
'Missing notch frequency argument, please provide the notch frequency to get live impedance values')
192+
193+
notch_freq = self.stream_processor.get_power_line_freq() or 50
192194

193195
duration = self._check_duration(duration)
194196

@@ -260,7 +262,6 @@ def handle_impedance_packet(packet):
260262
impedance_values = packet.get_impedances()
261263

262264
real_values = np.array(impedance_values) / 2
263-
print("Impedance:", real_values.tolist())
264265

265266
if file_type == 'csv':
266267
row_data = [float(packet.timestamp), *real_values]
@@ -271,7 +272,6 @@ def handle_impedance_packet(packet):
271272

272273
self.stream_processor.subscribe(callback=handle_exg_impedance_packet, topic=TOPICS.raw_ExG)
273274
self.stream_processor.subscribe(callback=handle_impedance_packet, topic=TOPICS.imp)
274-
self.stream_processor.imp_initialize(notch_freq=notch_freq)
275275
logger.info("Recording with impedance mode...")
276276
else:
277277
self.stream_processor.subscribe(callback=self.recorders['exg'].write_data, topic=TOPICS.raw_ExG)
@@ -301,8 +301,6 @@ def stop_recording(self):
301301

302302
if is_impedance_mode:
303303
try:
304-
self.stream_processor.disable_imp()
305-
306304
if 'handle_exg_impedance_callback' in self.recorders:
307305
self.stream_processor.unsubscribe(
308306
callback=self.recorders['handle_exg_impedance_callback'], topic=TOPICS.raw_ExG)

src/explorepy/filters.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ def __init__(self, cutoff_freq, filter_type, s_rate, n_chan, order=5):
3131
self.s_rate = float(s_rate)
3232
self.filter_type = filter_type
3333
self.filter_param = None
34+
self.cutoff_freq = cutoff_freq
3435
order = 2 if self.s_rate > 1000 else order
3536
a, b, zi = self.get_filter_coeffs(cutoff_freq, filter_type, s_rate, n_chan, order)
3637
self.filter_param = {'a': a, 'b': b, 'zi': zi}
@@ -110,6 +111,9 @@ def get_notch_coeffs(cutoff, nyquist, n_channels, order, quality=30, imp_mode=Fa
110111
zi = np.zeros(shape=(n_channels, 2))
111112
return a, b, zi
112113

114+
def get_cutoff_freq(self):
115+
return self.cutoff_freq
116+
113117
def apply(self, input_data, in_place=True):
114118
"""Apply filter
115119

src/explorepy/stream_processor.py

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ def __init__(self, debug=False):
7878
self.reset_timer()
7979
self.packet_count = 0
8080
self.progress = 0
81+
self._notch_filter = None
8182

8283
def subscribe(self, callback, topic):
8384
"""Subscribe a function to a topic
@@ -312,13 +313,17 @@ def process(self, packet):
312313
self.last_exg_packet_timestamp = get_local_time()
313314
missing_timestamps = self.fill_missing_packet(packet)
314315
self._update_last_time_point(packet, received_time)
315-
self.dispatch(topic=TOPICS.raw_ExG, packet=packet)
316316
self.packet_count += 1
317-
if self._is_imp_mode and self.imp_calculator:
317+
if self.is_imp_running():
318318
packet_imp = self.imp_calculator.measure_imp(
319319
packet=copy.deepcopy(packet))
320320
if packet_imp is not None:
321321
self.dispatch(topic=TOPICS.imp, packet=packet_imp)
322+
if self._notch_filter:
323+
self._notch_filter.apply(packet)
324+
self.dispatch(topic=TOPICS.raw_ExG, packet=packet)
325+
else:
326+
self.dispatch(topic=TOPICS.raw_ExG, packet=packet)
322327
try:
323328
self.apply_filters(packet=packet)
324329
except ValueError as error:
@@ -454,9 +459,10 @@ def imp_initialize(self, notch_freq, calibration=False):
454459
cmd = ZMeasurementEnable()
455460
if self.configure_device(cmd):
456461
self.imp_calib_info['calibration'] = calibration
462+
self._add_notch_filter()
457463
self.imp_calculator = ImpedanceMeasurement(device_info=self.device_info,
458464
calib_param=self.imp_calib_info,
459-
notch_freq=notch_freq)
465+
notch_freq=self.get_power_line_freq() or notch_freq)
460466
self._is_imp_mode = True
461467
else:
462468
raise ConnectionError('Device configuration process failed!')
@@ -470,6 +476,7 @@ def disable_imp(self):
470476
return True
471477
print("WARNING: Couldn't disable impedance measurement mode. "
472478
"Please restart your device manually.")
479+
self._notch_filter = None
473480
return False
474481

475482
def set_marker(self, marker_string, time_lsl=None, name='mkr', soft_marker=True):
@@ -583,3 +590,22 @@ def fill_missing_packet(self, packet):
583590
timestamps = np.linspace(self._last_packet_timestamp + sps,
584591
packet.timestamp, num=missing_samples, endpoint=True)
585592
return timestamps[:-1]
593+
594+
def _add_notch_filter(self):
595+
self._notch_filter = ExGFilter(
596+
cutoff_freq=62.5,
597+
filter_type='notch_imp',
598+
s_rate=250,
599+
n_chan=SettingsManager(self.device_info['device_name']).get_channel_count()
600+
)
601+
602+
def is_imp_running(self):
603+
return self._is_imp_mode and self.imp_calculator
604+
605+
def get_power_line_freq(self):
606+
match = next(
607+
(item for item in self.filters if item.filter_type == 'notch'),
608+
None
609+
)
610+
611+
return match.cutoff_freq if match else None

0 commit comments

Comments
 (0)