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

Updating the default config to be compatible with adult recordings. #173

Merged
merged 5 commits into from
Nov 10, 2024
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
144 changes: 144 additions & 0 deletions pylossless/assets/ll_default_config_adults.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
######################### General properties #########################
#ref_loc_file: derivatives/pylossless/code/misc/standard_1020_ll_ref19.elc
#montage_info: [0.0, -16.0, 0.0, -0.02, 0.0, -1.58, 10.7, 11.5, 11.5]

################## General info about the project ####################
project:
readme: "# Description of the dataset"

# Montage use to make file BIDS compliant.
# Can be path to digitized montage OR a string of one of mne's built in
# standard montages as specified by mne.channels.get_builtin_montages().
# Can be left empty if the input dataset is already in BIDS format.
bids_montage: GSN-HydroCel-129

# montage used while running the lossless pipeline.
# if empty, the pipeline will use the electrodes.tsv sidecar file, if created
# during the BIDS conversion.
# If specified, needs to be a string of one of mne's built in standard montages.
analysis_montage: ""

set_montage_kwargs: {}

coordsys:
EEGCoordinateSystem: Other
EEGCoordinateUnits: metres

general_info:
authors: [Unspecified]
institution_Name: Unspecified
institution_address: Unspecified
dataset_doi: []
funding: Unspecified
how_to_acknowledge: tba
license: ""
name: Unspecified
references_and_links: []

t_info:
EEG_placement_scheme: EGI 129
cap_manufacturer: EGI
cap_manufacturers_model_name: Hydrocel 129 Channel
hardware_filters: n/a
manufacturer: Electrical Geodesics
manufacturers_model_name: NetAmps300
power_line_frequency: 60
software_filters: n/a
software_versions: NetStation V4.5

######################## Task break detection ########################
# See arguments definition from mne.preprocessing.annotate_breaks
find_breaks:

############################## epoching ##############################
epoching:
overlap: 0

# See arguments definition from mne.Epochs
epochs_args:
baseline: null
tmax: 1
tmin: 0

########################### EEG filtering ############################
# See arguments definition from mne.io.Raw.filter & mne.io.Raw.notch_filter
filtering:
filter_args:
h_freq: 100
l_freq: 1
notch_filter_args:
freqs: [60]

############################## SLURM #################################
# Options for running the pipeline on a cluster
# through SLURM
slurm_options:
account: def-emayada
job_name: pylossless
memory: 16g
mpi: false
num_tasks: 1
program_options: []
threads_per_task: []
time_limit: 2h

########################## Nearest neighbor ##########################
nearest_neighbors:
n_nbr_ch: 3
n_nbr_epoch: 3

####################### Pipeline steps config ########################
bridged_channels:
bridge_trim: 40
bridge_z: 6

noisy_channels:
flag_crit: 0.2
outlier_method: quantile
outliers_kwargs:
k: 6
lower: 0.25
upper: 0.75

uncorrelated_channels:
flag_crit: 0.2
outlier_method: quantile
outliers_kwargs:
k: 6
lower: 0.25
upper: 0.75

noisy_epochs:
flag_crit: 0.2
outlier_method: quantile
outliers_kwargs:
k: 6
lower: 0.25
upper: 0.75

uncorrelated_epochs:
flag_crit: 0.2
outlier_method: quantile
outliers_kwargs:
k: 6
lower: 0.25
upper: 0.75

################################ ICA #################################
ica:
noisy_ic_epochs:
flag_crit: 0.2
outlier_method: quantile
outliers_kwargs:
k: 6
lower: 0.25
upper: 0.75

# See arguments definition from mne.preprocessing.ICA
ica_args:
run1:
method: fastica
run2:
method: infomax
fit_params:
extended: True
Original file line number Diff line number Diff line change
@@ -1,16 +1,10 @@
######################### General properties #########################
aref_trim: 30
order: 1
out_path: derivatives/EEG-IP-L
ref_loc_file: derivatives/EEG-IP-L/code/misc/standard_1020_ll_ref19.elc
save_f_res: 1
sd_t_pad: 1
in_path: []
montage_info: [0.0, -16.0, 0.0, -0.02, 0.0, -1.58, 10.7, 11.5, 11.5]
#ref_loc_file: derivatives/pylossless/code/misc/standard_1020_ll_ref19.elc
#montage_info: [0.0, -16.0, 0.0, -0.02, 0.0, -1.58, 10.7, 11.5, 11.5]

################## General info about the project ####################
project:
readme: "# Q1K ACAR Dataset"
readme: "# Description of the dataset"

# Montage use to make file BIDS compliant.
# Can be path to digitized montage OR a string of one of mne's built in
Expand All @@ -31,14 +25,14 @@ project:
EEGCoordinateUnits: metres

general_info:
authors: [Q1K Neuroimaging group]
institution_Name: McGill University
institution_address: 3775 Rue University, Montreal, QC
authors: [Unspecified]
institution_Name: Unspecified
institution_address: Unspecified
dataset_doi: []
funding: Azrieli Foundationt
funding: Unspecified
how_to_acknowledge: tba
license: ""
name: Q1K Mismatched Negativity
name: Unspecified
references_and_links: []

t_info:
Expand Down
19 changes: 12 additions & 7 deletions pylossless/config/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"""Base configuration file class for pipeline procedures."""

DEFAULT_CONFIG_PATH = (
Path(__file__).parent.parent / "assets" / "ll_default_config.yaml"
Path(__file__).parent.parent / "assets"
)

def read(self, file_name):
Expand Down Expand Up @@ -51,11 +51,16 @@
class Config(ConfigMixin):
"""Representation of configuration file for running the pipeline."""

DEFAULT_CONFIG_PATH = (
Path(__file__).parent.parent / "assets" / "ll_default_config.yaml"
)
def load_default(self, kind="adults"):
"""Get the default pylossless config file.

def load_default(self):
"""Get the default pylossless config file."""
self.read(Config.DEFAULT_CONFIG_PATH)
Parameters
----------
kind : str | pathlib.Path
Can be either 'adults' or 'infants'. Default to 'adults'.
"""
path = Config.DEFAULT_CONFIG_PATH / f"ll_default_config_{kind}.yaml"
if not path.exists():
raise ValueError(f"No default configuration for kind '{kind}'.")

Check warning on line 64 in pylossless/config/config.py

View check run for this annotation

Codecov / codecov/patch

pylossless/config/config.py#L64

Added line #L64 was not covered by tests
self.read(path)
return self
3 changes: 2 additions & 1 deletion pylossless/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
def pipeline_fixture():
"""Return a namedTuple containing MNE eyetracking raw data and events."""
raw, config, bids_path = load_openneuro_bids()
raw.crop(tmin=0, tmax=60) # take 60 seconds for speed
# raw.crop(tmin=0, tmax=60) # Too short for ICA to converge in some tests.
annots = Annotations(
onset=[1, 15], duration=[1, 1], description=["test_annot", "test_annot"]
)
Expand All @@ -28,6 +28,7 @@ def pipeline_fixture():
config["find_breaks"]["min_break_duration"] = 9
config["find_breaks"]["t_start_after_previous"] = 1
config["find_breaks"]["t_stop_before_next"] = 0
config["ica"]["ica_args"]["run1"]["max_iter"] = 5000
config.save("test_config.yaml")
pipeline = ll.LosslessPipeline("test_config.yaml")
not_in_1020 = ["EXG1", "EXG2", "EXG3", "EXG4", "EXG5", "EXG6", "EXG7", "EXG8"]
Expand Down
5 changes: 4 additions & 1 deletion pylossless/datasets/datasets.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,10 @@ def load_openneuro_bids(subject="pd6"):
openneuro = ll.utils.import_optional_dependency("openneuro")

config = ll.config.Config()
config.load_default()
# TODO: Tests were developed using this configuration. The adult version
# should probably be used instead, but this change will require fixing the
# tests accordingly.
config.load_default("infants")
config["project"]["bids_montage"] = ""
config["project"]["analysis_montage"] = "standard_1020"
config["project"]["set_montage_kwargs"]["on_missing"] = "warn"
Expand Down
2 changes: 1 addition & 1 deletion pylossless/tests/test_simulated.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

# LOAD DEFAULT CONFIG
config = ll.config.Config()
config.load_default()
config.load_default("infants")
config["noisy_channels"]["outliers_kwargs"]["lower"] = 0.25
config["noisy_channels"]["outliers_kwargs"]["upper"] = 0.75
# short file, raise threshold so epochs w/ blinks dont cause flag
Expand Down
14 changes: 9 additions & 5 deletions pylossless/tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,18 @@ def test_import_optional_dependency():
from pylossless.utils import check

# Test the case where the package is not installed.
with pytest.raises(ImportError, match="Missing optional dependency 'astropy'."):
# choosing a package that will probably never be added to the requirements!
check.import_optional_dependency("astropy")
package = "sdgssfersfsdesdfsefsdfsdt"
Copy link
Member

Choose a reason for hiding this comment

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

aha nice ; )

with pytest.raises(ImportError, match=f"Missing optional dependency '{package}'."):
# Choosing a package that will probably never be added to the requirements!
# We also choose a name of a package that is likely not to exist at all
# to avoid the corresponding package is installed in the development
# environment of developers.
check.import_optional_dependency(package)

# Test the case where the package is installed.
mne = check.import_optional_dependency("mne", raise_error=False)
assert mne is not None

# Test the where case package is not installed but we don't want to raise an error.
astropy = check.import_optional_dependency("astropy", raise_error=False)
assert astropy is None
ret_val = check.import_optional_dependency(package, raise_error=False)
assert ret_val is None
Loading