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

Simulator fix and orchestrator saving updates #358

Merged
merged 9 commits into from
Oct 30, 2024
51 changes: 41 additions & 10 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,36 +7,68 @@ Our final release candidate before the official 2.0 release!
- Multimodal Acquisition and Querying
- Support for multiple devices in online querying #286
- Support for trigger handling relative to a given device #293
- Session Orchestrator
- New task protocol for orchestrating tasks in a session. This refactors several Task and Cli functionality #339
- Support multiple device static offests #331
- Support for Device Status (passive or active) #310
- Session Orchestrator #339
- New task protocol for orchestrating tasks in a session. This refactors several Task and Cli functionality #339, #343
- Parameter guardrails #340
- Allow multiple phrases in a single protocol to be defined in a phrase.json and randomized #352
- BciPy Client Additions #346
- Other commands added for offline analysis, visualization and simulation.
- Artifact Module #336
- Simulator #350
- Task
- Calibration Task Refactor: pulls out common elements from RSVP and Matrix calibration tasks #330
- Registry Refactor #332
- Inquiry Preview
- Surface button error probability #347
- Add to Matrix #353
- Bugfixes/Refactor #348
- Add more stoppage criteria #351 (max_incorrect)
- Matrix
- Layout Support #349
- Grid always on #313
- Output stimuli position, screen capture and monitor information after Matrix tasks #303
- Row/Column spacing support #298
- VEP Calibration #304/#296
- session data to VEP calibration #322
- Model
- Offline analysis to support multimodal fusion. Initial release of GazeModel, GazeReshaper, and Gaze Visualization #294
- Language Model
- Add Oracle model #316
- Random Uniform model #311
- Stimuli
- Updates to ensure stimuli are presented at the same frequency #287 Output stimuli position, screen capture and monitor information after Matrix tasks #303
- Updates to ensure stimuli are presented at the same frequency #287
- Dynamic Selection Window
- Updated trial_length to trial_window to allow for greater control of window used after stimulus presentations #291
- Report
- Functionality to generate a report in the form of a PDF #325
- Add a BciPy Calbiraiton Report Action #357
- Offset Support
- Add support for determining offsets between timing verification Tasks (Ex. RSVPTimingVerificationCalibration) and RawData with a photodiode trigger column. This is useful for setting up new systems and preventing errors before an experiment begins. #TODO
- Add support for determining offsets between timing verification Tasks (Ex. RSVPTimingVerificationCalibration) and RawData with a photodiode trigger column. This is useful for setting up new systems and preventing errors before an experiment begins. #327
- Parameters
- Add a Range type parameter #285 Add editable fields #340 Update parameters.json to seperate relevant parameters by task
- Housekeeping
- Add mypy typing to the codebase #301
- Change default log level to INFO to prevent too many messages in the experiment logs #288
- Upgrade requirements for m1/2 chips #299/#300
- Fix GitHub actions build issues with macOS
- Fix occasionally failing test in `test_stimuli` #326
- GUI Refactor
- Fix GitHub actions build issues with macOS #324
- Tests Improvements
- Fix occasionally failing test in `test_stimuli` #326
- Reshaper tests #302
- Fix parameter save as #323
- Pause error #321
- Fix data buffer issue #308
- GUI Refactor #337
- Create new `BCIUI` class for simpler more straightforward UI creation.
- Create dedicated external stylesheet for global styling
- Rewrite Experiment Registry to use new GUI code
- Create intertask action UI
- Task Return Object
- Task Return Object #334
- Create `TaskData` dataclass to be returned from tasks
- updates task `execute` methods to return an instance of `TaskData`
- Allows for optional storage of a save path and task dictionary in `TaskData`
-Experiment Refactor
-Experiment Refactor #333 #329
- Refactors the Experiment Field Collection GUI to be an action
- Allows task protocol to be defined in the orchestrator

Expand Down Expand Up @@ -77,7 +109,6 @@ Our final release candidate before the official 2.0 release!
- added KenLM model `kenlm.py` #268
- added mixture model `mixture.py` and script to tune weights `mixture_tuning.py` #268
- added script to evaluate language model performance `lm_eval.py` #268
- added Oracle model #316
- Signal Model
- added `RdaKdeModel` and restructured to pull out common elements from the PcaRdaKdeModel #279
- Bug Fixes
Expand Down
4 changes: 2 additions & 2 deletions bcipy/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@
DEFAULT_USER_ID = 'test_user'
TASK_SEPERATOR = '->'

DEFAULT_PARAMETER_FILENAME = 'parameters.json'
DEFAULT_PARAMETERS_FILENAME = 'parameters.json'
DEFAULT_DEVICES_PATH = f"{BCIPY_ROOT}/parameters"
DEFAULT_PARAMETERS_PATH = f'{BCIPY_ROOT}/parameters/{DEFAULT_PARAMETER_FILENAME}'
DEFAULT_PARAMETERS_PATH = f'{BCIPY_ROOT}/parameters/{DEFAULT_PARAMETERS_FILENAME}'
DEFAULT_DEVICE_SPEC_FILENAME = 'devices.json'
DEVICE_SPEC_PATH = f'{BCIPY_ROOT}/parameters/{DEFAULT_DEVICE_SPEC_FILENAME}'
DEFAULT_LM_PARAMETERS_FILENAME = 'lm_params.json'
Expand Down
2 changes: 0 additions & 2 deletions bcipy/display/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
Display,
InformationProperties,
init_display_window,
PreviewInquiryProperties,
StimuliProperties,
VEPStimuliProperties
)
Expand All @@ -20,5 +19,4 @@
'StimuliProperties',
'VEPStimuliProperties',
'InformationProperties',
'PreviewInquiryProperties'
]
31 changes: 0 additions & 31 deletions bcipy/display/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -251,37 +251,6 @@ class ButtonPressMode(Enum):
REJECT = 2


class PreviewInquiryProperties:
""""Preview Inquiry Properties.
An encapsulation of properties relevant to preview_inquiry() operation.
"""

def __init__(
self,
preview_on: bool,
preview_only: bool,
preview_inquiry_length: float,
preview_inquiry_progress_method: int,
preview_inquiry_key_input: str,
preview_inquiry_isi: float):
"""Initialize Inquiry Preview Parameters.

preview_on(bool): If True, display an inquiry preview before the main inquiry.
preview_only(bool): If True, only preview the inquiry and do not probe for response
preview_inquiry_length(float): Length of time in seconds to present the inquiry preview
preview_inquiry_progress_method(int): Method of progression for inquiry preview.
0 == preview only; 1 == press to accept inquiry; 2 == press to skip inquiry.
preview_inquiry_key_input(str): Defines which key should be listened to for progressing
preview_inquiry_isi(float): Length of time after displaying the inquiry preview to display a blank screen
"""
self.preview_on = preview_on
self.preview_inquiry_length = preview_inquiry_length
self.preview_inquiry_key_input = preview_inquiry_key_input
self.press_to_accept = True if preview_inquiry_progress_method == 1 else False
self.preview_only = preview_only
self.preview_inquiry_isi = preview_inquiry_isi


class PreviewParams(NamedTuple):
"""Parameters relevant for the Inquiry Preview functionality.

Expand Down
4 changes: 4 additions & 0 deletions bcipy/display/tests/components/test_button_press_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,3 +189,7 @@ def test_press_to_reject_with_keypress(self, get_key_press_mock):
self.assertTrue(handler.has_response())
self.assertEqual('bcipy_key_press_space', handler.response_label)
self.assertEqual(1.5, handler.response_timestamp)


if __name__ == '__main__':
unittest.main()
4 changes: 2 additions & 2 deletions bcipy/helpers/convert.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from tqdm import tqdm

from bcipy.acquisition.devices import preconfigured_device
from bcipy.config import (DEFAULT_PARAMETER_FILENAME, RAW_DATA_FILENAME,
from bcipy.config import (DEFAULT_PARAMETERS_FILENAME, RAW_DATA_FILENAME,
TRIGGER_FILENAME, SESSION_LOG_FILENAME)
from bcipy.helpers.load import load_json_parameters, load_raw_data
from bcipy.helpers.raw_data import RawData
Expand Down Expand Up @@ -174,7 +174,7 @@ def pyedf_convert(data_dir: str,
otherwise a string of the filter parameters used to filter the data
"""

params = load_json_parameters(str(Path(data_dir, DEFAULT_PARAMETER_FILENAME)),
params = load_json_parameters(str(Path(data_dir, DEFAULT_PARAMETERS_FILENAME)),
value_cast=True)
data = load_raw_data(str(Path(data_dir, f'{RAW_DATA_FILENAME}.csv')))
fs = data.sample_rate
Expand Down
4 changes: 2 additions & 2 deletions bcipy/helpers/demo/demo_report.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from bcipy.helpers.triggers import trigger_decoder, TriggerType
from bcipy.config import (
BCIPY_ROOT,
DEFAULT_PARAMETER_FILENAME,
DEFAULT_PARAMETERS_FILENAME,
RAW_DATA_FILENAME,
TRIGGER_FILENAME,
DEFAULT_DEVICE_SPEC_FILENAME)
Expand Down Expand Up @@ -44,7 +44,7 @@
if prompt != 'skip':
# load the parameters from the data directory
parameters = load_json_parameters(
f'{session}/{DEFAULT_PARAMETER_FILENAME}', value_cast=True)
f'{session}/{DEFAULT_PARAMETERS_FILENAME}', value_cast=True)

# load the raw data from the data directory
raw_data = load_raw_data(Path(session, f'{RAW_DATA_FILENAME}.csv'))
Expand Down
4 changes: 2 additions & 2 deletions bcipy/helpers/demo/demo_visualization.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"""
import bcipy.acquisition.devices as devices
from bcipy.config import (DEFAULT_DEVICE_SPEC_FILENAME,
DEFAULT_PARAMETER_FILENAME, RAW_DATA_FILENAME,
DEFAULT_PARAMETERS_FILENAME, RAW_DATA_FILENAME,
TRIGGER_FILENAME)
from bcipy.helpers.acquisition import analysis_channels
from bcipy.helpers.load import (load_experimental_data, load_json_parameters,
Expand Down Expand Up @@ -44,7 +44,7 @@
if not path:
path = load_experimental_data()

parameters = load_json_parameters(f'{path}/{DEFAULT_PARAMETER_FILENAME}',
parameters = load_json_parameters(f'{path}/{DEFAULT_PARAMETERS_FILENAME}',
value_cast=True)

# extract all relevant parameters
Expand Down
4 changes: 2 additions & 2 deletions bcipy/helpers/offset.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
DIODE_TRIGGER,
RAW_DATA_FILENAME,
DEFAULT_TRIGGER_CHANNEL_NAME,
DEFAULT_PARAMETER_FILENAME
DEFAULT_PARAMETERS_FILENAME
)


Expand Down Expand Up @@ -343,7 +343,7 @@ def extract_data_latency_calculation(
data_path = ask_directory()

# grab the stim length from the data directory parameters
stim_length = load_json_parameters(f'{data_path}/{DEFAULT_PARAMETER_FILENAME}', value_cast=True)['stim_length']
stim_length = load_json_parameters(f'{data_path}/{DEFAULT_PARAMETERS_FILENAME}', value_cast=True)['stim_length']

raw_data, triggers, static_offset = extract_data_latency_calculation(
data_path,
Expand Down
4 changes: 2 additions & 2 deletions bcipy/helpers/save.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
DEFAULT_EXPERIMENT_ID,
DEFAULT_LM_PARAMETERS_FILENAME,
DEFAULT_LM_PARAMETERS_PATH,
DEFAULT_PARAMETER_FILENAME,
DEFAULT_PARAMETERS_FILENAME,
SIGNAL_MODEL_FILE_SUFFIX,
STIMULI_POSITIONS_FILENAME)
from bcipy.signal.model.base_model import SignalModel
Expand Down Expand Up @@ -95,7 +95,7 @@ def init_save_data_structure(data_save_path: str,
os.makedirs(save_directory)
os.makedirs(os.path.join(save_directory, 'logs'), exist_ok=True)

copyfile(parameters, Path(save_directory, DEFAULT_PARAMETER_FILENAME))
copyfile(parameters, Path(save_directory, DEFAULT_PARAMETERS_FILENAME))

copyfile(DEFAULT_LM_PARAMETERS_PATH, Path(save_directory, DEFAULT_LM_PARAMETERS_FILENAME))

Expand Down
4 changes: 2 additions & 2 deletions bcipy/helpers/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
WHITE = COLOR_INDEX[1]
YELLOW = COLOR_INDEX[5]
from bcipy.config import (BCIPY_ROOT, DEFAULT_ENCODING,
DEFAULT_PARAMETER_FILENAME, EXPERIMENT_DATA_FILENAME,
DEFAULT_PARAMETERS_FILENAME, EXPERIMENT_DATA_FILENAME,
SESSION_DATA_FILENAME, SESSION_SUMMARY_FILENAME)
from bcipy.helpers.load import (load_experiment_fields, load_experiments,
load_json_parameters)
Expand All @@ -37,7 +37,7 @@ def session_data(data_dir: str) -> Dict:
not useful for debugging."""

parameters = load_json_parameters(os.path.join(data_dir,
DEFAULT_PARAMETER_FILENAME),
DEFAULT_PARAMETERS_FILENAME),
value_cast=True)
session = read_session(os.path.join(data_dir, SESSION_DATA_FILENAME))
data = session.as_dict(evidence_only=True)
Expand Down
4 changes: 2 additions & 2 deletions bcipy/helpers/tests/test_convert.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from mockito import mock, unstub, verify, verifyNoMoreInteractions, when

import bcipy.acquisition.devices as devices
from bcipy.config import (DEFAULT_ENCODING, DEFAULT_PARAMETER_FILENAME,
from bcipy.config import (DEFAULT_ENCODING, DEFAULT_PARAMETERS_FILENAME,
RAW_DATA_FILENAME, TRIGGER_FILENAME)
from bcipy.helpers import convert
from bcipy.helpers.convert import (archive_list, compress, convert_to_bdf,
Expand Down Expand Up @@ -64,7 +64,7 @@ def create_bcipy_session_artifacts(
filter_high=filter_settings['filter_high'],
filter_low=filter_settings['filter_low'],
filter_order=filter_settings['filter_order'])
params.save(write_dir, DEFAULT_PARAMETER_FILENAME)
params.save(write_dir, DEFAULT_PARAMETERS_FILENAME)
return trg_data, data, params


Expand Down
4 changes: 2 additions & 2 deletions bcipy/helpers/tests/test_save.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

from bcipy.config import (
DEFAULT_PARAMETERS_PATH,
DEFAULT_PARAMETER_FILENAME,
DEFAULT_PARAMETERS_FILENAME,
DEFAULT_EXPERIMENT_ID,
STIMULI_POSITIONS_FILENAME)
from bcipy.helpers import save
Expand Down Expand Up @@ -50,7 +50,7 @@ def test_init_save_data_structure_creates_correct_save_folder(self):
def test_parameter_file_copies(self):

# construct the path of the parameters
param_path = self.save_folder_name + f'/{DEFAULT_PARAMETER_FILENAME}'
param_path = self.save_folder_name + f'/{DEFAULT_PARAMETERS_FILENAME}'

# assert that the params file was created in the correct location
self.assertTrue(os.path.isfile(param_path))
Expand Down
4 changes: 2 additions & 2 deletions bcipy/signal/evaluate/artifact.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import logging

from bcipy.config import (
DEFAULT_PARAMETER_FILENAME,
DEFAULT_PARAMETERS_FILENAME,
RAW_DATA_FILENAME,
TRIGGER_FILENAME,
DEFAULT_DEVICE_SPEC_FILENAME,
Expand Down Expand Up @@ -577,7 +577,7 @@ def write_mne_annotations(
if prompt != 'skip':
# load the parameters from the data directory
parameters = load_json_parameters(
f'{session}/{DEFAULT_PARAMETER_FILENAME}', value_cast=True)
f'{session}/{DEFAULT_PARAMETERS_FILENAME}', value_cast=True)

# load the raw data from the data directory
raw_data = load_raw_data(str(Path(session, f'{RAW_DATA_FILENAME}.csv')))
Expand Down
4 changes: 2 additions & 2 deletions bcipy/signal/tests/model/test_offline_analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import random
import gzip

from bcipy.config import RAW_DATA_FILENAME, DEFAULT_PARAMETER_FILENAME, TRIGGER_FILENAME, DEFAULT_DEVICE_SPEC_FILENAME
from bcipy.config import RAW_DATA_FILENAME, DEFAULT_PARAMETERS_FILENAME, TRIGGER_FILENAME, DEFAULT_DEVICE_SPEC_FILENAME
from bcipy.helpers.load import load_json_parameters
from bcipy.signal.model.offline_analysis import offline_analysis

Expand Down Expand Up @@ -48,7 +48,7 @@ def setUpClass(cls):
shutil.copyfile(input_folder / TRIGGER_FILENAME, cls.tmp_dir / TRIGGER_FILENAME)
shutil.copyfile(input_folder / DEFAULT_DEVICE_SPEC_FILENAME, cls.tmp_dir / DEFAULT_DEVICE_SPEC_FILENAME)

params_path = pwd.parent.parent.parent / "parameters" / DEFAULT_PARAMETER_FILENAME
params_path = pwd.parent.parent.parent / "parameters" / DEFAULT_PARAMETERS_FILENAME
cls.parameters = load_json_parameters(params_path, value_cast=True)
models = offline_analysis(
str(cls.tmp_dir),
Expand Down
4 changes: 2 additions & 2 deletions bcipy/simulator/data/data_process.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from bcipy.acquisition.devices import DeviceSpec
from bcipy.acquisition.multimodal import ContentType
from bcipy.config import (DEFAULT_DEVICE_SPEC_FILENAME,
DEFAULT_PARAMETER_FILENAME, TRIGGER_FILENAME)
DEFAULT_PARAMETERS_FILENAME, TRIGGER_FILENAME)
from bcipy.helpers.acquisition import analysis_channels, raw_data_filename
from bcipy.helpers.list import grouper
from bcipy.helpers.load import load_json_parameters, load_raw_data
Expand Down Expand Up @@ -270,7 +270,7 @@ def process(self, data_folder: str,
raw_data, device_spec = load_device_data(data_folder,
self.content_type.name)
data_parameters = load_json_parameters(
f"{data_folder}/{DEFAULT_PARAMETER_FILENAME}", value_cast=True)
f"{data_folder}/{DEFAULT_PARAMETERS_FILENAME}", value_cast=True)

timing_params = parameters.instantiate(TimingParams)

Expand Down
Loading
Loading