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

Update terms to glossary #121

Merged
merged 2 commits into from
Jan 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 23 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

### What is it?

It is Brain-computer interface software written in Python. It can function as a standalone or you can take the tools you need and start coding your own system.
It is Brain-computer interface software written in Python. It can function as a standalone or you can take the tools you need and start coding your own system. See our official BciPy documentation including affliations and more context information here: https://bcipy.github.io/ (in progress).

It should, based on our dependencies, work on most recent operating systems, however it has only been verified on Windows (7 & 10 Pro) and Mac OSx (High Sierra & Mojave) at this time. It won't build as is on Linux. Some additional work will be needed to install WxPython and pylsl.

Expand Down Expand Up @@ -60,7 +60,7 @@ To use all the goodies locally (including the GUI and demo scripts)
If wanting the latest version from PyPi:
1. `pip install bcipy`

Alternatley, if [Make](http://www.mingw.org/) is installed, you may run the follow command to run install:
Alternatley, if [Make](http://www.mingw.org/) is installed, you may run the follow command to install:

```sh
# install in development mode
Expand All @@ -71,7 +71,7 @@ make dev-install

Start by running `python bcipy/gui/BCInterface.py` in your command prompt or terminal. You may also invoke the experiment directly using command line tools for bci_main.py.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make sense to create a make command for this as well?


Ex.`python bci_main.py` *this will use default parameters, user, experiment and task*
Ex. `python bci_main.py` *this will use default parameters, user, experiment and task*

You can pass it attributes with flags, if desired.

Expand All @@ -94,7 +94,7 @@ This a list of the major modules and their functionality. Each module will conta
- `acquisition`: acquires data, gives back desired time series, saves to file at end of session.
- `display`: handles display of stimuli on screen and passes back stimuli timing.
- `signal`: eeg signal models, filters, processing, evaluators and viewers.
- `gui`: end-user interfaces which allow running of registered bci experiments, field collection and parameter editing.
- `gui`: end-user interface into registered bci tasks and parameter editing. See BCInterface.py.
- `helpers`: helpful functions needed for interactions between modules, basic I/O, and data visualization.
- `language_model`: gives probabilities of next letters during typing.
- `parameters`: location of json parameters.
Expand Down Expand Up @@ -166,7 +166,7 @@ coverage report
coverage html
```

Alternatley, if Make is installed, you may run the follow command to run coverage and generate the html:
Alternatley, if Make is installed, you may run the follow command to run coverage/pytest and generate the html:

```sh
make coverage-html
Expand Down Expand Up @@ -194,16 +194,29 @@ Alternatley, if Make is installed, you may run the follow command to run autopep
make lint
```

## Glossary
-----------

***Stimuli***: A single letter, tone or image shown (generally in an inquiry). Singular = stimulus, plural = stimuli.

***Trial***: A collection of data after a stimuli is shown. A----

***Inquiry***: The set of stimuli after a fixation cross in a spelling task to gather user intent. A ---- B --- C ----

***Series***: Each series contains at least one inquiry. A letter/icon decision is made after a series in a spelling task.


## Authorship
--------------

- Tab Memmott (OHSU)
- Matthew Lawhead (OHSU)
- Aziz Kocanaogullari (NEU)
- Matthew Lawhead (OHSU- OCTRI)
- Berkan Kadioglu (NEU)
- Shiran Dudy (OHSU)
- Dani Smektala (OHSU)
- Ian Jackson (OHSU/ Reed)
- Ian Jackson (Reed)
- Alister Cedeño (OHSU)
- Berkan Kadioglu (NEU)
- Basak Celik (NEU)
- Andac Demir (NEU)
- Shaobin Xu (NEU)
- Shiran Dudy (OHSU)
- Basak Celik (NEU)
2 changes: 1 addition & 1 deletion bci_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ def _clean_up_session(display, daq, server):
# Close the display window
# NOTE: There is currently a bug in psychopy when attempting to shutdown
# windows when using a USB-C monitor. Putting the display close last in
# the sequence allows acquisition to properly shutdown.
# the inquiry allows acquisition to properly shutdown.
display.close()

return True
Expand Down
2 changes: 1 addition & 1 deletion bcipy/acquisition/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ Sampling frequency of the hardware in Hz. Default value = 256
Downsampling order. Default value = 2
#### Usage:

Pass an input eeg np.array that is a matrix where every row is a channels data. For example a two channel EEG sequence could be:
Pass an input eeg np.array that is a matrix where every row is a channels data. For example a two channel EEG inquiry could be:

```python
input_seq = np.array([[1, 4, ...],
Expand Down
8 changes: 4 additions & 4 deletions bcipy/display/matrix/display.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@


class MatrixDisplay:
""" Matrix Display Object for Sequence Presentation. Animates a sequence
""" Matrix Display Object for inquiry Presentation. Animates a inquiry
in Matrix. Mode should be determined outside.
Attr:
task(visual_Text_Stimuli): task bar
Expand Down Expand Up @@ -124,8 +124,8 @@ def make_spelling_grid(self):
stim.draw()
self.stimuli.append(stim)

def do_sequence(self):
""" implements grid sequence """
def do_inquiry(self):
""" implements grid inquiry """

# Stimulate rows
for x in self.uniform_grid_values_row:
Expand Down Expand Up @@ -202,6 +202,6 @@ def determine_position_on_grid(row_idx, col_idx,
matrix.draw_static()

# animate!
matrix.do_sequence()
matrix.do_inquiry()

time.sleep(2)
10 changes: 5 additions & 5 deletions bcipy/display/rsvp/demo/demo_calibration_rsvp.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@
stim_font=font_sti,
stim_pos=pos_sti,
stim_height=sti_height,
stim_sequence=['a'] * 10,
stim_inquiry=['a'] * 10,
stim_colors=['white'] * 10,
stim_timing=[3] * 10,
is_txt_stim=is_txt_stim)
Expand All @@ -95,18 +95,18 @@
win.flip()
rsvp.sti.height = sti_height

# Schedule a sequence
rsvp.stimuli_sequence = ele_sti[idx_o]
# Schedule a inquiry
rsvp.stimuli_inquiry = ele_sti[idx_o]

if is_txt_stim:
rsvp.stimuli_colors = color_sti[idx_o]

rsvp.stimuli_timing = timing_sti[idx_o]

core.wait(.4)
sequence_timing = rsvp.do_sequence()
inquiry_timing = rsvp.do_inquiry()

# _write_triggers_from_sequence_calibration(sequence_timing, trigger_file)
# _write_triggers_from_inquiry_calibration(inquiry_timing, trigger_file)

core.wait(.5)

Expand Down
14 changes: 7 additions & 7 deletions bcipy/display/rsvp/demo/demo_copyphrase_rsvp.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@
task_height=height_task,
stim_font=font_sti, stim_pos=pos_sti,
stim_height=sti_height,
stim_sequence=['a'] * 10, stim_colors=['white'] * 10,
stim_inquiry=['a'] * 10, stim_colors=['white'] * 10,
stim_timing=[3] * 10,
is_txt_stim=is_txt_stim)

Expand All @@ -98,29 +98,29 @@
rsvp.sti.height = sti_height

for idx in range(int(len(ele_sti) / 2)):
# Schedule a sequence
rsvp.stimuli_sequence = ele_sti[counter]
# Schedule a inquiry
rsvp.stimuli_inquiry = ele_sti[counter]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good change to keep it clean start with definition

if is_txt_stim:
rsvp.stimuli_colors = color_sti[counter]

rsvp.stimuli_timing = timing_sti[counter]

#
core.wait(.4)
sequence_timing = rsvp.do_sequence()
inquiry_timing = rsvp.do_inquiry()

# _write_triggers_from_sequence_copy_phrase(sequence_timing,
# _write_triggers_from_inquiry_copy_phrase(inquiry_timing,
# trigger_file, text_task,
# task_text[idx_o])

core.wait(.5)
counter += 1

# Get stimuli parameters
rsvp.stim_sequence = ele_list_dec[idx_o]
rsvp.stim_inquiry = ele_list_dec[idx_o]
rsvp.color_list_sti = ['green']
rsvp.time_list_sti = [2]
rsvp.do_sequence()
rsvp.do_inquiry()

win.close()
# trigger_file.close()
Expand Down
56 changes: 28 additions & 28 deletions bcipy/display/rsvp/display.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@


class RSVPDisplay(object):
"""RSVP Display Object for Sequence Presentation.
"""RSVP Display Object for inquiry Presentation.

Animates a sequence in RSVP. Mode should be determined outside.
Animates a inquiry in RSVP. Mode should be determined outside.
"""

def __init__(
Expand All @@ -36,7 +36,7 @@ def __init__(
stim_font='Times',
stim_pos=(-.8, .9),
stim_height=0.2,
stim_sequence: List[str] = ['a'] * 10,
stim_inquiry: List[str] = ['a'] * 10,
stim_colors: List[str] = ['white'] * 10,
stim_timing: List[float] = [1] * 10,
is_txt_stim: bool = True,
Expand Down Expand Up @@ -74,7 +74,7 @@ def __init__(
stim_height(float): height of the stimuli object
stim_pos(tuple): position of stimuli
stim_font(string): font of the stimuli
stim_sequence(list[string]): list of elements to flash
stim_inquiry(list[string]): list of elements to flash
stim_colors(list[string]): list of colors for stimuli
stim_timing(list[float]): timing for each letter flash
"""
Expand All @@ -83,7 +83,7 @@ def __init__(

self.logger = logging.getLogger(__name__)

self.stimuli_sequence = stim_sequence
self.stimuli_inquiry = stim_inquiry
self.stimuli_colors = stim_colors
self.stimuli_timing = stim_timing

Expand All @@ -97,7 +97,7 @@ def __init__(
self.marker_writer = marker_writer or NullMarkerWriter()

# Length of the stimuli (number of flashes)
self.stim_length = len(stim_sequence)
self.stim_length = len(stim_inquiry)

# Informational Parameters
self.info_text = info_text
Expand Down Expand Up @@ -171,7 +171,7 @@ def schedule_to(self, ele_list=[], time_list=[], color_list=[]):
time_list(list[float]): list of timings of stimuli
color_list(list[string]): colors of elements of stimuli
"""
self.stimuli_sequence = ele_list
self.stimuli_inquiry = ele_list
self.stimuli_timing = time_list
self.stimuli_colors = color_list

Expand All @@ -188,17 +188,17 @@ def update_task(self, text: str, color_list: List[str], pos: Tuple[float]):
self.task.color = color_list[0]
self.task.pos = pos

def do_sequence(self):
"""Do Sequence.
def do_inquiry(self):
"""Do inquiry.

Animates a sequence of flashing letters to achieve RSVP.
Animates a inquiry of flashing letters to achieve RSVP.
"""

# init an array for timing information
timing = []

if self.first_run:
# play a sequence start sound to help orient triggers
# play a inquiry start sound to help orient triggers
first_stim_timing = _calibration_trigger(
self.experiment_clock,
trigger_type=self.trigger_type, display=self.window,
Expand All @@ -209,11 +209,11 @@ def do_sequence(self):
self.first_stim_time = first_stim_timing[-1]
self.first_run = False

# generate a sequence (list of stimuli with meta information)
sequence = self._generate_sequence()
# generate a inquiry (list of stimuli with meta information)
inquiry = self._generate_inquiry()

# do the sequence
for idx in range(len(sequence)):
# do the inquiry
for idx in range(len(inquiry)):

self.is_first_stim = (idx == 0)

Expand All @@ -226,17 +226,17 @@ def do_sequence(self):
self.window.callOnFlip(
self.trigger_callback.callback,
self.experiment_clock,
sequence[idx]['sti_label'])
self.window.callOnFlip(self.marker_writer.push_marker, sequence[idx]['sti_label'])
inquiry[idx]['sti_label'])
self.window.callOnFlip(self.marker_writer.push_marker, inquiry[idx]['sti_label'])

if idx == 0 and callable(self.first_stim_callback):
self.first_stim_callback(sequence[idx]['sti'])
self.first_stim_callback(inquiry[idx]['sti'])

# Draw stimulus for n frames
sequence[idx]['sti'].draw()
inquiry[idx]['sti'].draw()
self.draw_static()
self.window.flip()
core.wait((sequence[idx]['time_to_present'] - 1) / self.refresh_rate)
core.wait((inquiry[idx]['time_to_present'] - 1) / self.refresh_rate)

# End static period
self.staticPeriod.complete()
Expand All @@ -255,13 +255,13 @@ def do_sequence(self):

return timing

def _generate_sequence(self):
"""Generate Sequence.
def _generate_inquiry(self):
"""Generate inquiry.

Generate stimuli for next RSVP sequence.
Generate stimuli for next RSVP inquiry.
"""
stim_info = []
for idx in range(len(self.stimuli_sequence)):
for idx in range(len(self.stimuli_inquiry)):
current_stim = {}

# turn ms timing into frames! Much more accurate!
Expand All @@ -274,17 +274,17 @@ def _generate_sequence(self):
this_stimuli_size = self.stimuli_height

# Set the Stimuli attrs
if self.stimuli_sequence[idx].endswith('.png'):
if self.stimuli_inquiry[idx].endswith('.png'):
current_stim['sti'] = self.create_stimulus(mode='image', height_int=this_stimuli_size)
current_stim['sti'].image = self.stimuli_sequence[idx]
current_stim['sti'].image = self.stimuli_inquiry[idx]
current_stim['sti'].size = resize_image(
current_stim['sti'].image, current_stim['sti'].win.size, this_stimuli_size)
current_stim['sti_label'] = path.splitext(
path.basename(self.stimuli_sequence[idx]))[0]
path.basename(self.stimuli_inquiry[idx]))[0]
else:
# text stimulus
current_stim['sti'] = self.create_stimulus(mode='text', height_int=this_stimuli_size)
txt = self.stimuli_sequence[idx]
txt = self.stimuli_inquiry[idx]
# customize presentation of space char.
current_stim['sti'].text = txt if txt != SPACE_CHAR else self.space_char
current_stim['sti'].color = self.stimuli_colors[idx]
Expand Down
4 changes: 2 additions & 2 deletions bcipy/display/rsvp/mode/calibration.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def __init__(self,
stim_font='Times',
stim_pos=(-.8, .9),
stim_height=0.2,
stim_sequence=['a'] * 10,
stim_inquiry=['a'] * 10,
stim_colors=['white'] * 10,
stim_timing=[1] * 10,
is_txt_stim=True,
Expand Down Expand Up @@ -57,7 +57,7 @@ def __init__(self,
stim_font=stim_font,
stim_pos=stim_pos,
stim_height=stim_height,
stim_sequence=stim_sequence,
stim_inquiry=stim_inquiry,
stim_colors=stim_colors,
stim_timing=stim_timing,
is_txt_stim=is_txt_stim,
Expand Down
4 changes: 2 additions & 2 deletions bcipy/display/rsvp/mode/copy_phrase.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def __init__(
stim_font='Times',
stim_pos=(-.8, .9),
stim_height=0.2,
stim_sequence=['a'] * 10,
stim_inquiry=['a'] * 10,
stim_colors=['white'] * 10,
stim_timing=[1] * 10,
is_txt_stim=True,
Expand Down Expand Up @@ -83,7 +83,7 @@ def __init__(
stim_font=stim_font,
stim_pos=stim_pos,
stim_height=stim_height,
stim_sequence=stim_sequence,
stim_inquiry=stim_inquiry,
stim_colors=stim_colors,
stim_timing=stim_timing,
is_txt_stim=is_txt_stim,
Expand Down
Loading