Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

first version of 8 bit/string trigger #263

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion setup.py
Expand Up @@ -32,7 +32,7 @@ def read(*names, **kwargs):
return fh.read()


my_req = ['numpy', 'scipy', 'pyedflib', 'click==7.1.2', 'appdirs==1.4.3', 'sentry_sdk==1.0.0', 'mne', 'eeglabio', 'pandas'] # noqa: E501
my_req = ['numpy', 'scipy', 'pyedflib', 'click==7.1.2', 'appdirs==1.4.3', 'sentry_sdk==1.0.0', 'mne', 'eeglabio', 'pandas', 'pyserial'] # noqa: E501
test_requirements = ["pytest==6.2.5",
"pytest-mock==3.10.0",
"pytest-html==3.2.0",
Expand Down
10 changes: 10 additions & 0 deletions src/explorepy/explore.py
Expand Up @@ -426,6 +426,16 @@ def set_external_marker(self, time_lsl, marker_string):
self._check_connection()
self.stream_processor.set_ext_marker(time_lsl, marker_string)

def set_virtual_8bit_marker(self, marker_string):
"""Sets a vierual 8 bit marker while streaming

Args:
time_lsl (timestamp): timestamp from external marker)
marker_string (string): string to save as experiment marker)
"""
self._check_connection()
self.stream_processor.set_string_marker(marker_string)

def format_memory(self):
"""Format memory of the device

Expand Down
10 changes: 9 additions & 1 deletion src/explorepy/stream_processor.py
Expand Up @@ -32,7 +32,7 @@
from explorepy.tools import (
ImpedanceMeasurement,
PhysicalOrientation,
get_local_time
get_local_time, send_ttl_trigger
)


Expand Down Expand Up @@ -298,6 +298,14 @@ def set_ext_marker(self, time_lsl, marker_string):
marker = ExternalMarker.create(time_lsl, marker_string)
self.process(marker)

def set_string_marker(self, marker_string):
"""Set an external marker in the stream"""
logger.info(f"Setting an 8 bit marker id with code: {marker_string}")

send_ttl_trigger()
marker = ExternalMarker.create(self._get_sw_marker_time(), marker_string)
self.process(marker)

def compare_device_info(self, new_device_info):
"""Compare a device info dict with the current version

Expand Down
50 changes: 46 additions & 4 deletions src/explorepy/tools.py
Expand Up @@ -6,6 +6,10 @@
import datetime
import logging
import os.path
import time

import pandas as pd
import serial # pyserial is necessary
import socket
from collections import namedtuple
from contextlib import closing
Expand All @@ -28,13 +32,14 @@
local_clock
)
from scipy import signal

from serial.tools import (
list_ports
)
import explorepy
from explorepy.filters import ExGFilter
from explorepy.packet import EEG
from explorepy.settings_manager import SettingsManager


logger = logging.getLogger(__name__)
lock = Lock()

Expand Down Expand Up @@ -478,6 +483,9 @@ def stop(self):
data = pandas.read_csv(path, delimiter=",")
data = data.sort_values(by=['TimeStamp'])
pandas.DataFrame(data).to_csv(path, index=False)
elif "Marker" in self._file_name:
# Merge eight bit marker information
merge_string_trigger_info_with_ttl(self._file_name)

def _init_edf_channels(self):
self._file_obj.setEquipment(self._device_name)
Expand Down Expand Up @@ -535,7 +543,6 @@ def write_data(self, packet):
elif self.file_type == 'csv':
if isinstance(packet, EEG) and self._n_chan > 8:
indices = [0] + [i + 1 for i, flag in enumerate(reversed(self.adc_mask)) if flag == 1]
print(f'indices {indices}')
data = data[indices]
self._csv_obj.writerows(data.T.tolist())
self._file_obj.flush()
Expand Down Expand Up @@ -928,7 +935,7 @@ def compare_recover_from_bin(file_name_csv, file_name_device):
Args:
file_name_csv (str): Name of recorded csv file without extension
file_name_device_csv (str): Name of converted csv file
"""
"""
bin_df = pandas.read_csv(file_name_device + '_ExG.csv')
csv_df = pandas.read_csv(file_name_csv + '_ExG.csv')
meta_df = pandas.read_csv(file_name_csv + "_Meta.csv")
Expand All @@ -943,3 +950,38 @@ def compare_recover_from_bin(file_name_csv, file_name_device):
bin_df = bin_df[(bin_df[timestamp_key] >= start) & (bin_df[timestamp_key] <= stop)]
bin_df[timestamp_key] = bin_df[timestamp_key] + offset_
bin_df.to_csv(file_name_csv + '_recovered_ExG.csv', index=False)


def send_ttl_trigger():
""" Sends a trigger through Mentalab Triggerstick
"""

# There are several ways to find the right USB device: pid, vid, manufacturer etc. Here the code looks for Mentalab as manufacturer
port = [p for p in serial.tools.list_ports.comports(False) if 'Mentalab' in p.manufacturer][0].device
print(f'port is {port}')
if port is None:
print('Triggerstick not found!')
raise LookupError('Could not find triggerstick!')


mySerial = serial.Serial(port=port, baudrate=9600, timeout=1)
mySerial.write(b'TRG\n')

def merge_string_trigger_info_with_ttl(file_name):
"""
Here the code looks for same close timetamps and then merge them together as 8 bit markers with prefix 'string_'
"""
drop_indexes = []

df = pd.read_csv(file_name)
marker_info_list = df['Code']

for index, item in enumerate(marker_info_list):
if 'in_' in str(item) and (int(df['TimeStamp'][index + 1]) - int(df['TimeStamp'][index]) < 1) and 'ext_' in marker_info_list[index + 1] and (index <= len(marker_info_list) -1):
# merge two rows
marker_info_list[index] = 'in_' + marker_info_list[index + 1][4:]
drop_indexes.append(index + 1)
if len(drop_indexes) > 0:
df['Code'] = marker_info_list
df.drop(index=drop_indexes, inplace=True, axis= 1)
pandas.DataFrame(df).to_csv(os.path.join(os.getcwd(), file_name), index=False)