├── EMG_Controlled_Music └── LSL_Stream_Music.py ├── EMG_Controlled_Piano └── LSL_EMG_Piano.py ├── EMG_Controlled_Slideshow └── LSL_Stream_Slides.py ├── EMG_Controlled_Tetris └── tetris.py ├── EMG_Scrolling └── LSL_Stream_Scroll.py ├── External_Trigger ├── Breadboard_Setup.jpeg ├── Circuit_Diagram.png ├── ExternalTriggerCreator_quick.py ├── Full_Breadboard_Setup.jpeg ├── Images │ ├── Image_Class │ │ ├── Kitten │ │ │ ├── Cat_1.jpg │ │ │ ├── Cat_10.jpg │ │ │ ├── Cat_11.jpg │ │ │ ├── Cat_12.jpg │ │ │ ├── Cat_13.jpg │ │ │ ├── Cat_14.jpg │ │ │ ├── Cat_2.jpg │ │ │ ├── Cat_3.jpg │ │ │ ├── Cat_4.jpg │ │ │ ├── Cat_5.jpg │ │ │ └── Cat_9.jpg │ │ └── Puppy │ │ │ ├── Dog_11.jpg │ │ │ ├── Dog_12.jpg │ │ │ ├── Dog_13.jpg │ │ │ ├── Dog_14.jpg │ │ │ ├── Dog_19.jpg │ │ │ ├── Dog_2.jpg │ │ │ ├── Dog_3.jpg │ │ │ ├── Dog_4.jpg │ │ │ ├── Dog_5.jpg │ │ │ ├── Dog_6.jpg │ │ │ └── Dog_7.jpg │ └── Welcome │ │ ├── 1.PNG │ │ ├── 2.PNG │ │ ├── session1.PNG │ │ ├── session2.PNG │ │ ├── session3.PNG │ │ └── welcome2OpenBCI.jpg ├── OpenBCI_Experiment_Toolkits.ipynb ├── README.md ├── connect.jpeg ├── labels.txt ├── settings.json ├── test.jpg ├── video.mp4 └── video_picture.png ├── Facial_EMG ├── Arduino_Code │ └── Arduino_Code.ino └── LSL_Stream_Facial_One_LED.py ├── Facial_EMG_Multiple_LEDs ├── Arduino_Code │ └── Arduino_Code.ino └── LSL_Stream_Facial_Multiple_LEDs.py ├── LICENSE ├── Motor_Imagery ├── mental_imagery.ino └── neuropype_recieve.py └── README.md /EMG_Controlled_Music/LSL_Stream_Music.py: -------------------------------------------------------------------------------- 1 | """Code modified from the example program to show how to read a multi-channel time series from LSL at https://github.com/OpenBCI/OpenBCI_GUI/blob/master/Networking-Test-Kit/LSL/lslStreamTest.py.""" 2 | 3 | from pylsl import StreamInlet, resolve_byprop 4 | import pyautogui 5 | import time 6 | 7 | # resolve an EMG stream on the lab network and notify the user 8 | print("Looking for an EMG stream...") 9 | streams = resolve_byprop('type', 'EMG') 10 | inlet = StreamInlet(streams[0]) 11 | print("EMG stream found!") 12 | 13 | # initialize thresholds and variables for storing time 14 | time_thres = 2000 15 | prev_time = 0 16 | flex_thres = 1.0 17 | 18 | while True: 19 | 20 | sample, timestamp = inlet.pull_sample() # get EMG data sample and its timestamp 21 | 22 | curr_time = int(round(time.time() * 1000)) # get current time in milliseconds 23 | 24 | if ((sample[0] >= flex_thres) & (curr_time - time_thres > prev_time)): # if an EMG peak is detected and enough time has gone by since the last one, press space 25 | prev_time = curr_time # update time 26 | pyautogui.press('space') 27 | 28 | -------------------------------------------------------------------------------- /EMG_Controlled_Piano/LSL_EMG_Piano.py: -------------------------------------------------------------------------------- 1 | """Code modified from the example program to show how to read a multi-channel time series from LSL at https://github.com/OpenBCI/OpenBCI_GUI/blob/master/Networking-Test-Kit/LSL/lslStreamTest.py.""" 2 | 3 | from pylsl import StreamInlet, resolve_byprop 4 | import pyautogui 5 | import time 6 | 7 | # resolve an EMG stream on the lab network and notify the user 8 | print("Looking for an EMG stream...") 9 | streams = resolve_byprop('type', 'EMG') 10 | inlet = StreamInlet(streams[0]) 11 | print("EMG stream found!") 12 | 13 | # initialize thresholds and variables for storing time 14 | time_thres = 1000 15 | prev_time = 0 16 | pinky_thres = .7 17 | pointer_thres = .6 18 | 19 | while True: 20 | 21 | sample, timestamp = inlet.pull_sample() # get EMG data sample and its timestamp 22 | 23 | curr_time = int(round(time.time() * 1000)) # get current time in milliseconds 24 | 25 | if ((sample[0] >= pinky_thres) & (curr_time - time_thres > prev_time)): # if an EMG peak from channel 1 is detected and enough time has gone by since the last one, press key 26 | prev_time = curr_time # update time 27 | pyautogui.press('x') 28 | 29 | elif ((sample[1] >= pointer_thres) & (curr_time - time_thres > prev_time)): # if an EMG peak from channel 2 is detected from and enough time has gone by since the last one, press key 30 | prev_time = curr_time # update time 31 | pyautogui.press('p') 32 | 33 | elif ((sample[2] >= pointer_thres) & (curr_time - time_thres > prev_time)): # if an EMG peak from channel 3 is detected and enough time has gone by since the last one, press key 34 | prev_time = curr_time # update time 35 | pyautogui.press('o') 36 | 37 | elif ((sample[3] >= pinky_thres) & (curr_time - time_thres > prev_time)): # if an EMG peak from channel 4 is detected and enough time has gone by since the last one, press key 38 | prev_time = curr_time # update time 39 | pyautogui.press('i') 40 | -------------------------------------------------------------------------------- /EMG_Controlled_Slideshow/LSL_Stream_Slides.py: -------------------------------------------------------------------------------- 1 | """Code modified from the example program to show how to read a multi-channel time series from LSL at https://github.com/OpenBCI/OpenBCI_GUI/blob/master/Networking-Test-Kit/LSL/lslStreamTest.py.""" 2 | 3 | from pylsl import StreamInlet, resolve_byprop 4 | import pyautogui 5 | import time 6 | 7 | # resolve an EMG stream on the lab network and notify the user 8 | print("Looking for an EMG stream...") 9 | streams = resolve_byprop('type', 'EMG') 10 | inlet = StreamInlet(streams[0]) 11 | print("EMG stream found!") 12 | 13 | # initialize thresholds and variables for storing time 14 | time_thres = 2000 15 | prev_time = 0 16 | blink_thres = 0.95 17 | 18 | while True: 19 | 20 | sample, timestamp = inlet.pull_sample() # get EMG data sample and its timestamp 21 | 22 | curr_time = int(round(time.time() * 1000)) # get current time in milliseconds 23 | 24 | if ((sample[0] >= blink_thres) & (curr_time - time_thres > prev_time)): # if a blink is detected and enough time has gone by since the last blinking, press space 25 | prev_time = int(round(time.time() * 1000)) # update time 26 | pyautogui.press('space') 27 | 28 | -------------------------------------------------------------------------------- /EMG_Controlled_Tetris/tetris.py: -------------------------------------------------------------------------------- 1 | import socket 2 | import sys 3 | import time 4 | import argparse 5 | import signal 6 | import json 7 | import pyautogui 8 | 9 | """Code modified from the example program to show how to read a multi-channel time series from UDP at https://github.com/OpenBCI/OpenBCI_GUI/blob/master/Networking-Test-Kit/UDP/udp_receive.py.""" 10 | 11 | """ These variables can be changed if needed for changed controls on different Tetris websites. Refer to pyautogui documentation for 12 | more information on what keywords map to specific keys. https://pyautogui.readthedocs.io/en/latest/keyboard.html#keyboard-keys """ 13 | 14 | MOVE_PIECE_LEFT = "left" 15 | MOVE_PIECE_RIGHT = "right" 16 | DROP_PIECE = "space" 17 | ROTATE_PIECE = "up" 18 | 19 | 20 | # Clean exit from print mode 21 | def exit_print(signal, frame): 22 | print("Closing listener") 23 | sys.exit(0) 24 | 25 | 26 | if __name__ == "__main__": 27 | # Collect command line arguments 28 | parser = argparse.ArgumentParser() 29 | parser.add_argument("--ip", 30 | default="127.0.0.1", help="The ip to listen on") 31 | parser.add_argument("--port", 32 | type=int, default=12345, help="The port to listen on") 33 | parser.add_argument("--address", default="/openbci", help="address to listen to") 34 | parser.add_argument("--option", default="print", help="Debugger option") 35 | parser.add_argument("--len", default=8, help="Debugger option") 36 | args = parser.parse_args() 37 | 38 | # Set up necessary parameters from command line 39 | length = args.len 40 | if args.option == "print": 41 | signal.signal(signal.SIGINT, exit_print) 42 | 43 | # Connect to socket 44 | sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) 45 | sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 46 | server_address = (args.ip, args.port) 47 | sock.bind(server_address) 48 | 49 | # Display socket attributes 50 | print('--------------------') 51 | print("-- UDP LISTENER -- ") 52 | print('--------------------') 53 | print("IP:", args.ip) 54 | print("PORT:", args.port) 55 | print('--------------------') 56 | 57 | # Receive messages 58 | print("Calibration period, remain neutral...") 59 | start = time.time() 60 | numSamples = 0 61 | duration = 10 62 | rotated = False 63 | space_pressed = False 64 | left_once = False 65 | right_once = False 66 | x_prev = 0 67 | z_prev = 0 68 | 69 | x_start_sum = 0 70 | x_start_samples = 0 71 | for y in range(150): 72 | data, addr = sock.recvfrom(20000) # buffer size is 20000 bytes 73 | obj = json.loads(data.decode()) 74 | if obj.get('type') == 'accelerometer': 75 | aux_data = obj.get('data') 76 | x_start_sum += aux_data[0] 77 | x_start_samples += 1 78 | 79 | print("Calibration done. You may now begin Tetris!") 80 | 81 | x_start = x_start_sum / x_start_samples 82 | 83 | while True: 84 | data, addr = sock.recvfrom(20000) # buffer size is 20000 bytes 85 | if args.option == "print": 86 | obj = json.loads(data.decode()) 87 | if obj.get('type') == 'accelerometer': 88 | aux_data = obj.get('data') 89 | x = aux_data[0] 90 | z = aux_data[2] 91 | if z > 0.5 and z_prev < z and not space_pressed: # drop piece 92 | pyautogui.press('space') 93 | space_pressed = True 94 | else: 95 | if 0.075 + x_start < x < 0.2 + x_start and not left_once: # short left 96 | pyautogui.press('left') 97 | left_once = True 98 | space_pressed = False 99 | elif -0.075 + x_start > x > -0.2 + x_start and not right_once: # short right 100 | pyautogui.press('right') 101 | right_once = True 102 | space_pressed = False 103 | elif x > 0.2 + x_start and x_prev < x: # move left 104 | pyautogui.press('left') 105 | left_once = False 106 | space_pressed = False 107 | elif x < -0.2 + x_start and x_prev > x: # move right 108 | pyautogui.press('right') 109 | right_once = False 110 | space_pressed = False 111 | elif -0.075 + x_start < x < 0.075 + x_start: # head is neutral 112 | left_once = False 113 | right_once = False 114 | space_pressed = False 115 | elif z < 0.5: 116 | space_pressed = False 117 | if z > 0.5: 118 | space_pressed = True 119 | x_prev = x 120 | z_prev = z 121 | else: 122 | emg_data = obj.get('data') 123 | fp1 = emg_data[0] 124 | fp2 = emg_data[1] 125 | to_continue = 0 126 | for i in range(2, 8): 127 | if emg_data[i] > 0.8: 128 | to_continue += 1 129 | if (to_continue < 4): 130 | if fp2 < 0.9: 131 | rotated = False 132 | elif (fp2 > 0.9) and not rotated: 133 | pyautogui.press('up') 134 | rotated = True 135 | numSamples += 1 136 | -------------------------------------------------------------------------------- /EMG_Scrolling/LSL_Stream_Scroll.py: -------------------------------------------------------------------------------- 1 | """Code modified from the example program to show how to read a multi-channel time series from LSL at https://github.com/OpenBCI/OpenBCI_GUI/blob/master/Networking-Test-Kit/LSL/lslStreamTest.py.""" 2 | 3 | from pylsl import StreamInlet, resolve_byprop 4 | import pyautogui 5 | import time 6 | 7 | # resolve an EMG stream on the lab network and notify the user 8 | print("Looking for an EMG stream...") 9 | streams = resolve_byprop('type', 'EMG') 10 | inlet = StreamInlet(streams[0]) 11 | print("EMG stream found!") 12 | 13 | # initialize thresholds and variables for storing time 14 | prev_time = 0 15 | flex_thres = 1.0 16 | 17 | while True: 18 | 19 | sample, timestamp = inlet.pull_sample() # get EMG data sample and its timestamp 20 | 21 | curr_time = int(round(time.time() * 1000)) # get current time in milliseconds 22 | 23 | 24 | if (((sample[1] >= flex_thres) or (sample[0] >= flex_thres))): # if an EMG peak is detected from any of the arms 25 | 26 | prev_time = int(round(time.time() * 1000)) # update time 27 | 28 | if(sample[1] > sample[0]): # scroll up or down depending on which peak is larger 29 | pyautogui.scroll(50) 30 | else: 31 | pyautogui.scroll(-50) 32 | 33 | 34 | -------------------------------------------------------------------------------- /External_Trigger/Breadboard_Setup.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenBCI/OpenBCI_Tutorials/a9d60c75e8606a8a412a12bb0aa7c54b154a10d8/External_Trigger/Breadboard_Setup.jpeg -------------------------------------------------------------------------------- /External_Trigger/Circuit_Diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenBCI/OpenBCI_Tutorials/a9d60c75e8606a8a412a12bb0aa7c54b154a10d8/External_Trigger/Circuit_Diagram.png -------------------------------------------------------------------------------- /External_Trigger/ExternalTriggerCreator_quick.py: -------------------------------------------------------------------------------- 1 | # OpenBCI Experiment: ExternalTriggerCreator 2 | # A python script to customize video components and external trigger for EEG experiments 3 | 4 | # Date: 06/09/2020 5 | # Author: Fan Li 6 | 7 | import cv2 8 | import glob 9 | import argparse 10 | import json 11 | import random 12 | import copy 13 | import os 14 | import numpy as np 15 | 16 | random.seed(30) 17 | 18 | 19 | def resize_image(old_size, new_size): 20 | ratio_y = new_size[0] / old_size[0] 21 | ratio_x = new_size[1] / old_size[1] 22 | 23 | if ratio_y > ratio_x: 24 | y = old_size[0] * ratio_x 25 | x = new_size[1] 26 | else: 27 | y = new_size[0] 28 | x = old_size[1] * ratio_y 29 | 30 | size = (int(y), int(x), new_size[2]) 31 | return size 32 | 33 | 34 | def embed_trigger(img, background_size, trigger_position, trigger_color): 35 | # background 36 | background = np.zeros(background_size, dtype="uint8") 37 | 38 | background[:] = (0, 0, 0) 39 | 40 | background[ 41 | int(background_size[0] / 2) - int(img.shape[0] / 2):int(background_size[0] / 2) - int(img.shape[0] / 2) + img.shape[ 42 | 0], int(background_size[1] / 2) - int(img.shape[1] / 2): int(background_size[1] / 2) - int(img.shape[1] / 2) + 43 | img.shape[1]] = img 44 | 45 | # trigger 46 | background[trigger_position[1]:trigger_position[3], trigger_position[0]:trigger_position[2]] = (trigger_color) 47 | return background 48 | 49 | 50 | ### 51 | def create_session(kitten_image_path_list, puppy_image_path_list, frame_numbers, fps, trigger_position): 52 | frames_array = [] 53 | label_array = [] 54 | label_index = [] 55 | filename_array = [] 56 | 57 | 58 | 59 | # kitten 60 | for filename in kitten_image_path_list: 61 | 62 | 63 | # add current image 64 | img = cv2.imread(filename) 65 | frames, label = create_frames(img, frame_numbers, "Kitten", fps, trigger_position) 66 | frames_array.append(frames) 67 | 68 | label_array.append(label) 69 | label_index.append(1) 70 | filename_array.append(filename) 71 | 72 | # puppy 73 | for filename in puppy_image_path_list: 74 | img = cv2.imread(filename) 75 | frames, label = create_frames(img, frame_numbers, "Puppy", fps, trigger_position) 76 | frames_array.append(frames) 77 | label_array.append(label) 78 | label_index.append(2) 79 | filename_array.append(filename) 80 | 81 | # pack 82 | z = list(zip(frames_array, label_array, label_index, filename_array)) 83 | random.shuffle(z) 84 | new_frame_array, new_label_array, new_label_index_array, new_filename_array = zip(*z) 85 | 86 | new_frame_array = list(new_frame_array) 87 | new_label_array = list(new_label_array) 88 | new_label_index_array = list(new_label_index_array) 89 | new_filename_array = list(new_filename_array) 90 | # add test 91 | test_frame_numbers = fps * 1 92 | frames, label = create_frames(img, frame_numbers, "Test", fps, trigger_position) 93 | print(new_frame_array[:3]) 94 | new_frame_array.append(frames) 95 | new_label_array.append(label) 96 | new_label_index_array.append(3) 97 | new_filename_array.append(filename) 98 | 99 | return new_frame_array, new_label_array, new_label_index_array, new_filename_array 100 | 101 | 102 | def create_video(image_base_path, fps, flick_times, screen_size, time_range_per_image, video_output, label_output, 103 | trigger_position): 104 | screen_size = tuple(screen_size) 105 | img_array = [] 106 | 107 | kitten_image_path_list = glob.glob(image_base_path + 'Image_Class/' + 'Kitten' + '/*.jpg') 108 | puppy_image_path_list = glob.glob(image_base_path + 'Image_Class/' + 'Puppy' + '/*.jpg') 109 | 110 | # session 1 1 s 111 | frame_numbers = int(fps * 1) 112 | # puppy_image_path = puppy_image_path_list[1] 113 | frame_array_session_1, label_array_session_1, label_index_array_session_1, filename_array_session_1 = create_session( 114 | kitten_image_path_list, puppy_image_path_list, frame_numbers, fps, trigger_position) 115 | 116 | # session 2 0.75 s 117 | frame_numbers = int(fps * 0.75) 118 | # puppy_image_path = puppy_image_path_list[2] 119 | frame_array_session_2, label_array_session_2, label_index_array_session_2, filename_array_session_2 = create_session( 120 | kitten_image_path_list, puppy_image_path_list, frame_numbers, fps, trigger_position) 121 | 122 | # session 3 0.5 s 123 | frame_numbers = int(fps * 0.5) 124 | # puppy_image_path = puppy_image_path_list[3] 125 | frame_array_session_3, label_array_session_3, label_index_array_session_3, filename_array_session_3 = create_session( 126 | kitten_image_path_list, puppy_image_path_list, frame_numbers, fps, trigger_position) 127 | 128 | # session 4 0.25 s 129 | frame_numbers = int(fps * 0.25) 130 | # puppy_image_path = puppy_image_path_list[4] 131 | frame_array_session_4, label_array_session_4, label_index_array_session_4, filename_array_session_4 = create_session( 132 | kitten_image_path_list, puppy_image_path_list, frame_numbers, fps, trigger_position) 133 | 134 | new_frame_array = frame_array_session_1 + frame_array_session_2 + frame_array_session_3 + frame_array_session_4 135 | new_label_array = label_array_session_1 + label_array_session_2 + label_array_session_3 + label_array_session_4 136 | new_label_index_array = label_index_array_session_1 + label_index_array_session_2 + label_index_array_session_3 + label_index_array_session_4 137 | new_filename_array = filename_array_session_1 + filename_array_session_2 + filename_array_session_3 + filename_array_session_4 138 | 139 | for frames in new_frame_array: 140 | for image in frames: 141 | img_array.append(image) 142 | # print("output shape: ", image[0].shape) 143 | 144 | with open(label_output, 'w') as handle: 145 | for i in range(len(new_label_array)): 146 | handle.write("%s," % new_label_index_array[i]) 147 | handle.write("%s," % new_label_array[i]) 148 | local_file_name = new_filename_array[i].split("\\")[-1] 149 | handle.write("%s," % local_file_name) 150 | handle.write("\n") 151 | 152 | # Welcome frames 153 | welcome_array = [] 154 | 155 | img = cv2.imread(image_base_path + 'Welcome/welcome2OpenBCI.jpg') 156 | 157 | ###### 158 | new_size = (1080, 1350, 3) 159 | background_size = (1080, 1920, 3) 160 | old_size = img.shape 161 | size = resize_image(old_size, new_size) 162 | 163 | img_new = cv2.resize(img, (size[1], size[0])) 164 | 165 | img_white = embed_trigger(img_new, background_size, trigger_position, (255, 255, 255)) 166 | img_black = embed_trigger(img_new, background_size, trigger_position, (0, 0, 0)) 167 | 168 | for i in range(3 * fps): 169 | welcome_array.append(img_black) 170 | 171 | img_1 = cv2.imread(image_base_path + 'Welcome/1.PNG') 172 | old_size = img_1.shape 173 | size = resize_image(old_size, new_size) 174 | img_new_1 = cv2.resize(img_1, (size[1], size[0])) 175 | img_1_black = embed_trigger(img_new_1, background_size, trigger_position, (0, 0, 0)) 176 | for i in range(3 * fps): 177 | welcome_array.append(img_1_black) 178 | 179 | img_2 = cv2.imread(image_base_path + 'Welcome/2.PNG') 180 | old_size = img_2.shape 181 | size = resize_image(old_size, new_size) 182 | img_new_2 = cv2.resize(img_2, (size[1], size[0])) 183 | img_2_black = embed_trigger(img_new_2, background_size, trigger_position, (0, 0, 0)) 184 | for i in range(3 * fps): 185 | welcome_array.append(img_2_black) 186 | 187 | img_2 = cv2.imread(image_base_path + 'Welcome/2.PNG') 188 | 189 | for j in range(flick_times): 190 | for i in range(int(0.05 * fps)): 191 | welcome_array.append(img_black) 192 | for i in range(int(0.05 * fps)): 193 | welcome_array.append(img_white) 194 | 195 | # ending frames 196 | ending_array = [] 197 | for j in range(flick_times): 198 | for i in range(int(0.05 * fps)): 199 | ending_array.append(img_black) 200 | for i in range(int(0.05 * fps)): 201 | ending_array.append(img_white) 202 | 203 | img_array = welcome_array + img_array + ending_array 204 | print(len(welcome_array), len(img_array)) 205 | 206 | out = cv2.VideoWriter(video_output, cv2.VideoWriter_fourcc(*'FMP4'), fps, screen_size) 207 | for i in range(len(img_array)): 208 | out.write(img_array[i]) 209 | out.release() 210 | 211 | 212 | def create_frames(img, frame_num, label, fps, trigger_position): 213 | new_size = (1080, 1350, 3) 214 | background_size = (1080, 1920, 3) 215 | old_size = img.shape 216 | adjusted_size = resize_image(old_size, new_size) 217 | 218 | img_new = cv2.resize(img, (adjusted_size[1], adjusted_size[0])) 219 | 220 | print("Output Shape: ", img_new.shape) 221 | 222 | img_white = embed_trigger(img_new, background_size, trigger_position, (255, 255, 255)) 223 | img_black = embed_trigger(img_new, background_size, trigger_position, (0, 0, 0)) 224 | cv2.imwrite("test.jpg", img_white) 225 | 226 | # generate fixation across 227 | cross = np.zeros((1080, 1920, 3), np.uint8) 228 | cv2.line(cross, (950, 540), (970, 540), (0, 0, 255), 2) 229 | cv2.line(cross, (960, 530), (960, 550), (0, 0, 255), 2) 230 | 231 | # embed 232 | 233 | frame_array = [] 234 | # random interval 235 | random_interval = random.randint(-2, 2) / 10 236 | # add cross before current image 237 | frame_array += [cross] * int((0.5 + random_interval) * fps) 238 | 239 | # add current image 240 | for i in range(int(0.05 * fps)): 241 | frame_array.append(img_white) 242 | for i in range(frame_num): 243 | frame_array.append(img_black) 244 | for i in range(int(0.05 * fps)): 245 | frame_array.append(img_black) 246 | 247 | # random interval 248 | # random_interval = random.randint(-2, 2) / 10 249 | 250 | # add cross after current image 251 | frame_array += [cross] * int((0.5 + random_interval) * fps) 252 | print(int((0.5 + random_interval) * fps)) 253 | 254 | return frame_array, label 255 | 256 | 257 | if __name__ == "__main__": 258 | parser = argparse.ArgumentParser() 259 | parser.add_argument("-l", "--load_json", help="load json to parse args") 260 | args = parser.parse_args() 261 | if args.load_json: 262 | with open(args.load_json, 'rt') as f: 263 | t_args = argparse.Namespace() 264 | t_args.__dict__.update(json.load(f)) 265 | args = parser.parse_args(namespace=t_args) 266 | create_video(args.image_base_path, 267 | args.fps, 268 | args.flick_times, 269 | args.screen_size, 270 | args.time_range_per_image, 271 | args.video_output, 272 | args.label_output, 273 | args.trigger_position) 274 | -------------------------------------------------------------------------------- /External_Trigger/Full_Breadboard_Setup.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenBCI/OpenBCI_Tutorials/a9d60c75e8606a8a412a12bb0aa7c54b154a10d8/External_Trigger/Full_Breadboard_Setup.jpeg -------------------------------------------------------------------------------- /External_Trigger/Images/Image_Class/Kitten/Cat_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenBCI/OpenBCI_Tutorials/a9d60c75e8606a8a412a12bb0aa7c54b154a10d8/External_Trigger/Images/Image_Class/Kitten/Cat_1.jpg -------------------------------------------------------------------------------- /External_Trigger/Images/Image_Class/Kitten/Cat_10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenBCI/OpenBCI_Tutorials/a9d60c75e8606a8a412a12bb0aa7c54b154a10d8/External_Trigger/Images/Image_Class/Kitten/Cat_10.jpg -------------------------------------------------------------------------------- /External_Trigger/Images/Image_Class/Kitten/Cat_11.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenBCI/OpenBCI_Tutorials/a9d60c75e8606a8a412a12bb0aa7c54b154a10d8/External_Trigger/Images/Image_Class/Kitten/Cat_11.jpg -------------------------------------------------------------------------------- /External_Trigger/Images/Image_Class/Kitten/Cat_12.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenBCI/OpenBCI_Tutorials/a9d60c75e8606a8a412a12bb0aa7c54b154a10d8/External_Trigger/Images/Image_Class/Kitten/Cat_12.jpg -------------------------------------------------------------------------------- /External_Trigger/Images/Image_Class/Kitten/Cat_13.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenBCI/OpenBCI_Tutorials/a9d60c75e8606a8a412a12bb0aa7c54b154a10d8/External_Trigger/Images/Image_Class/Kitten/Cat_13.jpg -------------------------------------------------------------------------------- /External_Trigger/Images/Image_Class/Kitten/Cat_14.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenBCI/OpenBCI_Tutorials/a9d60c75e8606a8a412a12bb0aa7c54b154a10d8/External_Trigger/Images/Image_Class/Kitten/Cat_14.jpg -------------------------------------------------------------------------------- /External_Trigger/Images/Image_Class/Kitten/Cat_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenBCI/OpenBCI_Tutorials/a9d60c75e8606a8a412a12bb0aa7c54b154a10d8/External_Trigger/Images/Image_Class/Kitten/Cat_2.jpg -------------------------------------------------------------------------------- /External_Trigger/Images/Image_Class/Kitten/Cat_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenBCI/OpenBCI_Tutorials/a9d60c75e8606a8a412a12bb0aa7c54b154a10d8/External_Trigger/Images/Image_Class/Kitten/Cat_3.jpg -------------------------------------------------------------------------------- /External_Trigger/Images/Image_Class/Kitten/Cat_4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenBCI/OpenBCI_Tutorials/a9d60c75e8606a8a412a12bb0aa7c54b154a10d8/External_Trigger/Images/Image_Class/Kitten/Cat_4.jpg -------------------------------------------------------------------------------- /External_Trigger/Images/Image_Class/Kitten/Cat_5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenBCI/OpenBCI_Tutorials/a9d60c75e8606a8a412a12bb0aa7c54b154a10d8/External_Trigger/Images/Image_Class/Kitten/Cat_5.jpg -------------------------------------------------------------------------------- /External_Trigger/Images/Image_Class/Kitten/Cat_9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenBCI/OpenBCI_Tutorials/a9d60c75e8606a8a412a12bb0aa7c54b154a10d8/External_Trigger/Images/Image_Class/Kitten/Cat_9.jpg -------------------------------------------------------------------------------- /External_Trigger/Images/Image_Class/Puppy/Dog_11.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenBCI/OpenBCI_Tutorials/a9d60c75e8606a8a412a12bb0aa7c54b154a10d8/External_Trigger/Images/Image_Class/Puppy/Dog_11.jpg -------------------------------------------------------------------------------- /External_Trigger/Images/Image_Class/Puppy/Dog_12.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenBCI/OpenBCI_Tutorials/a9d60c75e8606a8a412a12bb0aa7c54b154a10d8/External_Trigger/Images/Image_Class/Puppy/Dog_12.jpg -------------------------------------------------------------------------------- /External_Trigger/Images/Image_Class/Puppy/Dog_13.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenBCI/OpenBCI_Tutorials/a9d60c75e8606a8a412a12bb0aa7c54b154a10d8/External_Trigger/Images/Image_Class/Puppy/Dog_13.jpg -------------------------------------------------------------------------------- /External_Trigger/Images/Image_Class/Puppy/Dog_14.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenBCI/OpenBCI_Tutorials/a9d60c75e8606a8a412a12bb0aa7c54b154a10d8/External_Trigger/Images/Image_Class/Puppy/Dog_14.jpg -------------------------------------------------------------------------------- /External_Trigger/Images/Image_Class/Puppy/Dog_19.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenBCI/OpenBCI_Tutorials/a9d60c75e8606a8a412a12bb0aa7c54b154a10d8/External_Trigger/Images/Image_Class/Puppy/Dog_19.jpg -------------------------------------------------------------------------------- /External_Trigger/Images/Image_Class/Puppy/Dog_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenBCI/OpenBCI_Tutorials/a9d60c75e8606a8a412a12bb0aa7c54b154a10d8/External_Trigger/Images/Image_Class/Puppy/Dog_2.jpg -------------------------------------------------------------------------------- /External_Trigger/Images/Image_Class/Puppy/Dog_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenBCI/OpenBCI_Tutorials/a9d60c75e8606a8a412a12bb0aa7c54b154a10d8/External_Trigger/Images/Image_Class/Puppy/Dog_3.jpg -------------------------------------------------------------------------------- /External_Trigger/Images/Image_Class/Puppy/Dog_4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenBCI/OpenBCI_Tutorials/a9d60c75e8606a8a412a12bb0aa7c54b154a10d8/External_Trigger/Images/Image_Class/Puppy/Dog_4.jpg -------------------------------------------------------------------------------- /External_Trigger/Images/Image_Class/Puppy/Dog_5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenBCI/OpenBCI_Tutorials/a9d60c75e8606a8a412a12bb0aa7c54b154a10d8/External_Trigger/Images/Image_Class/Puppy/Dog_5.jpg -------------------------------------------------------------------------------- /External_Trigger/Images/Image_Class/Puppy/Dog_6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenBCI/OpenBCI_Tutorials/a9d60c75e8606a8a412a12bb0aa7c54b154a10d8/External_Trigger/Images/Image_Class/Puppy/Dog_6.jpg -------------------------------------------------------------------------------- /External_Trigger/Images/Image_Class/Puppy/Dog_7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenBCI/OpenBCI_Tutorials/a9d60c75e8606a8a412a12bb0aa7c54b154a10d8/External_Trigger/Images/Image_Class/Puppy/Dog_7.jpg -------------------------------------------------------------------------------- /External_Trigger/Images/Welcome/1.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenBCI/OpenBCI_Tutorials/a9d60c75e8606a8a412a12bb0aa7c54b154a10d8/External_Trigger/Images/Welcome/1.PNG -------------------------------------------------------------------------------- /External_Trigger/Images/Welcome/2.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenBCI/OpenBCI_Tutorials/a9d60c75e8606a8a412a12bb0aa7c54b154a10d8/External_Trigger/Images/Welcome/2.PNG -------------------------------------------------------------------------------- /External_Trigger/Images/Welcome/session1.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenBCI/OpenBCI_Tutorials/a9d60c75e8606a8a412a12bb0aa7c54b154a10d8/External_Trigger/Images/Welcome/session1.PNG -------------------------------------------------------------------------------- /External_Trigger/Images/Welcome/session2.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenBCI/OpenBCI_Tutorials/a9d60c75e8606a8a412a12bb0aa7c54b154a10d8/External_Trigger/Images/Welcome/session2.PNG -------------------------------------------------------------------------------- /External_Trigger/Images/Welcome/session3.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenBCI/OpenBCI_Tutorials/a9d60c75e8606a8a412a12bb0aa7c54b154a10d8/External_Trigger/Images/Welcome/session3.PNG -------------------------------------------------------------------------------- /External_Trigger/Images/Welcome/welcome2OpenBCI.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenBCI/OpenBCI_Tutorials/a9d60c75e8606a8a412a12bb0aa7c54b154a10d8/External_Trigger/Images/Welcome/welcome2OpenBCI.jpg -------------------------------------------------------------------------------- /External_Trigger/OpenBCI_Experiment_Toolkits.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": { 6 | "collapsed": true, 7 | "pycharm": { 8 | "is_executing": true 9 | } 10 | }, 11 | "source": [ 12 | "# OpenBCI Experiment Toolkits\n", 13 | "This is a tutorial about how to create external triggers in a video, assemble external trigger receiver with photoresistors, label, segment and analyze neural data with OpenBCI hardwares." 14 | ] 15 | }, 16 | { 17 | "cell_type": "markdown", 18 | "metadata": {}, 19 | "source": [ 20 | "# Before Start\n", 21 | "1. Install opencv packages by ```pip install opencv-python```\n", 22 | "2. Collect 5 images in each class (e.g. Puppies and Kiddens) and save them in ./images. Name them with the routime: class_number.jpg (e.g. Cat_1.jpg)" 23 | ] 24 | }, 25 | { 26 | "cell_type": "markdown", 27 | "metadata": {}, 28 | "source": [ 29 | "# Step 1: Create a customized experiment video with black-and-white square flicker embedded.\n", 30 | "\n", 31 | "It is recommended to build your customized experiment video from **Quick Start**. If you would like to explore more possibilities, please feel free to change the arguments in ```settings.json```.\n", 32 | "\n", 33 | "#### Quick Start\n", 34 | "1. Install OpenCV packages by ```pip install opencv-python```\n", 35 | "2. Find the folder ```./Images/Image_Class/Cat```. Put the kitten images in this folder.\n", 36 | "3. Find the folder ```./Images/Image_Class/Dog```. Put the puppie images in this folder.\n", 37 | "4. In the terminal, change directory to the current folder or type ```cd /Puppies_and_Kittens/```. Then type ```python ExternalTriggerCreator.py -l settings.json```. The experiment video ```project_video.mp4``` and the corresponding labels ```label.txt``` will be output in the folder ```./```\n", 38 | "\n", 39 | "#### Arguments in json file with default values\n", 40 | "1. \"image_base_path\": \"./Images/\", directory that stores all the images including welcome page and classification image pages.\n", 41 | "2. \"image_types\": [\"Cat\", \"Dog\"], \n", 42 | "3. \"video_time\": 3000, default time for each image to appear (ms)\n", 43 | "4. \"trigger_interval\": 100, time for the trigger to flick one time (ms)\n", 44 | "5. \"flick_times\": 5, times for the trigger to flick at the begining and ending of the video (ms)\n", 45 | "6. \"fps\": 20, \n", 46 | "7. \"screen_size\": [500, 400], \n", 47 | "8. \"time_range_per_image\": [3.5, 6.5], \n", 48 | "9. \"video_output\": \"project_video.mp4\",\n", 49 | "10. \"label_output\": \"labels.txt\",\n", 50 | "11. \"trigger_position\": [0, 300, 100, 400], [x_start, y_start, x_end, y_end]\n", 51 | "\n", 52 | "#### Experiment Video\n", 53 | "![Experiment Video](./ExperimentImage.PNG)" 54 | ] 55 | }, 56 | { 57 | "cell_type": "markdown", 58 | "metadata": {}, 59 | "source": [ 60 | "# Step 2: Assemble an external trigger receiver with photoresistor and OpenBCI hardware.\n", 61 | "\n", 62 | "Special credit to ```andyh616``` from OpenBCI Forum!\n", 63 | "\n", 64 | "Option 1: OpenBCI Experiment Toolkits\n", 65 | "\n", 66 | "Option 2: Build toolkits by yourself" 67 | ] 68 | }, 69 | { 70 | "cell_type": "markdown", 71 | "metadata": {}, 72 | "source": [ 73 | "# Step 3: Collect neural data with OpenBCI hardware and GUI." 74 | ] 75 | }, 76 | { 77 | "cell_type": "markdown", 78 | "metadata": {}, 79 | "source": [ 80 | "# Step 4: Label, segment and analyze the neural data.\n", 81 | "\n", 82 | "On windows, the collected data can be found in ```C:\\Users\\username\\Documents\\OpenBCI_GUI\\Recordings```. We will label this data set with the text file ```labels.txt``` created in **Step 1**.\n", 83 | "\n", 84 | "#### First of all, let's read the collected neural data with columns: 'index', 'ch1', ... , 'ch8', 'A7', 'TimeStamp'. \n", 85 | "***'index'***: index of data row \n", 86 | "***'ch1' to 'ch8'***: EEG channel data \n", 87 | "***'A7'***: analog channel data " 88 | ] 89 | }, 90 | { 91 | "cell_type": "code", 92 | "execution_count": 8, 93 | "metadata": { 94 | "pycharm": { 95 | "is_executing": true 96 | } 97 | }, 98 | "outputs": [ 99 | { 100 | "name": "stdout", 101 | "output_type": "stream", 102 | "text": [ 103 | "OpenBCI data shape: (55791, 10)\n" 104 | ] 105 | } 106 | ], 107 | "source": [ 108 | "import pandas as pd\n", 109 | "import matplotlib.pyplot as plt\n", 110 | "import numpy as np\n", 111 | "from scipy.signal import find_peaks\n", 112 | "\n", 113 | "openbci_datapath = '../record.txt'\n", 114 | "sample_rate = 250\n", 115 | "\n", 116 | "data = pd.read_csv(openbci_datapath, sep=\",\", header=6, index_col=False, names=['index', 'ch1', 'ch2', 'ch3', 'ch4', 'ch5', 'ch6', 'ch7', 'ch8', 'A5', 'A6', 'A7', 'Time', 'TimeStamp'], usecols=['ch1', 'ch2', 'ch3', 'ch4', 'ch5', 'ch6', 'ch7', 'ch8', 'A7', 'TimeStamp'])\n", 117 | "print(\"OpenBCI data shape: \", data.shape)" 118 | ] 119 | }, 120 | { 121 | "cell_type": "markdown", 122 | "metadata": {}, 123 | "source": [ 124 | "#### Select timestamp" 125 | ] 126 | }, 127 | { 128 | "cell_type": "code", 129 | "execution_count": 9, 130 | "metadata": { 131 | "pycharm": { 132 | "is_executing": true 133 | } 134 | }, 135 | "outputs": [ 136 | { 137 | "name": "stdout", 138 | "output_type": "stream", 139 | "text": [ 140 | "Timestamps shape: (55791,)\n", 141 | "Total length of data: 222.321 s\n" 142 | ] 143 | } 144 | ], 145 | "source": [ 146 | "Timestamps = (data['TimeStamp'].to_numpy() - data['TimeStamp'].to_numpy()[0])/1000\n", 147 | "print(\"Timestamps shape: \", Timestamps.shape)\n", 148 | "print(\"Total length of data: \", Timestamps[-1], 's')" 149 | ] 150 | }, 151 | { 152 | "cell_type": "markdown", 153 | "metadata": {}, 154 | "source": [ 155 | "#### Select EEG data and plot." 156 | ] 157 | }, 158 | { 159 | "cell_type": "code", 160 | "execution_count": 10, 161 | "metadata": { 162 | "pycharm": { 163 | "is_executing": true 164 | } 165 | }, 166 | "outputs": [ 167 | { 168 | "name": "stdout", 169 | "output_type": "stream", 170 | "text": [ 171 | "EEG data shape: (55791, 8)\n" 172 | ] 173 | }, 174 | { 175 | "data": { 176 | "text/plain": [ 177 | "" 178 | ] 179 | }, 180 | "execution_count": 10, 181 | "metadata": {}, 182 | "output_type": "execute_result" 183 | }, 184 | { 185 | "data": { 186 | "image/png": "iVBORw0KGgoAAAANSUhEUgAAAW4AAAEKCAYAAAAyx7/DAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAAHeFJREFUeJzt3X2QJHd93/H3dx72efcedmbvdIjlkEAShARBrQm2gPAUChwCScUOEEIRx5UrCMZghyR+qBRUKq5AQkhIYeMImwTHmBgEpIgfiOxyQCUoPeyBpDv0ZAkO+aS7m9m9O93ePs/MN390z2zPzkzv7N707vbu51U1NdPdv1/3r/v2PvOb3/R0m7sjIiLpkdnpBoiIyOYouEVEUkbBLSKSMgpuEZGUUXCLiKSMgltEJGUU3CIiKaPgFhFJGQW3iEjK5JJYaaFQ8OPHjyexahGRPenkyZMz7l7spmwiwX38+HGmp6eTWLWIyJ5kZj/utqyGSkREUkbBLSKSMgpuEZGUUXCLiKSMgltEJGW6Cm4z+yUz+4GZnTazL5nZQNINExGR9jYMbjN7DvCLwJS7vwTIAu9MumEiItJet+dx54BBM1sFhoBnkmjMt7/9barVahKrFhFJXF9fH6961asS386Gwe3uT5vZJ4GngEXgTne/c305MzsBnACYnJzcUmPuvvtuVldXt1RXRGSnjYyMbEtw20Y3CzazQ8BXgXcAl4GvAHe4++93qjM1NeX65aSISPfM7KS7T3VTtpsvJ98I/Mjdy+6+CnwN+KlraaCIiGxdN8H9FPBKMxsyMwPeADySbLNERKSTDYPb3e8F7gC+B5wK69yecLtERKSDrs4qcfePAh9NuC0iItIF/XJSRCRlFNwiIimj4BYRSRkFt4hIyii4RURSRsEtIpIyCm4RkZRRcIuIpIyCW0QkZRTcIiIpo+AWEUkZBbeISMoouEVEUkbBLSKSMgpuEZGUUXCLiKSMgltEJGU2DG4zu9nMHog8rpjZh7ejcSIi0mrDW5e5+2PArQBmlgWeBr6ecLtERKSDzQ6VvAF40t1/nERjRERkY13dLDjincCXkmgIwMWvPI5Xa0mtXkQkUZmBHIf+3gsS307XwW1mfcDbgF/tsPwEcAJgcnJyS41ZfXoOX1Vwi0g6ZYbz27Idc/fuCpq9HfiAu79po7JTU1M+PT19rW0TEdk3zOyku091U3YzY9zvIsFhEhER6U5XwW1mQ8DfBr6WbHNERGQjXY1xu/sCMJ5wW0REpAv65aSISMoouEVEUkbBLSKSMgpuEZGUUXCLiKSMgltEJGUU3CIiKaPgFhFJGQW3iEjKKLhFRFJGwS0ikjIKbhGRlFFwi4ikjIJbRCRlFNwiIimj4BYRSRkFt4hIyii4RURSptt7Th40szvM7FEze8TMfjLphomISHtd3XMS+DTwTXf/GTPrA4YSbJOIiMTYMLjNbAx4DfBPANx9BVhJtlkiItJJNz3uG4Ay8N/N7KXASeBD7j7f68Z85ufewerycsflZjGVYxYacRU3WHHsoq2vN3ZfYtZr8RW33t7YYxC/zfhduYZ9iV3t1tq74Ra3vN5r+HeJ/8PuvCRjmBlmGSyTwczIZDKQyZAJpxvLMhaWWSsbfc7Ul9XnN5WJrMMMy2Qb2wrWm11X1pqn16+zaX3BtjHDMkamvi6zzvth69dlHdfdeX+ssc/rt42Fr9fvx7pt76RugjsHvBz4oLvfa2afBn4F+DfRQmZ2AjgBMDk5uaXGvOwtb6NWrbRf6N6xXucl8fWCxfHLt1wvdnnMvsRW22Bf4o5E3KIttnXDJl3Tere4L/E7usE2Y5fG1NvobyGB9Xqwp16rBQ/38LlGrVYDd2rtllUr1FZrUHOcYH69XHOdSL2ar5teW29T+Xq5Wi3+eOwR7d4khg8e4uf/6+cS33Y3wX0WOOvu94bTdxAEdxN3vx24HWBqampLaXjbP3z3VqqJyC7j7mth3vRGsH669c2l/gZQfwNqvLm4h28u1bDM2htF9E2j7fy221r/HJQPtrv+janNtht11taRHxjcluO7YXC7+3kz+yszu9ndHwPeADycfNNEJK2CYYusTjhOSLdnlXwQ+GJ4RskPgZ9LrkkiIhKnq+B29weAqYTbIiIiXdAHGRGRlFFwi4ikjIJbRCRlFNwiIimj4BYRSRkFt4hIyii4RURSRsEtIpIyCm4RkZRRcIuIpIyCW0QkZRTcIiIpo+AWEUkZBbeISMoouEVEUkbBLSKSMgpuEZGUUXCLiKRMV7cuM7MzwBxQBSrurtuYiYjskG5vFgzwOnefSawlIiLSFQ2ViIikTLc9bgfuNDMH/pu7355EY77wq9+hslJLYtUiIokbHM3zjz72ysS3021w3+buz5jZBPBnZvaou98VLWBmJ4ATAJOTk1tqzI0vn6BWUXCLSDrlBzYz+rx15u6bq2D2MeCqu3+yU5mpqSmfnp6+xqaJiOwfZnay2xM/NhzjNrNhMxutvwbeBJy+tiaKiMhWddOvPwJ83czq5f/A3b+ZaKtERKSjDYPb3X8IvHQb2iIiIl3Q6YAiIimj4BYRSRkFt4hIyii4RURSRsEtIpIyCm4RkZRRcIuIpIyCW0QkZRTcIiIpo+AWEUkZBbeISMoouEVEUkbBLSKSMgpuEZGUUXCLiKSMgltEJGUU3CIiKaPgFhFJma7vJW9mWWAaeNrd35pEY2Y+9zmoVDo1IKZmh2VxdToti62yhe2obR3rdGxzbBvS1zbry5M9fJhcoUiuWCB78CCWUZ9Jtq7r4AY+BDwCjCXUFmZ+67P44mJSqxfZHbJZcuPj5AoFssUCuUIhDPVi+HqcXLFIdrxAdmR4p1sru1BXwW1m1wN/B/gN4JeTaszN99/XfoF750odlsXU6Ly+LWxnS22Lb1zPtrO1tsU2rmfb6XnbOi7anrbF1aktr1CdnaEyM0OlHD6H09XyDMuPPEpldhaq1Za6NjRErhgGeyEM+WIxnBe8zhYK5A4fxnKb6YdJmnX7L/1fgH8FjCbYlp7+4cV9OhbZdjc8P3ax12pUL11aC/dymcpMmerMDJWZWSrlMsuPP878d79LbW6udQWZTDgcU4j03CMhX59XLJIZVi8+7TZMSjN7K1By95Nm9tqYcieAEwCTk5M9a6DIfmCZTDB8Mj4ON98cW7a2vByGe4nqbBDqwaPeqw9CvjI72/Y7o8zQUBjoxXCoptiYbjwmisFYfOx3JLJTbKOPxmb274H3ABVggGCM+2vu/o871ZmamvLp6eletlNENslrNarPPkulVG704CvloBe/WipRrffsy2VqCwst9S2fD4K9WAzCfaLY1HPPFSeC53EN0/SCmZ1096muym5mTDPscX9ko7NKFNwi6VKbn2/01psepebp6uXLrZXrwzT1YZmJiUi4FyMhXyDT37/9O5cSmwluvU2KCJnhYfqGh+l73vNiy/nKSvuAj4R848vWWq11O2NjQc+93fBMsd6rn9DZNBvYVHC7+7eAbyXSEhHZ9ayvj/yxY+SPHYst59Uq1YsXW0O+3oMvlVg8eZJKuYyvrrZup342Tbtwjzz26zi8etwi0nOWzTbClRe9qGM5d6f27LPte/Bh0C8//Ajz5bvajsOTzzcPy0wU101PBL37PTYOv3f2RERSx8zIHjxI9uBB+l/4wtiytfn5tUCfmaFSKoXPwbzVp55i8eTJ+HH49WPv9emJtXmZgYGE9rZ3FNwikgqNcfjjx2PL1VZWgvPfO43Dz8yw/NhjHX/0lBkZaTMs0zpskxkb27FhGgW3iOwpmb4+Mt2Owzd+9BQZf4+E/uJDDwXj8EtLLfWtr6+px54tFMhfd4zCiX+W1K41KLhFZF+ybLbxC1NuuaVjOXcPhmnWnQ/fOEVyZoaVM2eo3Hc/NjSk4BYR2WlmRnZkhOzICP0bXbqg09VNe0zXlhQR6ZHtOnNFwS0ikjIKbhGRlFFwi4ikjIJbRCRlFNwiIimj4BYRSRkFt4hIyii4RURSRsEtIpIyCm4RkZRRcIuIpMyGP6w3swHgLqA/LH+Hu380ica8/8/fz0p1pX076HDd246z2y/ouB7oeG3d3bjtXrUpdhubbdMWrk3cs23H7N+m/516tO2B3ACFwQLjA+PB8+A4xaEihcEC/VndNFe2rpsroiwDr3f3q2aWB+42sz9193t63ZhqrUql1v3VtZz2d6jvdOf6TuVjl3Wcnfy2O62rl+vpWKdXbdrBbW9lXb38d12sLHJp6VLbMqP50bUgH2gO9ejjYP9BMqYPxtJsw+D24C/2ajiZDx+b/x/UhdvfdHsSqxXZMZVahYtLFykvlpldnGV2cZaZxRnKi2VmFmeYXZzl9OxpZhZnWKwsttTPWY7Dg4cpDjaHemN6aG26L9u3A3soO6GraxCaWRY4CbwA+E13vzfRVonsEblMjomhCSaGJjYsu7C60BTq0Ud5scz5+fOcmjnVsRc/1jcWBPpQc7gXB4sUh4qMD44zMTjBcH54X94ZfS/pKrjdvQrcamYHga+b2Uvc/XS0jJmdAE4ATE5O9ryhInvdUH6Iyfwkk2Px/3/qvfimYF8oN4X8A6UHKC+UWam1fmc0mBtkfGCciaGJINjDIZrG9GCR4mCRA/0HFPC7lG123NDMPgrMu/snO5WZmpry6enpa22biFwDd2dudY6ZhSDMy4vl5tdh4JcXy8yvzrfUz2fyjR58PcyLQ63PGofvDTM76e5T3ZTt5qySIrDq7pfNbBB4I/CJa2yjiCTMzBjrG2Osb4wbDt4QWzY6TFMP8+jrM8+e4f7z93Nl5UpL3ZzlgmGYaI+9TcAf6j9ENpNNanf3lW6GSq4DvhCOc2eAL7v7HyXbLBHZTt0O0yxVlhpDMqWFUqPnXlooMbM4w9mrZ/l+6ftcXr7cUjdr2eDUyKECE4MTaz35eriHY/Ljg+PkMrodbpxuzip5CHjZNrRFRHa5gdwA149ez/Wj18eWW6murH3RujBDabHUGIcvLZY4N3+Oh2Ye4uLSxZa6hnF44HAj0Dv15McHx8ln8knt6q6mtzUR6bm+bB/HRo5xbORYbLnV2iqzi7ONIZnocE29F//w7MNcXLrYciaNYRwaONQYh58YnGjqvddfFwYL5LN7K+AV3CKyY/KZPEeHj3J0+GhsuUqt0nQOfD3Uo8+PX3yc2aVZal5rqX+o/9DaEE30DJp1vfq0nAuv4BaRXS+XyXFk+AhHho/ElqvWqo0fPDW+ZF0oU1osNc6o+cvLf8ns4ixVr7bUP9B/oNFLjw7RNHr04evB3GBSu9oVBbeI7BnZTDboRQ8VYbxzuWqtyqXlSy299ug58fedv4+ZxZm2l+EYzY+2fLlaGCxwZPgIbz7+5gT3MKDgFpF9J5vJNi4fcMvhWzqWc3cuL19uOQc+2puP/thpYnBCwS0ispPMgi9ADw0c4qZDN3UsV/+x05Xl1vPck6DgFhG5RtEfO20H/U5VRCRlFNwiIimj4BYRSRkFt4hIyii4RURSRsEtIpIyCm4RkZRRcIuIpIyCW0QkZRTcIiIps7t+8n7qDmhzLd1Ah7tNb/Yu1B3Lb3b9Kr+18h2Kp6H9loGhcRiZgMFDm//bE+mRbm4W/Fzg94CjQA243d0/nUhrvvFBWF1IZNUiPZXJw3AxCPGRI+ue66/D6b4Rhbz0VDc97grwL9z9e2Y2Cpw0sz9z94d73pr33d1+vnv7+XSYr/I9Lt+heGra36PytQoszMLVEly9APPl4HnuHJx/KJjf5uL85IfaBPzR5nmjR4M3gj12iy1JRjc3Cz4HnAtfz5nZI8BzgN4H9/iNPV+lyLap1cJgv9Ac7PWgnzsP5cfhzN2weKn9OobGI731SKjXp0fDwO8fUy9+H9vUGLeZHSe44/u9bZadAE4ATE5O9qBpIimTycBIMXjwkviyleW1QL9agqvnYe5C8/TsE8F0daW1fm4QRiM993q4rw/5oXHIZBPZXdk55h0/Rq4raDYCfBv4DXf/WlzZqakpn56e7kHzRPY596B3Xg/zq6Wg517vwdd793MXYPnZ1vqWDYZgRo82h/vo0SD0o+GvYZodZWYn3X2qm7Jd9bjNLA98FfjiRqEtIj1kBkOHg8dE51tsAbC6uBbijZA/t9aTv/I0PH0S5mdoHd83GC6shfnoURi9Lgz668JH2JNXwO+4bs4qMeB3gUfc/VPJN0lEtiQ/CIeOB4841dVg/D3ac587Hw7XhI/zp2G+1P703KHCWpA3BXz4ut6zV8Anppse923Ae4BTZvZAOO/X3P1PkmuWiCQmm4exY8EjTq0aBnzYa5871xz0c+c2F/AjR9eGaRTw16Sbs0ruJuZnEyKyR2Wya0Ebp1YNhl8awX4uEu5hT/7CD4JlLQEfHaKpD9NcF+nJR8bms7vr94I7SUdCRK5NJhsG7pH4co0efKTHXn9unA9/qkMP3sIvWSPBPrKu9z56FIYn9kXA7/09FJHdodsefLWyNkTTrgc/dw6eeSAo0+5L1vrpkU0993U9+eFCqk+TVHCLyO6SzcHYdcEjTrUS9M6vnGv+YrUe9M8+DWenYWGmta5lm0+NbBp3j0wPjQfn5+8yCm4RSadsrrsvWSsrQcA3Dc9EQv7Sj+Gpe2DxYmvdTC7yw6ZowK8bstnmgFdwi8jeluuDA9cHjziV5chZM/Xz36MB/yN46rvtL1eQyQUBPn4DvPf/JLMfEQpuERGAXD8cnAwecVaXIpcoWDc8s00n4Cm4RUQ2Iz/Q3Q+dErT7Rt1FRCSWgltEJGUU3CIiKaPgFhFJGQW3iEjKKLhFRFJGwS0ikjIKbhGRlFFwi4ikjIJbRCRlFNwiIinTzc2CPw+8FSi5+0uSbMyrPvEXLK1WO7Wk/dwO13SJu9RL5zq93MbmLjYTV3wn29uxTlx7e7SN2GOyyX2P06t2dZrfn8tSHOmnMNpHcWSA4mh/06Mw0kd/Lr0X9Zft181Fpv4H8Bng95JtCrzxRUdYrbbedHT9PS4a8zst6Fijc52O8zusq/O2N9/eTtuIW1nnbXRob+ctxLRrc9uI3U4vj2+P1rWVY9KpVlx7F1aqPFm+yj0/WubywmrbMgcG80GQjzSHenS6MNLP4eE+shndAna/6+ZmwXeZ2fHkmwIfe9tf247NiOyYlUqNmavLjUd5LvIIpx86e5ny3DLzK62fPjMG4yOdA35itJ+JsaBXP9yX3fQnP0mHnl3W1cxOACcAJic3uJ6tyD7Vl8tw7OAgxw4Oblh2frnSHO5tgv6x83PMXF2mUmvt8g/ms0yMBWEehPraME10nnrx6WNxH3sbhYIe9x91O8Y9NTXl09PT19YyEelKreZcXlylNLdEeW6Z0pW1kC/NLVO6shRMX1lmbrnSUj+bMQojfRRH+zkyOsDEWD/F0YGg9x724OtBn8/qfIakmNlJd5/qpqxupCCScpmMcXi4j8PDfdyywQ3UF1eqYaAvrQV75PUzzy7x4NlnmZ1fbjtuPz4cBHw9zNeH+5FwmGYgry9bk6TgFtlHBvuyTI4PMTk+FFuuUq0xO7/ChStLlK6sBXy9B1+aW+bx83OUry5TbTNMMzqQ48hYa689GvhHxgYY7lcEbUU3pwN+CXgtUDCzs8BH3f13k26YiOycXDbDkbEBjowNxJar1ZyLCythuAeBXo6Ee2lumekfX6I0t8xKpfWMseG+bOPL1OagD8bfj4TDNmMDOX3RGtHNWSXv2o6GiEj6ZDJGYSQ4VfHFjHUs5+5cWaxQmlviwpVo732ZC3NLlK8sc+rsZS5cWWaxzW85BvIZJurj7mGoT4ytjcnXQ/7AYH5fBLw+p4hI4syMA0N5DgzleeGR0Y7l3J2ry5VGqJfmgqGaC+EXrBeuLPHo+TnuenyGq22+aO3LZSJj70GYt+vRHxrqI5PiM2kU3CKya5gZowN5Rgfy3FgciS27sFJphHppLgz3cHjmwpUlnihf5TtPzjC31Brw+axRHImOvTf33uvP48O7M+AV3CKSSkN9OY4XchwvDMeWW1ypNg/NNMbfg978mdl57jtzse2vWnPhUND64ZliZCz+yFgQ8LltPFVSwS0ie9pgX5bnjQ/zvPH4gF9arTZ67OXoWPyVZS7MLXP20gLfe+oSF+dXWuqawfhwP88vDPGV9/1UUrvSoOAWEQEG8lmee3iI5x6OP1WyftmC0rqzZ8pzS9vUUgW3iMimbOayBUnR71dFRFJGwS0ikjIKbhGRlFFwi4ikjIJbRCRlFNwiIimj4BYRSRkFt4hIynR167JNr9SsDPx4i9ULwEwPm7PX6Xhtjo7X5uh4bZ/nuXuxm4KJBPe1MLPpbu+7Jjpem6XjtTk6XruThkpERFJGwS0ikjK7Mbhv3+kGpIyO1+boeG2OjtcutOvGuEVEJN5u7HGLiEiMHQtuM3uzmT1mZk+Y2a+0Wd5vZn8YLr/XzI5vfyu3l5mdMbNTZvaAmU2H8z5mZk+H8x4ws59uU+/myPIHzOyKmX242/ppZWafN7OSmZ2OzPtZM/uBmdXMbCoyf9zM/p+ZXTWzz8Ssc88cr3bHJ5z/wfD/3g/M7D+E89697m+oZma3tlnnfzSzR83sITP7upkdDOcfN7PFSP3f3p693KfcfdsfQBZ4ErgB6AMeBF68rsw/B347fP1O4A93oq3bfFzOAIV18z4GfGSTx/Y8wTmhm66fpgfwGuDlwOnIvBcBNwPfAqYi84eBVwHvAz4Ts849c7w6HJ/XAX8O9IfTE23q/XXghx3W+SYgF77+BPCJ8PXx6Hb0SPaxUz3uVwBPuPsP3X0F+F/A29eVeTvwhfD1HcAbzGz33W5593kD8KS7b/UHUKnh7ncBF9fNe8TdH2tTdt7d7wa27/5SO6zd8QHeD3zc3ZfDMqU2Vd8FfKnDOu909/pt0+8Bru9Rc2UTdiq4nwP8VWT6bDivbZnwD+VZYHxbWrdzHLjTzE6a2YnI/F8IP5p+3swObbCOd9L6n24z9WVvH6+bgFeHw4/fNrOfaFPmHXQI7nX+KfCnkennm9n3w/W+uheNlfZ2Krjb9ZzXn97STZm95jZ3fznwFuADZvYa4LPAjcCtwDngP3WqbGZ9wNuAr0Rmd11fgL1/vHLAIeCVwL8Evhz9JGtmfxNYcPfTHerXy/06UAG+GM46B0y6+8uAXwb+wMzGEmi/sHPBfRZ4bmT6euCZTmXMLAccoPVj357i7s+EzyXg68Ar3P2Cu1fdvQZ8jmCYqZO3AN9z9wuRdW6m/r63D47XWeBrHrgPqBFcj6Su3Se2Jmb2XuCtwLs9HOB292V3nw1fnyT4DuumBNov7Fxw3w+80MyeH/YS3wl8Y12ZbwDvDV//DPAX9T+SvcjMhs1stP6a4Eug02Z2XaTY3wfiekItY5ObrL/v7YPj9b+B1wOY2U0EJwfMhNMZ4GcJvnNqy8zeDPxr4G3uvhCZXzSzbPj6BuCFwA8T2gfZqW9FgZ8GHid4Z/71cN6/JfiDABgg+Mj/BHAfcMNOf5Ob8PG4geDsmgeBH0SOyf8ETgEPEbyZXRfOPwb8SaT+EDALHFi33rb198KD4E3qHLBK0JP8eYKwPQssAxeA/xspf4bgU9vVsMyLw/m/Q3gGyl46Xh2OTx/w+wRvSN8DXh8p/1rgnjbriR6fJwi+e3ogfNTP/PoH4d/tg+F6/+5O7/9efuiXkyIiKaNfToqIpIyCW0QkZRTcIiIpo+AWEUkZBbeISMoouEVEUkbBLbtaeDnW+qVCz6+75Op3E9rmy8zsd2KWF83sm0lsW6QbuZ1ugEgcD35GfSsE18oGrrr7JxPe7K8B/y6mTWUzO2dmt7n7dxJui0gL9bgltczsavj82vCKdF82s8fN7OPhjQHus+DGFDeG5Ypm9lUzuz983NZmnaPA33D3B8PpvxXp4X+/flkCgp+Ov3ubdlWkiYJb9oqXAh8iuAnAe4Cb3P0VBD/X/mBY5tPAf3b3nyD4iXa74ZApmq9P8hHgA+5+K/BqYDGcPx1Oi2w7DZXIXnG/u58DMLMngTvD+acI7voC8EbgxZGrmI6Z2ai7z0XWcx1Qjkx/B/iUmX2R4Kp6Z8P5JYLrxYhsOwW37BXLkde1yHSNtb/zDPCT7r5IZ4sEFzgDwN0/bmZ/THBRtHvM7I3u/mhYJm49IonRUInsJ3cCv1CfaHczXOAR4AWRMje6+yl3/wTB8Mgt4aKb2HuXfJWUUHDLfvKLwFR4W7KHCW4c3CTsTR+IfAn5YTM7bWYPEvSw67fqeh3wx9vRaJH1dFlXkXXM7JeAOXePO5f7LuDt7n5p+1omElCPW6TVZ2keM29iZkXgUwpt2SnqcYuIpIx63CIiKaPgFhFJGQW3iEjKKLhFRFJGwS0ikjL/H4zGl/45dvhpAAAAAElFTkSuQmCC\n", 187 | "text/plain": [ 188 | "
" 189 | ] 190 | }, 191 | "metadata": { 192 | "needs_background": "light" 193 | }, 194 | "output_type": "display_data" 195 | } 196 | ], 197 | "source": [ 198 | "EEG_data = data[['ch1', 'ch2', 'ch3', 'ch4', 'ch5', 'ch6', 'ch7', 'ch8']].to_numpy()\n", 199 | "print(\"EEG data shape: \", EEG_data.shape)\n", 200 | "for i in range(EEG_data.shape[1]):\n", 201 | " plt.plot(EEG_data[:,i]/np.mean(EEG_data[:,i])+i)\n", 202 | "plt.xticks(ticks=np.arange(0, round(Timestamps[-1]+1)*sample_rate, round(Timestamps[-1]+1)*sample_rate/4), \n", 203 | " labels=np.arange(0, round(Timestamps[-1]+1),round(Timestamps[-1]+1)/4))\n", 204 | "plt.xlabel('Time (s)')\n", 205 | "plt.tight_layout" 206 | ] 207 | }, 208 | { 209 | "cell_type": "markdown", 210 | "metadata": {}, 211 | "source": [ 212 | "#### Select analog data and plot." 213 | ] 214 | }, 215 | { 216 | "cell_type": "code", 217 | "execution_count": 11, 218 | "metadata": { 219 | "pycharm": { 220 | "is_executing": true 221 | } 222 | }, 223 | "outputs": [ 224 | { 225 | "name": "stdout", 226 | "output_type": "stream", 227 | "text": [ 228 | "analog data shape: (55791,)\n" 229 | ] 230 | }, 231 | { 232 | "data": { 233 | "text/plain": [ 234 | "" 235 | ] 236 | }, 237 | "execution_count": 11, 238 | "metadata": {}, 239 | "output_type": "execute_result" 240 | }, 241 | { 242 | "data": { 243 | "image/png": "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\n", 244 | "text/plain": [ 245 | "
" 246 | ] 247 | }, 248 | "metadata": { 249 | "needs_background": "light" 250 | }, 251 | "output_type": "display_data" 252 | } 253 | ], 254 | "source": [ 255 | "analog_data = data['A7']\n", 256 | "print(\"analog data shape: \", analog_data.shape)\n", 257 | "plt.plot(analog_data)\n", 258 | "plt.xticks(ticks=np.arange(0, round(Timestamps[-1]+1)*sample_rate, round(Timestamps[-1]+1)*sample_rate/5), \n", 259 | " labels=np.arange(0, round(Timestamps[-1]+1),round(Timestamps[-1]+1)/5))\n", 260 | "plt.xlabel('Time (s)')\n", 261 | "plt.tight_layout" 262 | ] 263 | }, 264 | { 265 | "cell_type": "markdown", 266 | "metadata": {}, 267 | "source": [ 268 | "#### Detect spikes in analog channel." 269 | ] 270 | }, 271 | { 272 | "cell_type": "code", 273 | "execution_count": 12, 274 | "metadata": { 275 | "pycharm": { 276 | "is_executing": true 277 | } 278 | }, 279 | "outputs": [ 280 | { 281 | "name": "stdout", 282 | "output_type": "stream", 283 | "text": [ 284 | "Total number of peaks: 38\n" 285 | ] 286 | }, 287 | { 288 | "data": { 289 | "image/png": "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\n", 290 | "text/plain": [ 291 | "
" 292 | ] 293 | }, 294 | "metadata": { 295 | "needs_background": "light" 296 | }, 297 | "output_type": "display_data" 298 | } 299 | ], 300 | "source": [ 301 | "peaks, _ = find_peaks(analog_data, height=(5, 20), distance=0.1*250) # distance is essential!\n", 302 | "fig, ax = plt.subplots(1, 3, figsize=(20,5))\n", 303 | "\n", 304 | "ax[0].plot(analog_data)\n", 305 | "ax[0].plot(peaks, analog_data[peaks], \"x\")\n", 306 | "ax[0].set_ylim(-2, 20)\n", 307 | "ax[0].title.set_text('Summary')\n", 308 | "ax[0].set_xticks(ticks=np.arange(0, len(analog_data), len(analog_data)/4))\n", 309 | "ax[0].set_xticklabels(labels=np.arange(0, len(analog_data)/250,len(analog_data)/250/4))\n", 310 | "\n", 311 | "# Start \n", 312 | "ax[1].plot(analog_data)\n", 313 | "ax[1].plot(peaks, analog_data[peaks], \"x\")\n", 314 | "ax[1].set_xlim(1000,3000)\n", 315 | "ax[1].set_ylim(-2, 20)\n", 316 | "ax[1].title.set_text('4 - 12 s')\n", 317 | "ax[1].set_xticks(ticks=np.arange(1000, 3000, 2000/4))\n", 318 | "ax[1].set_xticklabels(labels=np.arange(1000/250, 3000/250, 2000/250/4))\n", 319 | "\n", 320 | "# End\n", 321 | "ax[2].plot(analog_data)\n", 322 | "ax[2].plot(peaks, analog_data[peaks], \"x\")\n", 323 | "ax[2].set_xlim(28000,30000)\n", 324 | "ax[2].set_ylim(-2, 20)\n", 325 | "ax[2].title.set_text('112 - 120 s')\n", 326 | "ax[2].set_xticks(ticks=np.arange(28000, 30000, 2000/4))\n", 327 | "ax[2].set_xticklabels(labels=np.arange(28000/250, 30000/250, 2000/250/4))\n", 328 | "\n", 329 | "fig.savefig('fig.png')\n", 330 | "\n", 331 | "print(\"Total number of peaks: \", len(peaks))" 332 | ] 333 | }, 334 | { 335 | "cell_type": "markdown", 336 | "metadata": {}, 337 | "source": [ 338 | "#### From the figure above, the combination of the first 4 peaks is the indicator of the start of the video. From Step 1, there will be totally 22 peaks indicating the start of each image." 339 | ] 340 | }, 341 | { 342 | "cell_type": "code", 343 | "execution_count": 13, 344 | "metadata": { 345 | "pycharm": { 346 | "is_executing": true 347 | } 348 | }, 349 | "outputs": [ 350 | { 351 | "data": { 352 | "text/plain": [ 353 | "22" 354 | ] 355 | }, 356 | "execution_count": 13, 357 | "metadata": {}, 358 | "output_type": "execute_result" 359 | } 360 | ], 361 | "source": [ 362 | "image_peaks = peaks[4:4+22]\n", 363 | "len(image_peaks)" 364 | ] 365 | }, 366 | { 367 | "cell_type": "markdown", 368 | "metadata": {}, 369 | "source": [ 370 | "#### Insert labels into the raw data set: Puppies: 1 vs Kittens: 2" 371 | ] 372 | }, 373 | { 374 | "cell_type": "code", 375 | "execution_count": 14, 376 | "metadata": { 377 | "pycharm": { 378 | "is_executing": true 379 | } 380 | }, 381 | "outputs": [ 382 | { 383 | "data": { 384 | "text/plain": [ 385 | "" 386 | ] 387 | }, 388 | "execution_count": 14, 389 | "metadata": {}, 390 | "output_type": "execute_result" 391 | }, 392 | { 393 | "data": { 394 | "image/png": "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\n", 395 | "text/plain": [ 396 | "
" 397 | ] 398 | }, 399 | "metadata": { 400 | "needs_background": "light" 401 | }, 402 | "output_type": "display_data" 403 | } 404 | ], 405 | "source": [ 406 | "label_path = '../labels_version_3.txt'\n", 407 | "\n", 408 | "label_data = pd.read_csv(label_path, sep=',', index_col=False, names=['label_index', 'label', 'filename'])\n", 409 | "index_array = label_data['label_index'].to_numpy()\n", 410 | "labels = np.zeros(len(EEG_data))\n", 411 | "\n", 412 | "for i in range(len(image_peaks)):\n", 413 | " peak_timestamp = image_peaks[i]\n", 414 | " labels[peak_timestamp] = index_array[i]+1\n", 415 | " \n", 416 | "\n", 417 | "for i in range(EEG_data.shape[1]):\n", 418 | " plt.plot(EEG_data[:,i]/np.mean(EEG_data[:,i])-i)\n", 419 | "plt.xticks(ticks=np.arange(0, round(Timestamps[-1]+1)*sample_rate, round(Timestamps[-1]+1)*sample_rate/4), \n", 420 | " labels=np.arange(0, round(Timestamps[-1]+1),round(Timestamps[-1]+1)/4))\n", 421 | "plt.plot(labels-i-2)\n", 422 | "plt.xlabel('Time (s)')\n", 423 | "plt.tight_layout\n", 424 | "plt.legend(['ch1', 'ch2', 'ch3', 'ch4', 'ch5', 'ch6', 'ch7', 'ch8', 'label'])" 425 | ] 426 | }, 427 | { 428 | "cell_type": "code", 429 | "execution_count": null, 430 | "metadata": {}, 431 | "outputs": [], 432 | "source": [] 433 | }, 434 | { 435 | "cell_type": "code", 436 | "execution_count": null, 437 | "metadata": {}, 438 | "outputs": [], 439 | "source": [] 440 | } 441 | ], 442 | "metadata": { 443 | "kernelspec": { 444 | "display_name": "Python 3", 445 | "language": "python", 446 | "name": "python3" 447 | }, 448 | "language_info": { 449 | "codemirror_mode": { 450 | "name": "ipython", 451 | "version": 3 452 | }, 453 | "file_extension": ".py", 454 | "mimetype": "text/x-python", 455 | "name": "python", 456 | "nbconvert_exporter": "python", 457 | "pygments_lexer": "ipython3", 458 | "version": "3.7.1" 459 | } 460 | }, 461 | "nbformat": 4, 462 | "nbformat_minor": 1 463 | } 464 | -------------------------------------------------------------------------------- /External_Trigger/README.md: -------------------------------------------------------------------------------- 1 | # OpenBCI_Experiment 2 | 3 | Welcome to the OpenBCI Puppies and Kittens Experiment designed by Fan Li. 4 | 5 | During this experiment, you will watch a video containing images of puppies and kittens, and press a button every time you see a puppy in the image. 6 | 7 | Below are the instructions on how to do it. The full information on this experiment can be found on [Fan Li's Repository](https://github.com/Fan1117/Puppies_and_Kittens/). Once you're comfortable with how the experiment works, you can modify the script to create your own experiments. 8 | 9 | ## Equipment Required 10 | 11 | 1. Headwear, which can be: 12 | 13 | - [Ultracortex Mark IV Headset](https://shop.openbci.com/products/ultracortex-mark-iv) with [Copper Wires](https://www.amazon.com/StrivedayTM-Flexible-Electric-electronic-electrics/dp/B01LH1FYHO/ref=sr_1_3?crid=2ANLHLBH5WL2Q&dchild=1&keywords=flexible+wire+22+gauge&qid=1598387126&s=hi&sprefix=flexible+wire+22+g%2Ctools%2C179&sr=1-3). 14 | - [Gold Cup Electrodes](https://shop.openbci.com/collections/frontpage/products/openbci-gold-cup-electrodes?variant=9056028163) with [Ten20 Paste](https://shop.openbci.com/collections/frontpage/products/ten20-conductive-paste-2oz-jars?variant=31373533198). 15 | - [EEG Electrode Cap Kit](https://docs.openbci.com/docs/04AddOns/01-Headwear/ElectrodeCap) with [Electrode Cap Gel](https://shop.openbci.com/collections/frontpage/products/electrodegel?variant=28056992776264) and [Touch Proof Adapter](https://shop.openbci.com/collections/frontpage/products/touch-proof-electrode-cable-adapter?variant=31007211715). 16 | 2. [Cyton Board](https://shop.openbci.com/collections/frontpage/products/cyton-biosensing-board-8-channel?variant=38958638542) 17 | 2. [OpenBCI GUI](https://github.com/OpenBCI/OpenBCI_GUI/releases/tag/v5.0.0) 18 | 3. Breadboard: 19 | 20 | The breadboard includes a photocell circuit for the trigger, and a button circuit for user feedback. The components needed for both are: 21 | 22 | - [1x Breadboard](https://www.amazon.com/DEYUE-breadboard-Set-Prototype-Board/dp/B07LFD4LT6/ref=sr_1_5?dchild=1&keywords=breadboard&qid=1591125068&sr=8-5) 23 | - [1x Photoresistor](https://www.amazon.com/gp/product/B01N7V536K/ref=ppx_yo_dt_b_asin_title_o07_s00?ie=UTF8&psc=) 24 | - [1x 220 Ohm resistor](https://www.amazon.com/EDGELEC-Resistor-Tolerance-Multiple-Resistance/dp/B07QK9ZBVZ/ref=sr_1_1_sspa?crid=S5FLXTR7YG6L&dchild=1&keywords=resistor+220+ohm&qid=1591125607&s=industrial&sprefix=resistor+220+%2Cindustrial%2C146&sr=1-1-spons&psc=1&spLa=ZW5jcnlwdGVkUXVhbGlmaWVyPUExWlRVVTM3QzRBWEE4JmVuY3J5cHRlZElkPUEwOTMyNDM3Q1JIM0gwUlc5UzJYJmVuY3J5cHRlZEFkSWQ9QTAwNzUwODkxSDRDS0ZQVTlJWVpKJndpZGdldE5hbWU9c3BfYXRmJmFjdGlvbj1jbGlja1JlZGlyZWN0JmRvTm90TG9nQ2xpY2s9dHJ1ZQ==) 25 | - [1x 1KOhm resistor](https://www.amazon.com/EDGELEC-Resistor-Tolerance-Multiple-Resistance/dp/B07QG1V4YL/ref=sr_1_1_sspa?dchild=1&keywords=resistor+1k+ohm&qid=1598631730&s=industrial&sr=1-1-spons&psc=1&spLa=ZW5jcnlwdGVkUXVhbGlmaWVyPUFNWEM0VURBS0lSS0EmZW5jcnlwdGVkSWQ9QTA5NTk4MzkyNk5QWldHMVY4U0hKJmVuY3J5cHRlZEFkSWQ9QTAwOTU5MDVGODBTMU85ODM0QUkmd2lkZ2V0TmFtZT1zcF9hdGYmYWN0aW9uPWNsaWNrUmVkaXJlY3QmZG9Ob3RMb2dDbGljaz10cnVl) 26 | - [5x Jumper cables male to male (8 inch)](https://www.amazon.com/GenBasic-Solderless-Dupont-Compatible-Breadboard-Prototyping/dp/B077N9X7Y3/ref=sr_1_2?dchild=1&keywords=Male%2Bto%2Bmale%2BJumpers&qid=1591126744&sr=8-2&th=1) 27 | - Either [2x Jumper cables female to male (8 inch)](https://www.amazon.com/GenBasic-Solderless-Dupont-Compatible-Breadboard-Prototyping/dp/B077N5RLHN/ref=sr_1_1_sspa?dchild=1&keywords=Male%2Bto%2BFemale%2BJumpers&qid=1591126392&sr=8-1-spons&spLa=ZW5jcnlwdGVkUXVhbGlmaWVyPUEzTEtKREtGMTZSNTA0JmVuY3J5cHRlZElkPUEwMjExMDE0Q0dYOEZCUFlKRFZMJmVuY3J5cHRlZEFkSWQ9QTA0NDYyMjMyMTk5WlhCMEg0MzFRJndpZGdldE5hbWU9c3BfYXRmJmFjdGlvbj1jbGlja1JlZGlyZWN0JmRvTm90TG9nQ2xpY2s9dHJ1ZQ&th=1) for the photoresistor connection or [2x Jumper cables male to male (8 inch)](https://www.amazon.com/GenBasic-Solderless-Dupont-Compatible-Breadboard-Prototyping/dp/B077N9X7Y3/ref=sr_1_2?dchild=1&keywords=Male%2Bto%2Bmale%2BJumpers&qid=1591126744&sr=8-2&th=1) if you can solder the cable with the photoresistor. 28 | 29 | ## Step 1: Headwear, Board and Software Setup 30 | 31 | First, connect the headwear to yourself and to the Cyton board, and read from it using the GUI. If you are using the Ultracortex, follow [this tutorial](https://docs.openbci.com/docs/04AddOns/01-Headwear/MarkIV). If you're using the gold cup electrodes, follow [this guide](https://docs.openbci.com/docs/01GettingStarted/02-Biosensing-Setups/EEGSetup) to learn how to connect each electrode, and connect them in the positions you'd like to measure EEG from. A good guide to the 8 positions commonly used can be found in the Ultracortex tutorial. If you're using an electrode cap, follow [this tutorial](https://docs.openbci.com/docs/04AddOns/01-Headwear/ElectrodeCap) to connect it. 32 | 33 | ## Step 2: Breadboard Setup 34 | 35 | The diagram for the circuit with the photocell and the button can be found below. 36 | 37 | ![](Circuit_Diagram.png) 38 | 39 | Using the components listed above, assemble the breadboard. You can find an example of how to assemble a button circuit using Arduino [here](https://www.arduino.cc/en/tutorial/button) and an example of how to assemble a photocell circuit [here](https://openbci.com/community/measuring-stimulus-timing-with-a-photoresistor/). The final breadboard should look similar to the pictures. 40 | 41 | ![](Full_Breadboard_Setup.jpeg) 42 | ![](Breadboard_Setup.jpeg) 43 | 44 | Next, connect the breadboard to the Cyton board as shown below. Place the breadboard beside your computer such that the photocell points to the lower left corner of your screen, which is where the video trigger will be located. 45 | 46 | ![](connect.jpeg) 47 | 48 | ## Step 4: Run Experiment 49 | 50 | Download [this video](video.mp4). Once you're ready to start, press ```Start Data Stream``` in the GUI, open the video, and make it Full-Screen. Every time a puppy appears in the video, press the button. The video is around 3 minutes long. You're now ready to press play! 51 | 52 | ## Step 5: Retrieve Data 53 | 54 | Once you've finished watching the video, press ```Stop Data Stream```. In your /Documents/OpenBCI_GUI/Recordings folder you should find the recorded data for that session. 55 | 56 | ## Step 6: Process Data 57 | 58 | In [this Python notebook](OpenBCI_Experiment_Toolkits.ipynb), you'll find sample code to read, plot, and analyze the recorded data. 59 | 60 | ## Step 7: Create your Own Experiment 61 | 62 | Once you understand how to conduct an experiment, you can modify [this Python script](ExternalTriggerCreator_quick.py) to make your own video. The current code reads the images stored in the ```Images``` folder, shuffles them, and creates a video with 4 different sessions. Each session displays the images at a different rate. Each image has an embedded trigger and is separated from the others by a fixation cross. 63 | 64 | The video pattern was created in accordance to the diagram below obtained from the research paper [Toward Emotion Aware Computing: An Integrated Approach Using Multichannel Neurophysiological Recordings and Affective Visual Stimuli](https://ieeexplore.ieee.org/document/5415563) by C. A. Frantzidis, C. Bratsas, C. L. Papadelis, E. Konstantinidis, C. Pappas and P. D. Bamidis, published in IEEE Transactions on Information Technology in Biomedicine, vol. 14, no. 3, pp. 589-597, May 2010. 65 | 66 | ![](video_picture.png) 67 | -------------------------------------------------------------------------------- /External_Trigger/connect.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenBCI/OpenBCI_Tutorials/a9d60c75e8606a8a412a12bb0aa7c54b154a10d8/External_Trigger/connect.jpeg -------------------------------------------------------------------------------- /External_Trigger/labels.txt: -------------------------------------------------------------------------------- 1 | 2,Puppy,./Images/Image_Class/Puppy/Dog_2.jpg, 2 | 2,Puppy,./Images/Image_Class/Puppy/Dog_5.jpg, 3 | 1,Kitten,./Images/Image_Class/Kitten/Cat_12.jpg, 4 | 1,Kitten,./Images/Image_Class/Kitten/Cat_4.jpg, 5 | 2,Puppy,./Images/Image_Class/Puppy/Dog_3.jpg, 6 | 2,Puppy,./Images/Image_Class/Puppy/Dog_13.jpg, 7 | 1,Kitten,./Images/Image_Class/Kitten/Cat_5.jpg, 8 | 2,Puppy,./Images/Image_Class/Puppy/Dog_7.jpg, 9 | 1,Kitten,./Images/Image_Class/Kitten/Cat_13.jpg, 10 | 2,Puppy,./Images/Image_Class/Puppy/Dog_19.jpg, 11 | 1,Kitten,./Images/Image_Class/Kitten/Cat_10.jpg, 12 | 1,Kitten,./Images/Image_Class/Kitten/Cat_3.jpg, 13 | 1,Kitten,./Images/Image_Class/Kitten/Cat_1.jpg, 14 | 1,Kitten,./Images/Image_Class/Kitten/Cat_11.jpg, 15 | 2,Puppy,./Images/Image_Class/Puppy/Dog_14.jpg, 16 | 1,Kitten,./Images/Image_Class/Kitten/Cat_14.jpg, 17 | 1,Kitten,./Images/Image_Class/Kitten/Cat_2.jpg, 18 | 2,Puppy,./Images/Image_Class/Puppy/Dog_12.jpg, 19 | 1,Kitten,./Images/Image_Class/Kitten/Cat_9.jpg, 20 | 2,Puppy,./Images/Image_Class/Puppy/Dog_6.jpg, 21 | 2,Puppy,./Images/Image_Class/Puppy/Dog_11.jpg, 22 | 2,Puppy,./Images/Image_Class/Puppy/Dog_4.jpg, 23 | 3,Test,./Images/Image_Class/Puppy/Dog_7.jpg, 24 | 1,Kitten,./Images/Image_Class/Kitten/Cat_5.jpg, 25 | 1,Kitten,./Images/Image_Class/Kitten/Cat_10.jpg, 26 | 2,Puppy,./Images/Image_Class/Puppy/Dog_4.jpg, 27 | 1,Kitten,./Images/Image_Class/Kitten/Cat_13.jpg, 28 | 2,Puppy,./Images/Image_Class/Puppy/Dog_14.jpg, 29 | 1,Kitten,./Images/Image_Class/Kitten/Cat_14.jpg, 30 | 2,Puppy,./Images/Image_Class/Puppy/Dog_12.jpg, 31 | 2,Puppy,./Images/Image_Class/Puppy/Dog_3.jpg, 32 | 2,Puppy,./Images/Image_Class/Puppy/Dog_19.jpg, 33 | 2,Puppy,./Images/Image_Class/Puppy/Dog_7.jpg, 34 | 1,Kitten,./Images/Image_Class/Kitten/Cat_1.jpg, 35 | 2,Puppy,./Images/Image_Class/Puppy/Dog_11.jpg, 36 | 2,Puppy,./Images/Image_Class/Puppy/Dog_5.jpg, 37 | 1,Kitten,./Images/Image_Class/Kitten/Cat_11.jpg, 38 | 1,Kitten,./Images/Image_Class/Kitten/Cat_3.jpg, 39 | 2,Puppy,./Images/Image_Class/Puppy/Dog_6.jpg, 40 | 1,Kitten,./Images/Image_Class/Kitten/Cat_12.jpg, 41 | 2,Puppy,./Images/Image_Class/Puppy/Dog_2.jpg, 42 | 2,Puppy,./Images/Image_Class/Puppy/Dog_13.jpg, 43 | 1,Kitten,./Images/Image_Class/Kitten/Cat_4.jpg, 44 | 1,Kitten,./Images/Image_Class/Kitten/Cat_2.jpg, 45 | 1,Kitten,./Images/Image_Class/Kitten/Cat_9.jpg, 46 | 3,Test,./Images/Image_Class/Puppy/Dog_7.jpg, 47 | 2,Puppy,./Images/Image_Class/Puppy/Dog_7.jpg, 48 | 2,Puppy,./Images/Image_Class/Puppy/Dog_19.jpg, 49 | 1,Kitten,./Images/Image_Class/Kitten/Cat_10.jpg, 50 | 2,Puppy,./Images/Image_Class/Puppy/Dog_14.jpg, 51 | 2,Puppy,./Images/Image_Class/Puppy/Dog_3.jpg, 52 | 2,Puppy,./Images/Image_Class/Puppy/Dog_13.jpg, 53 | 1,Kitten,./Images/Image_Class/Kitten/Cat_4.jpg, 54 | 1,Kitten,./Images/Image_Class/Kitten/Cat_3.jpg, 55 | 1,Kitten,./Images/Image_Class/Kitten/Cat_5.jpg, 56 | 2,Puppy,./Images/Image_Class/Puppy/Dog_11.jpg, 57 | 1,Kitten,./Images/Image_Class/Kitten/Cat_14.jpg, 58 | 1,Kitten,./Images/Image_Class/Kitten/Cat_11.jpg, 59 | 1,Kitten,./Images/Image_Class/Kitten/Cat_9.jpg, 60 | 1,Kitten,./Images/Image_Class/Kitten/Cat_2.jpg, 61 | 1,Kitten,./Images/Image_Class/Kitten/Cat_1.jpg, 62 | 2,Puppy,./Images/Image_Class/Puppy/Dog_5.jpg, 63 | 1,Kitten,./Images/Image_Class/Kitten/Cat_13.jpg, 64 | 2,Puppy,./Images/Image_Class/Puppy/Dog_4.jpg, 65 | 2,Puppy,./Images/Image_Class/Puppy/Dog_12.jpg, 66 | 1,Kitten,./Images/Image_Class/Kitten/Cat_12.jpg, 67 | 2,Puppy,./Images/Image_Class/Puppy/Dog_6.jpg, 68 | 2,Puppy,./Images/Image_Class/Puppy/Dog_2.jpg, 69 | 3,Test,./Images/Image_Class/Puppy/Dog_7.jpg, 70 | 2,Puppy,./Images/Image_Class/Puppy/Dog_14.jpg, 71 | 2,Puppy,./Images/Image_Class/Puppy/Dog_19.jpg, 72 | 1,Kitten,./Images/Image_Class/Kitten/Cat_9.jpg, 73 | 1,Kitten,./Images/Image_Class/Kitten/Cat_3.jpg, 74 | 1,Kitten,./Images/Image_Class/Kitten/Cat_11.jpg, 75 | 1,Kitten,./Images/Image_Class/Kitten/Cat_2.jpg, 76 | 2,Puppy,./Images/Image_Class/Puppy/Dog_4.jpg, 77 | 1,Kitten,./Images/Image_Class/Kitten/Cat_12.jpg, 78 | 2,Puppy,./Images/Image_Class/Puppy/Dog_12.jpg, 79 | 2,Puppy,./Images/Image_Class/Puppy/Dog_5.jpg, 80 | 2,Puppy,./Images/Image_Class/Puppy/Dog_11.jpg, 81 | 2,Puppy,./Images/Image_Class/Puppy/Dog_6.jpg, 82 | 1,Kitten,./Images/Image_Class/Kitten/Cat_13.jpg, 83 | 1,Kitten,./Images/Image_Class/Kitten/Cat_10.jpg, 84 | 2,Puppy,./Images/Image_Class/Puppy/Dog_3.jpg, 85 | 1,Kitten,./Images/Image_Class/Kitten/Cat_1.jpg, 86 | 1,Kitten,./Images/Image_Class/Kitten/Cat_14.jpg, 87 | 1,Kitten,./Images/Image_Class/Kitten/Cat_4.jpg, 88 | 1,Kitten,./Images/Image_Class/Kitten/Cat_5.jpg, 89 | 2,Puppy,./Images/Image_Class/Puppy/Dog_2.jpg, 90 | 2,Puppy,./Images/Image_Class/Puppy/Dog_7.jpg, 91 | 2,Puppy,./Images/Image_Class/Puppy/Dog_13.jpg, 92 | 3,Test,./Images/Image_Class/Puppy/Dog_7.jpg, 93 | -------------------------------------------------------------------------------- /External_Trigger/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "image_base_path": "./Images/", 3 | "image_types": ["Kitten", "Puppy"], 4 | "video_time": 3000, 5 | "trigger_interval": 100, 6 | "flick_times": 5, 7 | "fps": 20, 8 | "screen_size": [1920, 1080], 9 | "time_range_per_image": 0.2, 10 | "video_output": "video.mp4", 11 | "label_output": "labels.txt", 12 | "trigger_position": [0, 830, 100, 930] 13 | } 14 | -------------------------------------------------------------------------------- /External_Trigger/test.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenBCI/OpenBCI_Tutorials/a9d60c75e8606a8a412a12bb0aa7c54b154a10d8/External_Trigger/test.jpg -------------------------------------------------------------------------------- /External_Trigger/video.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenBCI/OpenBCI_Tutorials/a9d60c75e8606a8a412a12bb0aa7c54b154a10d8/External_Trigger/video.mp4 -------------------------------------------------------------------------------- /External_Trigger/video_picture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenBCI/OpenBCI_Tutorials/a9d60c75e8606a8a412a12bb0aa7c54b154a10d8/External_Trigger/video_picture.png -------------------------------------------------------------------------------- /Facial_EMG/Arduino_Code/Arduino_Code.ino: -------------------------------------------------------------------------------- 1 | /* Code to turn the RGB components of an RGB LED on or off depending on received serial commands. Modified from Arduino examples. */ 2 | 3 | int incomingByte; // variable to read serial data into 4 | 5 | int redPin = 12; 6 | int greenPin = 8; 7 | int bluePin = 11; 8 | 9 | #define COMMON_ANODE // uncomment this line if using a common anode 10 | 11 | void setup() { 12 | 13 | // initialize serial communication 14 | Serial.begin(9600); 15 | 16 | // set LED pins as outputs 17 | pinMode(redPin, OUTPUT); 18 | pinMode(greenPin, OUTPUT); 19 | pinMode(bluePin, OUTPUT); 20 | 21 | setColor(0, 0, 255); // initialize to blue 22 | } 23 | 24 | void loop() { 25 | 26 | // check if there's incoming data 27 | if (Serial.available() > 0) { 28 | 29 | // read the oldest byte in the buffer: 30 | incomingByte = Serial.read(); 31 | 32 | if (incomingByte == 'G') { 33 | setColor(0, 255, 0); // green 34 | } 35 | 36 | if (incomingByte == 'R') { 37 | setColor(255, 0, 0); // red 38 | } 39 | 40 | if (incomingByte == 'B') { 41 | setColor(0, 0, 255); // blue 42 | } 43 | } 44 | } 45 | 46 | /* Function to set the color of the LED*/ 47 | void setColor(int red, int green, int blue) 48 | { 49 | #ifdef COMMON_ANODE // if the LED has a common anode we must drive the pins to GND to create the voltage difference that lights it up 50 | red = 255 - red; 51 | green = 255 - green; 52 | blue = 255 - blue; 53 | #endif 54 | 55 | analogWrite(redPin, red); 56 | analogWrite(greenPin, green); 57 | analogWrite(bluePin, blue); 58 | } 59 | -------------------------------------------------------------------------------- /Facial_EMG/LSL_Stream_Facial_One_LED.py: -------------------------------------------------------------------------------- 1 | """Code modified from the example program to show how to read a multi-channel time series from LSL at https://github.com/OpenBCI/OpenBCI_GUI/blob/master/Networking-Test-Kit/LSL/lslStreamTest.py.""" 2 | 3 | from pylsl import StreamInlet, resolve_byprop 4 | import time 5 | import serial 6 | 7 | # set up Arduino serial port - replace with the one you are using 8 | ser = serial.Serial('COM4', 9600) 9 | 10 | # resolve an EMG stream on the lab network and notify the user 11 | print("Looking for an EMG stream...") 12 | streams = resolve_byprop('type', 'EEG') 13 | inlet = StreamInlet(streams[0]) 14 | #inlet_ch2 = StreamInlet(streams[1]) 15 | print("EMG stream found!") 16 | 17 | # initialize time threshold and variables for storing time 18 | thres = 500 19 | prev_time = 0 20 | 21 | while True: 22 | 23 | samples, timestamp = inlet.pull_sample() # get EMG data sample and its timestamp 24 | 25 | curr_time = int(round(time.time() * 1000)) # get current time in milliseconds 26 | 27 | 28 | if ((samples[0] >= 0.7) & (curr_time - thres > prev_time)): # if an EMG spike is detected from the cheek muscles send 'G' 29 | prev_time = int(round(time.time() * 1000)) # update time 30 | ser.write(b'G') 31 | 32 | 33 | elif((samples[1] >= 0.7) & (curr_time - thres > prev_time)): # if an EMG spike is detected from the eyebrow muscles send 'R' 34 | prev_time = int(round(time.time() * 1000)) # update time 35 | ser.write(b'R') 36 | 37 | elif(curr_time - thres > prev_time): # if no spike is detected send 'B' 38 | prev_time = int(round(time.time() * 1000)) # update time 39 | ser.write(b'B') 40 | -------------------------------------------------------------------------------- /Facial_EMG_Multiple_LEDs/Arduino_Code/Arduino_Code.ino: -------------------------------------------------------------------------------- 1 | /* Code to turn the LEDS on or off depending on received serial commands. Modified from Arduino examples. */ 2 | 3 | int incomingByte; // variable to read serial data into 4 | 5 | int redPin = 12; 6 | int yellowPin = 8; 7 | int bluePin = 11; 8 | 9 | void setup() { 10 | 11 | // initialize serial communication 12 | Serial.begin(9600); 13 | 14 | // set LED pins as outputs 15 | pinMode(redPin, OUTPUT); 16 | pinMode(yellowPin, OUTPUT); 17 | pinMode(bluePin, OUTPUT); 18 | 19 | digitalWrite(bluePin, HIGH); // initialize to blue 20 | } 21 | 22 | void loop() { 23 | 24 | // check if there's incoming data 25 | if (Serial.available() > 0) { 26 | 27 | // read the oldest byte in the buffer: 28 | incomingByte = Serial.read(); 29 | 30 | if (incomingByte == 'Y') { 31 | digitalWrite(yellowPin, HIGH); // yellow 32 | digitalWrite(redPin, LOW); 33 | digitalWrite(bluePin, LOW); 34 | } 35 | 36 | if (incomingByte == 'R') { 37 | digitalWrite(redPin, HIGH); // red 38 | digitalWrite(bluePin, LOW); 39 | digitalWrite(yellowPin, LOW); 40 | } 41 | 42 | if (incomingByte == 'B') { 43 | digitalWrite(bluePin, HIGH); // blue 44 | digitalWrite(redPin, LOW); 45 | digitalWrite(yellowPin, LOW); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Facial_EMG_Multiple_LEDs/LSL_Stream_Facial_Multiple_LEDs.py: -------------------------------------------------------------------------------- 1 | """Code modified from the example program to show how to read a multi-channel time series from LSL at https://github.com/OpenBCI/OpenBCI_GUI/blob/master/Networking-Test-Kit/LSL/lslStreamTest.py.""" 2 | 3 | from pylsl import StreamInlet, resolve_byprop 4 | import time 5 | import serial 6 | 7 | # set up Arduino serial port - replace with the one you are using 8 | ser = serial.Serial('COM4', 9600) 9 | 10 | # resolve an EMG stream on the lab network and notify the user 11 | print("Looking for an EMG stream...") 12 | streams = resolve_byprop('type', 'EEG') 13 | inlet = StreamInlet(streams[0]) 14 | #inlet_ch2 = StreamInlet(streams[1]) 15 | print("EMG stream found!") 16 | 17 | # initialize time threshold and variables for storing time 18 | time_thres = 500 19 | prev_time = 0 20 | flex_thres = 0.7 21 | 22 | while True: 23 | 24 | samples, timestamp = inlet.pull_sample() # get EMG data sample and its timestamp 25 | 26 | curr_time = int(round(time.time() * 1000)) # get current time in milliseconds 27 | 28 | 29 | if ((samples[0] >= flex_thres) & (curr_time - time_thres > prev_time)): # if an EMG spike is detected from the cheek muscles send 'G' 30 | prev_time = int(round(time.time() * 1000)) # update time 31 | ser.write(b'Y') 32 | 33 | 34 | elif((samples[1] >= flex_thres) & (curr_time - time_thres > prev_time)): # if an EMG spike is detected from the eyebrow muscles send 'R' 35 | prev_time = int(round(time.time() * 1000)) # update time 36 | ser.write(b'R') 37 | 38 | elif(curr_time - time_thres > prev_time): # if no spike is detected send 'B' 39 | prev_time = int(round(time.time() * 1000)) # update time 40 | ser.write(b'B') 41 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /Motor_Imagery/mental_imagery.ino: -------------------------------------------------------------------------------- 1 | // Code written by Rakesh C Jakati for the Motor Imagery tutorial 2 | 3 | //Settings 4 | #define WIFI_SSID "**YOUR SSID**" 5 | #define WIFI_PASSWORD "**YOUR PASSWORD**" 6 | #define LISTEN_PORT 9002 7 | #define TIMEOUT_MILLIS 5000 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | 17 | /* define L298N or L293D motor control pins */ 18 | int leftMotorForward = 2; /* GPIO2(D4) -> IN3 */ 19 | int rightMotorForward = 15; /* GPIO15(D8) -> IN1 */ 20 | int leftMotorBackward = 0; /* GPIO0(D3) -> IN4 */ 21 | int rightMotorBackward = 13; /* GPIO13(D7) -> IN2 */ 22 | 23 | /* define L298N or L293D enable pins */ 24 | int rightMotorENB = 14; /* GPIO14(D5) -> Motor-A Enable */ 25 | int leftMotorENB = 12; /* GPIO12(D6) -> Motor-B Enable */ 26 | 27 | 28 | WiFiUDP Udp; 29 | 30 | long timeoutTargetMS = 0; 31 | 32 | 33 | void setup() { 34 | Serial.begin(115200); 35 | Serial.println("\n\nESP Booted."); 36 | setupWifi(); 37 | /* initialize motor control pins as output */ 38 | pinMode(leftMotorForward, OUTPUT); 39 | pinMode(rightMotorForward, OUTPUT); 40 | pinMode(leftMotorBackward, OUTPUT); 41 | pinMode(rightMotorBackward, OUTPUT); 42 | 43 | /* initialize motor enable pins as output */ 44 | pinMode(leftMotorENB, OUTPUT); 45 | pinMode(rightMotorENB, OUTPUT); 46 | 47 | } 48 | 49 | 50 | String localIP(){ 51 | IPAddress ip; 52 | if (WIFI_SSID==""){ 53 | ip = WiFi.softAPIP(); 54 | } else { 55 | ip = WiFi.localIP(); 56 | } 57 | String sip = String(ip[0]); 58 | sip += ".";sip += ip[1]; 59 | sip += ".";sip += ip[2]; 60 | sip += ".";sip += ip[3]; 61 | return(sip); 62 | } 63 | 64 | void setupWifi(){ 65 | WiFi.mode(WIFI_STA); 66 | WiFi.disconnect(); 67 | delay(100); 68 | Serial.println(WIFI_SSID); 69 | WiFi.begin(WIFI_SSID, WIFI_PASSWORD); 70 | while (WiFi.status() != WL_CONNECTED) { 71 | delay(500); 72 | yield(); 73 | Serial.print("."); 74 | } 75 | Serial.println(localIP()); 76 | Udp.begin(LISTEN_PORT); 77 | } 78 | 79 | 80 | /********************************************* FORWARD *****************************************************/ 81 | void MotorForward(void) 82 | { 83 | digitalWrite(leftMotorENB,HIGH); 84 | digitalWrite(rightMotorENB,HIGH); 85 | digitalWrite(leftMotorForward,HIGH); 86 | digitalWrite(rightMotorForward,HIGH); 87 | digitalWrite(leftMotorBackward,LOW); 88 | digitalWrite(rightMotorBackward,LOW); 89 | } 90 | 91 | /********************************************* BACKWARD *****************************************************/ 92 | void MotorBackward(void) 93 | { 94 | digitalWrite(leftMotorENB,HIGH); 95 | digitalWrite(rightMotorENB,HIGH); 96 | digitalWrite(leftMotorBackward,HIGH); 97 | digitalWrite(rightMotorBackward,HIGH); 98 | digitalWrite(leftMotorForward,LOW); 99 | digitalWrite(rightMotorForward,LOW); 100 | } 101 | 102 | /********************************************* TURN LEFT *****************************************************/ 103 | void TurnLeft(void) 104 | { 105 | digitalWrite(leftMotorENB,HIGH); 106 | digitalWrite(rightMotorENB,HIGH); 107 | digitalWrite(leftMotorForward,LOW); 108 | digitalWrite(rightMotorForward,HIGH); 109 | digitalWrite(rightMotorBackward,LOW); 110 | digitalWrite(leftMotorBackward,HIGH); 111 | } 112 | 113 | /********************************************* TURN RIGHT *****************************************************/ 114 | void TurnRight(void) 115 | { 116 | digitalWrite(leftMotorENB,HIGH); 117 | digitalWrite(rightMotorENB,HIGH); 118 | digitalWrite(leftMotorForward,HIGH); 119 | digitalWrite(rightMotorForward,LOW); 120 | digitalWrite(rightMotorBackward,HIGH); 121 | digitalWrite(leftMotorBackward,LOW); 122 | } 123 | 124 | /********************************************* STOP *****************************************************/ 125 | void MotorStop(void) 126 | { 127 | digitalWrite(leftMotorENB,LOW); 128 | digitalWrite(rightMotorENB,LOW); 129 | digitalWrite(leftMotorForward,LOW); 130 | digitalWrite(leftMotorBackward,LOW); 131 | digitalWrite(rightMotorForward,LOW); 132 | digitalWrite(rightMotorBackward,LOW); 133 | } 134 | 135 | //OSC from Neuromore 136 | void mentalImagery(OSCMessage &msg) { 137 | float right_prediction = msg.getFloat(0); 138 | float left_prediction = msg.getFloat(1); 139 | Serial.println(right_prediction); 140 | if (left_prediction > 0.6) { 141 | TurnLeft(); 142 | } 143 | else if (right_prediction > 0.6){ 144 | TurnRight(); 145 | } 146 | else{ 147 | MotorStop(); 148 | } 149 | } 150 | 151 | void loop() { 152 | OSCBundle bundle; 153 | int size = Udp.parsePacket(); 154 | if (size > 0) { 155 | while (size--) { 156 | bundle.fill(Udp.read()); 157 | } 158 | 159 | if (!bundle.hasError()) { 160 | bundle.dispatch("/neuropype", mentalImagery); 161 | } 162 | 163 | //Reset timeout 164 | timeoutTargetMS = millis() + TIMEOUT_MILLIS; 165 | } 166 | } 167 | -------------------------------------------------------------------------------- /Motor_Imagery/neuropype_recieve.py: -------------------------------------------------------------------------------- 1 | # Code written by Rakesh C Jakati for the Motor Imagery tutorial 2 | 3 | from oscpy.server import OSCThreadServer 4 | from time import sleep 5 | from oscpy.client import OSCClient 6 | 7 | osc = OSCThreadServer() 8 | sock = osc.listen(address='127.0.0.1', port=9002, default=True) 9 | @osc.address(b'/neuropype') 10 | def callback(left, right): 11 | print("Left prediction : ",round(left,2),"Right prediction : ",round(right,2)) 12 | sleep(100) 13 | 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OpenBCI_Tutorials 2 | 3 | Compilation of tutorials using OpenBCI equipment under MIT License. 4 | --------------------------------------------------------------------------------