diff --git a/Makefile b/Makefile index 01140b9..b59cc88 100644 --- a/Makefile +++ b/Makefile @@ -138,6 +138,11 @@ generalize: ## demo: predicts labels of MOAE dataset generalize \ --model 1_guided_fixations \ -vv + bidsmreye $$PWD/tests/data/moae_fmriprep \ + $$PWD/outputs/moae_fmriprep/derivatives \ + participant \ + generalize \ + -vv # run demo via boutiques demo_boutiques: tests/data/moae_fmriprep diff --git a/bidsmreye/bids_utils.py b/bidsmreye/bids_utils.py index cdb890a..782a71c 100644 --- a/bidsmreye/bids_utils.py +++ b/bidsmreye/bids_utils.py @@ -1,6 +1,7 @@ from __future__ import annotations import json +import re from pathlib import Path from typing import Any @@ -88,7 +89,10 @@ def check_layout(cfg: Config, layout: BIDSLayout, for_file: str = "bold") -> Non def create_bidsname( - layout: BIDSLayout, filename: dict[str, str] | str | Path, filetype: str + layout: BIDSLayout, + filename: dict[str, str] | str | Path, + filetype: str, + extra_entities: dict[str, str] | None = None, ) -> Path: """Return a BIDS valid filename for layout and a filename or a dict of BIDS entities. @@ -117,8 +121,9 @@ def create_bidsname( padding = len(x.split("-")[1]) entities["run"] = f"{entities['run']:0{padding}d}" - else: - raise TypeError(f"filename must be a dict or a Path, not {type(filename)}") + if extra_entities is not None: + for key in extra_entities: + entities[key] = extra_entities[key] bids_name_config = get_bidsname_config() @@ -128,6 +133,32 @@ def create_bidsname( return output_file.absolute() +def return_desc_entity(model_filename: Path): + model_name = sanitize_filename(model_filename).replace("Dataset", "") + if model_name in ["1GuidedFixations", "5FreeViewing"]: + return model_name[1:] + elif model_name == "3Openclosed": + return "OpenClosed" + elif model_name in ["4Pursuit", "2Pursuit", "3Pursuit"]: + return model_name[1:] + model_name[0] + elif model_name in ["1to5", "1to6"]: + return model_name + else: + return sanitize_filename(model_filename) + + +def sanitize_filename(filename: Path): + """Turn filename stem into its alphanumeric CamelCase equivalent. + + To use as a BIDS entity label. + """ + # Remove non-alphanumeric characters and split into words + words = re.sub(r"[^a-zA-Z0-9]", " ", filename.stem).split() + # Capitalize the first letter of each word and join them + camelcase_name = "".join(word.capitalize() for word in words) + return camelcase_name + + def create_sidecar( layout: BIDSLayout, filename: str, @@ -142,9 +173,9 @@ def create_sidecar( } if source is not None: content["Sources"] = [source] # type: ignore - sidecar_name = create_bidsname(layout, filename, "confounds_json") + sidecar_name = create_bidsname(layout, filename, "no_label_json") json.dump(content, open(sidecar_name, "w"), indent=4) - log.debug(f"sidecar saved to {sidecar_name}") + log.debug(f"Sidecar saved to {sidecar_name}") def save_sampling_frequency_to_json( @@ -191,7 +222,7 @@ def get_dataset_layout( if config is None: pybids_config = get_pybids_config() - log.info(f"indexing {dataset_path}") + log.info(f"Indexing {dataset_path}") if not use_database: return BIDSLayout( @@ -263,7 +294,7 @@ def list_subjects(cfg: Config, layout: BIDSLayout) -> list[str]: subjects = [subjects[0]] log.debug("Running first subject only.") - log.info(f"processing subjects: {subjects}") + log.info(f"Processing subjects: {subjects}") return subjects diff --git a/bidsmreye/config/config_bidsname.json b/bidsmreye/config/config_bidsname.json index 4fb5fc9..0614e48 100644 --- a/bidsmreye/config/config_bidsname.json +++ b/bidsmreye/config/config_bidsname.json @@ -1,10 +1,11 @@ { "mask": "sub-{subject}/[ses-{session}]/func/sub-{subject}[_ses-{session}]_task-{task}[_acq-{acquisition}][_ce-{ce}][_rec-{rec}][_dir-{dir}][_run-{run}][_space-{space}][_res-{res}][_den-{den}]_desc-eye_mask.p", "report": "sub-{subject}/[ses-{session}]/figures/sub-{subject}[_ses-{session}]_task-{task}[_acq-{acquisition}][_ce-{ce}][_rec-{rec}][_dir-{dir}][_run-{run}][_space-{space}][_res-{res}][_den-{den}]_desc-eye_report.html", - "no_label": "sub-{subject}/[ses-{session}]/func/sub-{subject}[_ses-{session}]_task-{task}[_acq-{acquisition}][_ce-{ce}][_rec-{rec}][_dir-{dir}][_run-{run}][_space-{space}][_res-{res}][_den-{den}]_desc-nolabel_bidsmreye.npz", - "confounds_tsv": "sub-{subject}/[ses-{session}]/func/sub-{subject}[_ses-{session}]_task-{task}[_acq-{acquisition}][_ce-{ce}][_rec-{rec}][_dir-{dir}][_run-{run}][_space-{space}]_desc-bidsmreye_eyetrack.tsv", - "confounds_json": "sub-{subject}/[ses-{session}]/func/sub-{subject}[_ses-{session}]_task-{task}[_acq-{acquisition}][_ce-{ce}][_rec-{rec}][_dir-{dir}][_run-{run}][_space-{space}]_desc-bidsmreye_eyetrack.json", - "confounds_svg": "sub-{subject}/[ses-{session}]/figures/sub-{subject}[_ses-{session}]_task-{task}[_acq-{acquisition}][_ce-{ce}][_rec-{rec}][_dir-{dir}][_run-{run}][_space-{space}]_desc-bidsmreye_eyetrack.svg", - "confounds_html": "sub-{subject}/[ses-{session}]/figures/sub-{subject}[_ses-{session}]_task-{task}[_acq-{acquisition}][_ce-{ce}][_rec-{rec}][_dir-{dir}][_run-{run}][_space-{space}]_desc-bidsmreye_eyetrack.html", - "confounds_numpy": "sub-{subject}/[ses-{session}]/func/sub-{subject}[_ses-{session}]_task-{task}_space-{space}_desc-bidsmreye_confounds.npy" + "no_label_bold": "sub-{subject}/[ses-{session}]/func/sub-{subject}[_ses-{session}]_task-{task}[_acq-{acquisition}][_ce-{ce}][_rec-{rec}][_dir-{dir}][_run-{run}][_space-{space}][_res-{res}][_den-{den}]_desc-eye_timeseries.npz", + "no_label_json": "sub-{subject}/[ses-{session}]/func/sub-{subject}[_ses-{session}]_task-{task}[_acq-{acquisition}][_ce-{ce}][_rec-{rec}][_dir-{dir}][_run-{run}][_space-{space}][_res-{res}][_den-{den}]_desc-eye_timeseries.json", + "confounds_tsv": "sub-{subject}/[ses-{session}]/func/sub-{subject}[_ses-{session}]_task-{task}[_acq-{acquisition}][_ce-{ce}][_rec-{rec}][_dir-{dir}][_run-{run}][_space-{space}]_desc-{desc}_eyetrack.tsv", + "confounds_json": "sub-{subject}/[ses-{session}]/func/sub-{subject}[_ses-{session}]_task-{task}[_acq-{acquisition}][_ce-{ce}][_rec-{rec}][_dir-{dir}][_run-{run}][_space-{space}]_desc-{desc}_eyetrack.json", + "confounds_html": "sub-{subject}/[ses-{session}]/figures/sub-{subject}[_ses-{session}]_task-{task}[_acq-{acquisition}][_ce-{ce}][_rec-{rec}][_dir-{dir}][_run-{run}][_space-{space}]_desc-{desc}_eyetrack.html", + "confounds_svg": "sub-{subject}/[ses-{session}]/figures/sub-{subject}[_ses-{session}]_task-{task}[_acq-{acquisition}][_ce-{ce}][_rec-{rec}][_dir-{dir}][_run-{run}][_space-{space}]_desc-{desc}_eyetrack.svg", + "confounds_numpy": "sub-{subject}/[ses-{session}]/func/sub-{subject}[_ses-{session}]_task-{task}_space-{space}_desc-{desc}_confounds.npy" } diff --git a/bidsmreye/config/default_filter_file.json b/bidsmreye/config/default_filter_file.json index d0b5fb6..1f2b843 100644 --- a/bidsmreye/config/default_filter_file.json +++ b/bidsmreye/config/default_filter_file.json @@ -9,11 +9,16 @@ "suffix": "mask", "extension": "p" }, - "no_label": { - "desc": "nolabel", - "suffix": "^bidsmreye$$", + "no_label_bold": { + "desc": "eye", + "suffix": "^timeseries$$", "extension": "npz" }, + "no_label_bold_json": { + "desc": "eye", + "suffix": "^timeseries$$", + "extension": "json" + }, "eyetrack": { "suffix": "^eyetrack$$", "extension": "tsv" diff --git a/bidsmreye/generalize.py b/bidsmreye/generalize.py index cb57fc5..12bb625 100644 --- a/bidsmreye/generalize.py +++ b/bidsmreye/generalize.py @@ -2,8 +2,10 @@ from __future__ import annotations +import json import logging import os +import shutil import warnings from pathlib import Path from typing import Any @@ -20,12 +22,13 @@ create_bidsname, get_dataset_layout, list_subjects, + return_desc_entity, ) from bidsmreye.configuration import Config from bidsmreye.logger import bidsmreye_log from bidsmreye.quality_control import quality_control_output from bidsmreye.utils import ( - add_sidecar_in_root, + add_timestamps_to_dataframe, check_if_file_found, create_dir_for_file, move_file, @@ -70,7 +73,9 @@ def create_and_save_figure( fig.write_image(confound_svg) -def convert_confounds(layout_out: BIDSLayout, file: str | Path) -> Path: +def convert_confounds( + layout_out: BIDSLayout, file: str | Path, extra_entities: dict[str, str] | None = None +) -> Path: """Convert numpy output to TSV. :param layout_out: pybids layout to of the dataset to act on. @@ -86,7 +91,43 @@ def convert_confounds(layout_out: BIDSLayout, file: str | Path) -> Path: but should still be able to unpack the results from a numpy file with results from multiple files. """ - confound_numpy = create_bidsname(layout_out, file, "confounds_numpy") + COLUMNS = ["timestamp", "x_coordinate", "y_coordinate"] + + bold_json = Path(file).with_suffix(".json") + confounds_json = create_bidsname( + layout_out, file, "confounds_json", extra_entities=extra_entities + ) + shutil.copyfile(bold_json, confounds_json) + with open(confounds_json) as f: + metadata = json.load(f) + metadata["StartTime"] = 0.0 + metadata["Columns"] = COLUMNS + metadata["PhysioType"] = "eyetrack" + metadata["EnvironmentCoordinates"] = "center" + metadata["RecordedEye"] = "cyclopean" + metadata["timestamp"] = { + "Description": ( + "Timestamp indexing the continuous recordings " + "corresponding to the sampled eye." + ), + "Units": "seconds", + } + metadata["x_coordinate"] = { + "Description": ("Gaze position x-coordinate of the recorded eye."), + "Units": "degrees", + } + metadata["y_coordinate"] = { + "Description": ("Gaze position y-coordinate of the recorded eye."), + "Units": "degrees", + } + with open(confounds_json, "w") as f: + metadata = {key: metadata[key] for key in sorted(metadata)} + json.dump(metadata, f, indent=4) + log.debug(f"Sidecar saved to {confounds_json}") + + confound_numpy = create_bidsname( + layout_out, file, "confounds_numpy", extra_entities=extra_entities + ) content = np.load( file=confound_numpy, @@ -100,14 +141,19 @@ def convert_confounds(layout_out: BIDSLayout, file: str | Path) -> Path: this_pred = np.nanmedian(item["pred_y"], axis=1) - confound_name = create_bidsname(layout_out, Path(key + "p"), "confounds_tsv") + confound_name = create_bidsname( + layout_out, Path(key + "p"), "confounds_tsv", extra_entities=extra_entities + ) log.info(f"Saving eye gaze data to {confound_name.relative_to(layout_out.root)}") - pd.DataFrame(this_pred).to_csv( + df = pd.DataFrame(this_pred) + df = add_timestamps_to_dataframe(df, metadata["SamplingFrequency"]) + + df.to_csv( confound_name, sep="\t", - header=["eye1_x_coordinate", "eye1_y_coordinate"], + header=COLUMNS, index=None, ) @@ -117,7 +163,12 @@ def convert_confounds(layout_out: BIDSLayout, file: str | Path) -> Path: return confound_name -def create_confounds_tsv(layout_out: BIDSLayout, file: str, subject_label: str) -> None: +def create_confounds_tsv( + layout_out: BIDSLayout, + file: str, + subject_label: str, + extra_entities: dict[str, str] | None = None, +) -> None: """Generate a TSV file for the eye motion timeseries. :param layout_out: @@ -129,7 +180,9 @@ def create_confounds_tsv(layout_out: BIDSLayout, file: str, subject_label: str) :param subject_label: :type subject_label: str """ - confound_numpy = create_bidsname(layout_out, file, "confounds_numpy") + confound_numpy = create_bidsname( + layout_out, file, "confounds_numpy", extra_entities=extra_entities + ) source_file = Path(layout_out.root) / f"sub-{subject_label}" / "results_tmp.npy" @@ -138,7 +191,7 @@ def create_confounds_tsv(layout_out: BIDSLayout, file: str, subject_label: str) confound_numpy, ) - convert_confounds(layout_out, file) + convert_confounds(layout_out, file, extra_entities=extra_entities) def process_subject(cfg: Config, layout_out: BIDSLayout, subject_label: str) -> None: @@ -155,7 +208,7 @@ def process_subject(cfg: Config, layout_out: BIDSLayout, subject_label: str) -> """ log.info(f"Running subject: {subject_label}") - this_filter = set_this_filter(cfg, subject_label, "no_label") + this_filter = set_this_filter(cfg, subject_label, "no_label_bold") bf = layout_out.get( regex_search=True, @@ -199,7 +252,10 @@ def process_subject(cfg: Config, layout_out: BIDSLayout, subject_label: str) -> percentile_cut=80, ) - create_confounds_tsv(layout_out, file.path, subject_label) + extra_entities = None + if cfg.model_weights_file is not None: + extra_entities = {"desc": return_desc_entity(Path(cfg.model_weights_file))} + create_confounds_tsv(layout_out, file.path, subject_label, extra_entities) def generalize(cfg: Config) -> None: @@ -211,8 +267,6 @@ def generalize(cfg: Config) -> None: layout_out = get_dataset_layout(cfg.output_dir) check_layout(cfg, layout_out) - add_sidecar_in_root(layout_out) - subjects = list_subjects(cfg, layout_out) text = "GENERALIZING" diff --git a/bidsmreye/prepare_data.py b/bidsmreye/prepare_data.py index 3568b31..e3f4d4c 100644 --- a/bidsmreye/prepare_data.py +++ b/bidsmreye/prepare_data.py @@ -96,7 +96,7 @@ def combine_data_with_empty_labels(layout_out: BIDSLayout, img: Path, i: int = 1 subj["labels"].append(labels) subj["ids"].append(([entities["subject"]] * labels.shape[0], [i] * labels.shape[0])) - output_file = create_bidsname(layout_out, Path(img), "no_label") + output_file = create_bidsname(layout_out, Path(img), "no_label_bold") file_to_move = Path(layout_out.root) / ".." / "bidsmreye" / output_file.name preprocess.save_data( @@ -151,7 +151,7 @@ def prepapre_image( report_name = create_bidsname(layout_out, filename=img_path, filetype="report") mask_name = create_bidsname(layout_out, filename=img_path, filetype="mask") - output_file = create_bidsname(layout_out, Path(img_path), "no_label") + output_file = create_bidsname(layout_out, Path(img_path), "no_label_bold") if ( not cfg.force diff --git a/bidsmreye/quality_control.py b/bidsmreye/quality_control.py index 8c09a03..18bb072 100644 --- a/bidsmreye/quality_control.py +++ b/bidsmreye/quality_control.py @@ -17,11 +17,13 @@ get_dataset_layout, init_dataset, list_subjects, + return_desc_entity, ) from bidsmreye.configuration import Config from bidsmreye.logger import bidsmreye_log from bidsmreye.report import generate_report from bidsmreye.utils import ( + add_timestamps_to_dataframe, check_if_file_found, create_dir_for_file, progress_bar, @@ -59,33 +61,63 @@ def add_qc_to_sidecar(confounds: pd.DataFrame, sidecar_name: Path) -> None: create_dir_for_file(file=sidecar_name) content = {} - content["NbDisplacementOutliers"] = confounds["displacement_outliers"].sum() - content["NbXOutliers"] = confounds["eye1_x_outliers"].sum() - content["NbYOutliers"] = confounds["eye1_y_outliers"].sum() - content["eye1XVar"] = confounds["eye1_x_coordinate"].var() - content["eye1YVar"] = confounds["eye1_y_coordinate"].var() - - json.dump(content, open(sidecar_name, "w"), indent=4) + content["NbDisplacementOutliers"] = int(confounds["displacement_outliers"].sum()) + content["NbXOutliers"] = int(confounds["x_outliers"].sum()) + content["NbYOutliers"] = int(confounds["y_outliers"].sum()) + content["XVar"] = confounds["x_coordinate"].var() + content["YVar"] = confounds["y_coordinate"].var() + content["Columns"] = confounds.columns.to_list() + + content["displacement"] = { + "Description": ( + "Framewise eye movement computed from the X and Y eye position " + "between 2 consecutives timeframes." + ), + "Units": "degrees", + } + content["displacement_outliers"] = { + "Description": ( + "Displacement outliers computed using robust ouliers with Carling's k." + ), + "Levels": {"0": "not an outlier", "1": "outlier"}, + } + content["x_outliers"] = { + "Description": ( + "X position outliers computed using robust ouliers with Carling's k." + ), + "Levels": {"0": "not an outlier", "1": "outlier"}, + } + content["y_outliers"] = { + "Description": ( + "Y position outliers computed using robust ouliers with Carling's k." + ), + "Levels": {"0": "not an outlier", "1": "outlier"}, + } + + content = {key: content[key] for key in sorted(content)} + + with open(sidecar_name, "w") as f: + json.dump(content, f, indent=4) def compute_displacement_and_outliers(confounds: pd.DataFrame) -> pd.DataFrame: confounds["displacement"] = compute_displacement( - confounds["eye1_x_coordinate"], confounds["eye1_y_coordinate"] + confounds["x_coordinate"], confounds["y_coordinate"] ) confounds["displacement_outliers"] = compute_robust_outliers( confounds["displacement"], outlier_type="Carling" ) - confounds["eye1_x_outliers"] = compute_robust_outliers( - confounds["eye1_x_coordinate"], outlier_type="Carling" + confounds["x_outliers"] = compute_robust_outliers( + confounds["x_coordinate"], outlier_type="Carling" ) - log.debug(f"Found {confounds['eye1_x_outliers'].sum()} x outliers") + log.debug(f"Found {confounds['x_outliers'].sum()} x outliers") - confounds["eye1_y_outliers"] = compute_robust_outliers( - confounds["eye1_y_coordinate"], outlier_type="Carling" + confounds["y_outliers"] = compute_robust_outliers( + confounds["y_coordinate"], outlier_type="Carling" ) - log.debug(f"Found {confounds['eye1_y_outliers'].sum()} y outliers") + log.debug(f"Found {confounds['y_outliers'].sum()} y outliers") return confounds @@ -122,19 +154,16 @@ def perform_quality_control( confounds = pd.read_csv(confounds_tsv, sep="\t") - if "eye_timestamp" not in confounds.columns: - sampling_frequency = get_sampling_frequency(layout_in, confounds_tsv) + if "timestamp" not in confounds.columns: + extra_entities = None + if cfg.model_weights_file is not None: + extra_entities = {"desc": return_desc_entity(Path(cfg.model_weights_file))} + sampling_frequency = get_sampling_frequency( + layout_in, confounds_tsv, extra_entities=extra_entities + ) if sampling_frequency is not None: - nb_timepoints = confounds.shape[0] - eye_timestamp = np.arange( - 0, 1 / sampling_frequency * nb_timepoints, 1 / sampling_frequency - ) - confounds["eye_timestamp"] = eye_timestamp - - cols = confounds.columns.tolist() - cols.insert(0, cols.pop(cols.index("eye_timestamp"))) - confounds = confounds[cols] + confounds = add_timestamps_to_dataframe(confounds, sampling_frequency) compute_displacement_and_outliers(confounds) @@ -151,11 +180,15 @@ def perform_quality_control( confounds.to_csv(confounds_tsv, sep="\t", index=False) -def get_sampling_frequency(layout: BIDSLayout, file: str | Path) -> float | None: +def get_sampling_frequency( + layout: BIDSLayout, file: str | Path, extra_entities: dict[str, str] | None = None +) -> float | None: """Get the sampling frequency from the sidecar JSON file.""" sampling_frequency = None - sidecar_name = create_bidsname(layout, file, "confounds_json") + sidecar_name = create_bidsname( + layout, file, "confounds_json", extra_entities=extra_entities + ) # TODO: deal with cases where the sidecar is in the root of the dataset if sidecar_name.is_file(): @@ -164,6 +197,11 @@ def get_sampling_frequency(layout: BIDSLayout, file: str | Path) -> float | None SamplingFrequency = content.get("SamplingFrequency", None) if SamplingFrequency is not None and SamplingFrequency > 0: sampling_frequency = SamplingFrequency + else: + log.error( + "The following sidecar was not found. " + f"Cannot infer sampling frequency.\n{sidecar_name}." + ) return sampling_frequency @@ -299,7 +337,7 @@ def compute_robust_outliers( # get the outliers in a normal distribution # no scaling needed as S estimates already std(data) - outliers = np.zeros(len(time_series)) + outliers = np.zeros(len(time_series), dtype=np.int8) outliers[non_nan_idx] = (distance / Sn) > k return outliers.tolist() @@ -325,7 +363,7 @@ def compute_robust_outliers( df = pd.DataFrame({"lt": lt, "gt": gt}) outliers = df["lt"] | df["gt"] - return list(map(float, outliers)) # type: ignore + return list(map(np.int8, outliers)) # type: ignore else: raise ValueError(f"Unknown outlier_type: {outlier_type}") diff --git a/bidsmreye/utils.py b/bidsmreye/utils.py index e9f29f8..3c4bbb3 100644 --- a/bidsmreye/utils.py +++ b/bidsmreye/utils.py @@ -1,11 +1,12 @@ from __future__ import annotations -import json import re import shutil from pathlib import Path from typing import Any +import numpy as np +import pandas as pd from bids import BIDSLayout # type: ignore from bids.layout import BIDSFile from rich.progress import ( @@ -55,18 +56,6 @@ def copy_license(output_dir: Path) -> Path: return output_file -def add_sidecar_in_root(layout_out: BIDSLayout) -> None: - content = { - "StartTime": 0, - "SampleCoordinateUnit": "degrees", - "EnvironmentCoordinates": "center", - "SampleCoordinateSystem": "gaze-on-screen", - "RecordedEye": "both", - } - sidecar_name = Path(layout_out.root) / "desc-bidsmreye_eyetrack.json" - json.dump(content, open(sidecar_name, "w"), indent=4) - - def check_if_file_found( bf: list[BIDSFile], this_filter: dict[str, Any], layout: BIDSLayout ) -> None: @@ -216,3 +205,15 @@ def return_deepmreye_output_filename(filename: str, filetype: str | None = None) filename = "report_" + re.sub(r"\.nii.*", ".html", filename) return filename + + +def add_timestamps_to_dataframe(df: pd.DataFrame, sampling_frequency: float): + nb_timepoints = df.shape[0] + timestamp = np.arange( + 0, 1 / sampling_frequency * nb_timepoints, 1 / sampling_frequency + ) + df["timestamp"] = timestamp + + cols = df.columns.tolist() + cols.insert(0, cols.pop(cols.index("timestamp"))) + return df[cols] diff --git a/bidsmreye/visualize.py b/bidsmreye/visualize.py index fc1c565..6736d3e 100644 --- a/bidsmreye/visualize.py +++ b/bidsmreye/visualize.py @@ -69,8 +69,6 @@ def collect_group_qc_data(cfg: Config) -> pd.DataFrame | None: with open(file.path) as f: data = json.loads(f.read()) - print(data) - df = pd.json_normalize(data) df["filename"] = Path(file.path).name df["subject"] = entities["subject"] @@ -85,8 +83,8 @@ def collect_group_qc_data(cfg: Config) -> pd.DataFrame | None: "NbDisplacementOutliers", "NbXOutliers", "NbYOutliers", - "eye1XVar", - "eye1YVar", + "XVar", + "YVar", ] try: qc_data = qc_data[cols] @@ -183,7 +181,7 @@ def group_report(cfg: Config) -> None: qc_data=qc_data, row=row, col=col, - column_names=["eye1XVar", "eye1YVar"], + column_names=["XVar", "YVar"], trace_names=["x gaze
position", "Y gaze
position"], ticktext=["X", "Y"], yaxes_title="variance (degrees2)", @@ -312,12 +310,12 @@ def plot_time_series( ) -> None: outliers = None - values_to_plot = eye_gaze_data["eye1_x_coordinate"] - outliers = eye_gaze_data["eye1_x_outliers"] + values_to_plot = eye_gaze_data["x_coordinate"] + outliers = eye_gaze_data["x_outliers"] outlier_color = "orange" if title_text == "Y": - values_to_plot = eye_gaze_data["eye1_y_coordinate"] - outliers = eye_gaze_data["eye1_y_outliers"] + values_to_plot = eye_gaze_data["y_coordinate"] + outliers = eye_gaze_data["y_outliers"] elif title_text == "displacement": values_to_plot = eye_gaze_data["displacement"] outliers = eye_gaze_data["displacement_outliers"] @@ -328,7 +326,7 @@ def plot_time_series( fig.add_trace( go.Scatter( - x=time_range(eye_gaze_data["eye_timestamp"]), + x=time_range(eye_gaze_data["timestamp"]), y=[0, 0], mode="lines", line_color="black", @@ -340,7 +338,7 @@ def plot_time_series( fig.add_trace( go.Scatter( - x=eye_gaze_data["eye_timestamp"], + x=eye_gaze_data["timestamp"], y=values_to_plot, mode="lines", line_color=line_color, @@ -353,7 +351,7 @@ def plot_time_series( if outliers is not None: fig.add_trace( go.Scatter( - x=eye_gaze_data["eye_timestamp"][outliers == 1], + x=eye_gaze_data["timestamp"][outliers == 1], y=values_to_plot[outliers == 1], mode="markers", marker_color=outlier_color, @@ -364,7 +362,7 @@ def plot_time_series( ) fig.update_xaxes( - range=time_range(eye_gaze_data["eye_timestamp"]), + range=time_range(eye_gaze_data["timestamp"]), row=row, col=col, gridcolor=GRID_COLOR, @@ -392,8 +390,8 @@ def plot_time_series( def plot_heat_map(fig: Any, eye_gaze_data: pd.DataFrame) -> None: - X = eye_gaze_data["eye1_x_coordinate"] - Y = eye_gaze_data["eye1_y_coordinate"] + X = eye_gaze_data["x_coordinate"] + Y = eye_gaze_data["y_coordinate"] x_range = value_range(X) y_range = value_range(Y) @@ -438,10 +436,10 @@ def plot_heat_map(fig: Any, eye_gaze_data: pd.DataFrame) -> None: col=3, ) - outliers = eye_gaze_data["eye1_x_outliers"] + outliers = eye_gaze_data["x_outliers"] outlier_color = "orange" add_outliers_to_heatmap(fig, X, Y, outliers, outlier_color) - outliers = eye_gaze_data["eye1_y_outliers"] + outliers = eye_gaze_data["y_outliers"] add_outliers_to_heatmap(fig, X, Y, outliers, outlier_color) outliers = eye_gaze_data["displacement_outliers"] outlier_color = "red" diff --git a/docs/source/CHANGELOG.md b/docs/source/CHANGELOG.md index 0c926a0..6202411 100644 --- a/docs/source/CHANGELOG.md +++ b/docs/source/CHANGELOG.md @@ -23,8 +23,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +* [ENH] Extra metadata have been added to the output of the `generalize` step to better align with BIDS BEP20 @Remi-Gau in https://github.com/cpp-lln-lab/bidsMReye/pull/232 + ### Changed +* [ENH] Output filenames of the prepare step has been changed to use the `timeseries` suffix and the output of the `generalize` step now include the name of the Deepmreye model used to compute them @Remi-Gau in https://github.com/cpp-lln-lab/bidsMReye/pull/232 + ### Deprecated ### Removed diff --git a/tests/conftest.py b/tests/conftest.py index 98d5ec3..ee82654 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -23,7 +23,7 @@ def data_dir(): @pytest.fixture -def output_dir(tmp_path, data_dir): +def output_dir(tmp_path, data_dir) -> Path: src_dir = data_dir / "bidsmreye" target_dir = tmp_path / "bidsmreye" target_dir.mkdir() @@ -44,8 +44,8 @@ def bidsmreye_eyetrack_tsv(output_dir): @pytest.fixture def create_basic_data(): return { - "eye1_x_coordinate": np.random.randn(400), - "eye1_y_coordinate": np.random.randn(400), + "x_coordinate": np.random.randn(400), + "y_coordinate": np.random.randn(400), } @@ -75,21 +75,21 @@ def _generate_confounds_tsv(filename): df = pd.DataFrame(create_data_with_outliers) df["displacement"] = compute_displacement( - df["eye1_x_coordinate"], - df["eye1_y_coordinate"], + df["x_coordinate"], + df["y_coordinate"], ) - df["eye1_x_outliers"] = compute_robust_outliers( - df["eye1_x_coordinate"], outlier_type="Carling" + df["x_outliers"] = compute_robust_outliers( + df["x_coordinate"], outlier_type="Carling" ) - df["eye1_y_outliers"] = compute_robust_outliers( - df["eye1_y_coordinate"], outlier_type="Carling" + df["y_outliers"] = compute_robust_outliers( + df["y_coordinate"], outlier_type="Carling" ) df["displacement_outliers"] = compute_robust_outliers( df["displacement"], outlier_type="Carling" ) cols = df.columns.tolist() - cols.insert(0, cols.pop(cols.index("eye_timestamp"))) + cols.insert(0, cols.pop(cols.index("timestamp"))) df = df[cols] df.to_csv(filename, sep="\t", index=False) @@ -101,19 +101,15 @@ def _generate_confounds_tsv(filename): def create_data_with_outliers(create_basic_data): data = create_basic_data - data["eye_timestamp"] = np.arange(400) + data["timestamp"] = np.arange(400) - eye1_x_coordinate = data["eye1_x_coordinate"] - eye1_y_coordinate = data["eye1_y_coordinate"] + x_coordinate = data["x_coordinate"] + y_coordinate = data["y_coordinate"] - data["eye1_x_coordinate"][200] = ( - eye1_x_coordinate.mean() + eye1_x_coordinate.std() * 4 - ) - data["eye1_y_coordinate"][200] = ( - eye1_y_coordinate.mean() - eye1_y_coordinate.std() * 5 - ) - data["eye1_x_coordinate"][50] = eye1_x_coordinate.mean() - eye1_x_coordinate.std() * 5 - data["eye1_y_coordinate"][50] = eye1_y_coordinate.mean() + eye1_y_coordinate.std() * 4 + data["x_coordinate"][200] = x_coordinate.mean() + x_coordinate.std() * 4 + data["y_coordinate"][200] = y_coordinate.mean() - y_coordinate.std() * 5 + data["x_coordinate"][50] = x_coordinate.mean() - x_coordinate.std() * 5 + data["y_coordinate"][50] = y_coordinate.mean() + y_coordinate.std() * 4 return data diff --git a/tests/data/bidsmreye/sub-01/func/sub-01_task-nback_space-MNI152NLin2009cAsym_desc-bidsmreye_confounds.npy b/tests/data/bidsmreye/sub-01/func/sub-01_task-nback_space-MNI152NLin2009cAsym_desc-1to6_confounds.npy similarity index 100% rename from tests/data/bidsmreye/sub-01/func/sub-01_task-nback_space-MNI152NLin2009cAsym_desc-bidsmreye_confounds.npy rename to tests/data/bidsmreye/sub-01/func/sub-01_task-nback_space-MNI152NLin2009cAsym_desc-1to6_confounds.npy diff --git a/tests/data/bidsmreye/sub-01/func/sub-01_task-nback_space-MNI152NLin2009cAsym_desc-bidsmreye_eyetrack.json b/tests/data/bidsmreye/sub-01/func/sub-01_task-nback_space-MNI152NLin2009cAsym_desc-1to6_eyetrack.json similarity index 100% rename from tests/data/bidsmreye/sub-01/func/sub-01_task-nback_space-MNI152NLin2009cAsym_desc-bidsmreye_eyetrack.json rename to tests/data/bidsmreye/sub-01/func/sub-01_task-nback_space-MNI152NLin2009cAsym_desc-1to6_eyetrack.json diff --git a/tests/data/bidsmreye/sub-01/func/sub-01_task-nback_space-MNI152NLin2009cAsym_desc-nolabel_bidsmreye.npz b/tests/data/bidsmreye/sub-01/func/sub-01_task-nback_space-MNI152NLin2009cAsym_desc-eye_bold.npz similarity index 100% rename from tests/data/bidsmreye/sub-01/func/sub-01_task-nback_space-MNI152NLin2009cAsym_desc-nolabel_bidsmreye.npz rename to tests/data/bidsmreye/sub-01/func/sub-01_task-nback_space-MNI152NLin2009cAsym_desc-eye_bold.npz diff --git a/tests/data/derivatives/bidsmreye/group_eyetrack.tsv b/tests/data/derivatives/bidsmreye/group_eyetrack.tsv index 92cc213..c41dc55 100644 --- a/tests/data/derivatives/bidsmreye/group_eyetrack.tsv +++ b/tests/data/derivatives/bidsmreye/group_eyetrack.tsv @@ -1,3 +1,3 @@ -subject filename NbDisplacementOutliers NbXOutliers NbYOutliers eye1XVar eye1YVar +subject filename NbDisplacementOutliers NbXOutliers NbYOutliers XVar YVar 9001 sub-9001_ses-1_task-rest_desc-bidsmreye_eyetrack.json 3.0 7.0 1.0 0.00016818632287251184 0.0003536839964260474 9008 sub-9008_ses-1_task-rest_desc-bidsmreye_eyetrack.json 11.0 13.0 3.0 0.005923704468120273 0.010185736784632825 diff --git a/tests/data/derivatives/bidsmreye/sub-9001/ses-1/func/sub-9001_ses-1_task-rest_desc-bidsmreye_eyetrack.json b/tests/data/derivatives/bidsmreye/sub-9001/ses-1/func/sub-9001_ses-1_task-rest_desc-1to6_eyetrack.json similarity index 52% rename from tests/data/derivatives/bidsmreye/sub-9001/ses-1/func/sub-9001_ses-1_task-rest_desc-bidsmreye_eyetrack.json rename to tests/data/derivatives/bidsmreye/sub-9001/ses-1/func/sub-9001_ses-1_task-rest_desc-1to6_eyetrack.json index 714a394..0ac8b1a 100644 --- a/tests/data/derivatives/bidsmreye/sub-9001/ses-1/func/sub-9001_ses-1_task-rest_desc-bidsmreye_eyetrack.json +++ b/tests/data/derivatives/bidsmreye/sub-9001/ses-1/func/sub-9001_ses-1_task-rest_desc-1to6_eyetrack.json @@ -2,6 +2,6 @@ "NbDisplacementOutliers": 3.0, "NbXOutliers": 7.0, "NbYOutliers": 1.0, - "eye1XVar": 0.00016818632287251184, - "eye1YVar": 0.0003536839964260474 + "XVar": 0.00016818632287251184, + "YVar": 0.0003536839964260474 } diff --git a/tests/data/derivatives/bidsmreye/sub-9007/ses-1/func/sub-9007_ses-1_task-rest_desc-bidsmreye_eyetrack.json b/tests/data/derivatives/bidsmreye/sub-9007/ses-1/func/sub-9007_ses-1_task-rest_desc-1to6_eyetrack.json similarity index 54% rename from tests/data/derivatives/bidsmreye/sub-9007/ses-1/func/sub-9007_ses-1_task-rest_desc-bidsmreye_eyetrack.json rename to tests/data/derivatives/bidsmreye/sub-9007/ses-1/func/sub-9007_ses-1_task-rest_desc-1to6_eyetrack.json index b59dadc..6ffba5f 100644 --- a/tests/data/derivatives/bidsmreye/sub-9007/ses-1/func/sub-9007_ses-1_task-rest_desc-bidsmreye_eyetrack.json +++ b/tests/data/derivatives/bidsmreye/sub-9007/ses-1/func/sub-9007_ses-1_task-rest_desc-1to6_eyetrack.json @@ -2,6 +2,6 @@ "NbDisplacementOutliers": 3.0, "NbXOutliers": 7.0, "NbYOutliers": 0.0, - "eye1XVar": 0.0004570412431083883, - "eye1YVar": 0.0023510466096491 + "XVar": 0.0004570412431083883, + "YVar": 0.0023510466096491 } diff --git a/tests/data/derivatives/bidsmreye/sub-9008/ses-1/func/sub-9008_ses-1_task-rest_desc-bidsmreye_eyetrack.json b/tests/data/derivatives/bidsmreye/sub-9008/ses-1/func/sub-9008_ses-1_task-rest_desc-1to6_eyetrack.json similarity index 54% rename from tests/data/derivatives/bidsmreye/sub-9008/ses-1/func/sub-9008_ses-1_task-rest_desc-bidsmreye_eyetrack.json rename to tests/data/derivatives/bidsmreye/sub-9008/ses-1/func/sub-9008_ses-1_task-rest_desc-1to6_eyetrack.json index 232d2cd..a84acdd 100644 --- a/tests/data/derivatives/bidsmreye/sub-9008/ses-1/func/sub-9008_ses-1_task-rest_desc-bidsmreye_eyetrack.json +++ b/tests/data/derivatives/bidsmreye/sub-9008/ses-1/func/sub-9008_ses-1_task-rest_desc-1to6_eyetrack.json @@ -2,6 +2,6 @@ "NbDisplacementOutliers": 11.0, "NbXOutliers": 13.0, "NbYOutliers": 3.0, - "eye1XVar": 0.005923704468120273, - "eye1YVar": 0.010185736784632825 + "XVar": 0.005923704468120273, + "YVar": 0.010185736784632825 } diff --git a/tests/data/derivatives/bidsmreye/sub-9013/ses-1/func/sub-9013_ses-1_task-rest_desc-bidsmreye_eyetrack.json b/tests/data/derivatives/bidsmreye/sub-9013/ses-1/func/sub-9013_ses-1_task-rest_desc-1to6_eyetrack.json similarity index 53% rename from tests/data/derivatives/bidsmreye/sub-9013/ses-1/func/sub-9013_ses-1_task-rest_desc-bidsmreye_eyetrack.json rename to tests/data/derivatives/bidsmreye/sub-9013/ses-1/func/sub-9013_ses-1_task-rest_desc-1to6_eyetrack.json index efe32d5..5d4db74 100644 --- a/tests/data/derivatives/bidsmreye/sub-9013/ses-1/func/sub-9013_ses-1_task-rest_desc-bidsmreye_eyetrack.json +++ b/tests/data/derivatives/bidsmreye/sub-9013/ses-1/func/sub-9013_ses-1_task-rest_desc-1to6_eyetrack.json @@ -2,6 +2,6 @@ "NbDisplacementOutliers": 6.0, "NbXOutliers": 3.0, "NbYOutliers": 2.0, - "eye1XVar": 0.000979110204728377, - "eye1YVar": 0.004960593708823918 + "XVar": 0.000979110204728377, + "YVar": 0.004960593708823918 } diff --git a/tests/data/derivatives/bidsmreye/sub-9016/ses-2/func/sub-9016_ses-2_task-rest_desc-bidsmreye_eyetrack.json b/tests/data/derivatives/bidsmreye/sub-9016/ses-2/func/sub-9016_ses-2_task-rest_desc-1to6_eyetrack.json similarity index 53% rename from tests/data/derivatives/bidsmreye/sub-9016/ses-2/func/sub-9016_ses-2_task-rest_desc-bidsmreye_eyetrack.json rename to tests/data/derivatives/bidsmreye/sub-9016/ses-2/func/sub-9016_ses-2_task-rest_desc-1to6_eyetrack.json index d14cbcd..77f9f24 100644 --- a/tests/data/derivatives/bidsmreye/sub-9016/ses-2/func/sub-9016_ses-2_task-rest_desc-bidsmreye_eyetrack.json +++ b/tests/data/derivatives/bidsmreye/sub-9016/ses-2/func/sub-9016_ses-2_task-rest_desc-1to6_eyetrack.json @@ -2,6 +2,6 @@ "NbDisplacementOutliers": 9.0, "NbXOutliers": 0.0, "NbYOutliers": 0.0, - "eye1XVar": 0.0008164079508936875, - "eye1YVar": 0.013005047983662045 + "XVar": 0.0008164079508936875, + "YVar": 0.013005047983662045 } diff --git a/tests/data/derivatives/bidsmreye/sub-9022/ses-2/func/sub-9022_ses-2_task-rest_desc-bidsmreye_eyetrack.json b/tests/data/derivatives/bidsmreye/sub-9022/ses-2/func/sub-9022_ses-2_task-rest_desc-1to6_eyetrack.json similarity index 54% rename from tests/data/derivatives/bidsmreye/sub-9022/ses-2/func/sub-9022_ses-2_task-rest_desc-bidsmreye_eyetrack.json rename to tests/data/derivatives/bidsmreye/sub-9022/ses-2/func/sub-9022_ses-2_task-rest_desc-1to6_eyetrack.json index a2925f2..ffc4c6c 100644 --- a/tests/data/derivatives/bidsmreye/sub-9022/ses-2/func/sub-9022_ses-2_task-rest_desc-bidsmreye_eyetrack.json +++ b/tests/data/derivatives/bidsmreye/sub-9022/ses-2/func/sub-9022_ses-2_task-rest_desc-1to6_eyetrack.json @@ -2,6 +2,6 @@ "NbDisplacementOutliers": 10.0, "NbXOutliers": 0.0, "NbYOutliers": 3.0, - "eye1XVar": 0.00725997346654229, - "eye1YVar": 0.02005290083830694 + "XVar": 0.00725997346654229, + "YVar": 0.02005290083830694 } diff --git a/tests/data/ds000201-der/sub-9001/ses-1/func/sub-9001_ses-1_task-rest_desc-preproc_eyetrack.tsv b/tests/data/ds000201-der/sub-9001/ses-1/func/sub-9001_ses-1_task-rest_desc-preproc_eyetrack.tsv index 5b579d7..ce525f9 100644 --- a/tests/data/ds000201-der/sub-9001/ses-1/func/sub-9001_ses-1_task-rest_desc-preproc_eyetrack.tsv +++ b/tests/data/ds000201-der/sub-9001/ses-1/func/sub-9001_ses-1_task-rest_desc-preproc_eyetrack.tsv @@ -1,4 +1,4 @@ -eye_timestamp eye1_x_coordinate eye1_y_coordinate eye1_pupil_size pup_sizeDet blinks eye1_x_velocity eye1_y_velocity eye1_pupil_velocity vel_pup_sizeDet eye1_x_coordinate_squared eye1_y_coordinate_squared eye1_pupil_size_squared pup_sizeDet2 gaze_amplitude eye1_x_coordinate_squared_velocity eye1_y_coordinate_squared_velocity eye1_pupil_size_squared_velocity vel_pup_sizeDet2 gaze_amplitude_velocity +timestamp x_coordinate y_coordinate eye1_pupil_size pup_sizeDet blinks eye1_x_velocity eye1_y_velocity eye1_pupil_velocity vel_pup_sizeDet x_coordinate_squared y_coordinate_squared eye1_pupil_size_squared pup_sizeDet2 gaze_amplitude x_coordinate_squared_velocity y_coordinate_squared_velocity eye1_pupil_size_squared_velocity vel_pup_sizeDet2 gaze_amplitude_velocity 0 -0.0125876420525764 -0.0296409266355282 0.01256773460495163 0.006064294761973154 0 0.00784167192564718 -0.02984870375253712 -0.006659375729763218 -0.0001440730074933779 0.0002998521873619699 0.002114566224108526 0.0001964818109893877 8.10157559729575e-05 0.002414418411470494 0.09585696024660084 0.3436842393645932 0.02647713841622712 4.76404146549535e-06 0.4395411996111939 2.5 -0.006685255001682728 -0.03048902997978127 -0.001896792768960595 -0.007466956189474277 0.1866666666666667 -0.188300615139441 0.1273722758356769 0.04269587245031523 0.0005315521161134626 0.0002528059019962128 0.001388388613594129 4.371414434221871e-05 8.192300222851202e-05 0.001641194515590341 0.3744926175270962 0.4573105852300601 0.03437445053772459 5.492458821402291e-06 0.8318032027571568 5 0.03440434491048539 -0.002900281017239187 -0.001908296066575723 -0.003347569058012667 0.3133333333333334 -0.009824448908201205 -0.06865083053613513 0.01513178930836155 0.0001615765211978517 0.004519955746989152 0.0008324283163660172 5.862081325242659e-05 3.843647274076083e-05 0.00535238406335517 0.3307139629893529 1.165021972018996 0.08295360896939702 1.225080143223143e-05 1.495735935008348 diff --git a/tests/data/ds000201-der/sub-9007/ses-1/func/sub-9007_ses-1_task-rest_desc-preproc_eyetrack.tsv b/tests/data/ds000201-der/sub-9007/ses-1/func/sub-9007_ses-1_task-rest_desc-preproc_eyetrack.tsv index a052e5a..1837669 100644 --- a/tests/data/ds000201-der/sub-9007/ses-1/func/sub-9007_ses-1_task-rest_desc-preproc_eyetrack.tsv +++ b/tests/data/ds000201-der/sub-9007/ses-1/func/sub-9007_ses-1_task-rest_desc-preproc_eyetrack.tsv @@ -1,4 +1,4 @@ -eye_timestamp eye1_x_coordinate eye1_y_coordinate eye1_pupil_size pup_sizeDet blinks eye1_x_velocity eye1_y_velocity eye1_pupil_velocity vel_pup_sizeDet eye1_x_coordinate_squared eye1_y_coordinate_squared eye1_pupil_size_squared pup_sizeDet2 gaze_amplitude eye1_x_coordinate_squared_velocity eye1_y_coordinate_squared_velocity eye1_pupil_size_squared_velocity vel_pup_sizeDet2 gaze_amplitude_velocity +timestamp x_coordinate y_coordinate eye1_pupil_size pup_sizeDet blinks eye1_x_velocity eye1_y_velocity eye1_pupil_velocity vel_pup_sizeDet x_coordinate_squared y_coordinate_squared eye1_pupil_size_squared pup_sizeDet2 gaze_amplitude x_coordinate_squared_velocity y_coordinate_squared_velocity eye1_pupil_size_squared_velocity vel_pup_sizeDet2 gaze_amplitude_velocity 0 -0.02961961754580149 -0.09933694208530197 -0.002417159943411741 0.001216704517905867 0.09333333333333334 -0.04193736016811529 -0.05722690275269908 0.07080778454454553 0.001178966616774533 0.001076993116474701 0.01316094561873952 8.749351094978264e-05 9.027428470726289e-05 0.01423793873521422 0.3119753885607867 0.2676051991829836 0.08457300698841376 2.311489951539797e-05 0.5795805877437705 2.5 -0.01608119770685977 -0.05342539736608681 0.00550354602532982 0.01037419740255071 0 -0.04167466552931883 0.09839747852109026 0.003553957462571309 4.76776297407822e-05 0.0004706734118014426 0.003586638123239135 8.640121564505361e-05 0.0001561160165094076 0.004057311535040576 0.4720685623683645 0.5931237142241347 0.08765747299084191 2.066558999451649e-05 1.0651922765925 5 -0.01716212344814437 -0.02112737323959944 0.0009855481271891743 0.006647177741806887 0.08666666666666667 0.01149125052778946 -0.08229100503134314 0.01170426995025856 0.0001298411663927714 0.0004301416063785495 0.001278284989896798 6.853012092545004e-05 0.000122331123432818 0.001708426596275347 0.2341330709894196 0.2999777752920794 0.06136576422478598 1.627920732179061e-05 0.5341108462814987 diff --git a/tests/data/ds000201-der/sub-9008/ses-1/func/sub-9008_ses-1_task-rest_desc-preproc_eyetrack.tsv b/tests/data/ds000201-der/sub-9008/ses-1/func/sub-9008_ses-1_task-rest_desc-preproc_eyetrack.tsv index 0a7b106..302c9e0 100644 --- a/tests/data/ds000201-der/sub-9008/ses-1/func/sub-9008_ses-1_task-rest_desc-preproc_eyetrack.tsv +++ b/tests/data/ds000201-der/sub-9008/ses-1/func/sub-9008_ses-1_task-rest_desc-preproc_eyetrack.tsv @@ -1,4 +1,4 @@ -eye_timestamp eye1_x_coordinate eye1_y_coordinate eye1_pupil_size pup_sizeDet blinks eye1_x_velocity eye1_y_velocity eye1_pupil_velocity vel_pup_sizeDet eye1_x_coordinate_squared eye1_y_coordinate_squared eye1_pupil_size_squared pup_sizeDet2 gaze_amplitude eye1_x_coordinate_squared_velocity eye1_y_coordinate_squared_velocity eye1_pupil_size_squared_velocity vel_pup_sizeDet2 gaze_amplitude_velocity +timestamp x_coordinate y_coordinate eye1_pupil_size pup_sizeDet blinks eye1_x_velocity eye1_y_velocity eye1_pupil_velocity vel_pup_sizeDet x_coordinate_squared y_coordinate_squared eye1_pupil_size_squared pup_sizeDet2 gaze_amplitude x_coordinate_squared_velocity y_coordinate_squared_velocity eye1_pupil_size_squared_velocity vel_pup_sizeDet2 gaze_amplitude_velocity 0 0.008553191340153221 0.0705885224617267 0.005594641699716886 0.01285344308330689 0.2933333333333333 -0.101909589141193 -0.3530480193201198 0.1587813803104909 0.002275560343913671 0.009210565373408319 0.00674792086978221 0.0001715419719469159 0.0003479492028882619 0.01595848624319053 1.234359599295059 0.9383148840948606 0.1618343444060233 3.061050948110752e-05 2.17267448338992 2.5 0.00139634679541902 0.0896180095962945 0.007507317431539402 0.01594218364710845 0 -0.1012899998904163 0.3003007417549582 -0.07767498391642574 -0.001186919672575744 0.0005588882605189964 0.009543284550326778 0.0001015916702457746 0.0003381956793067698 0.01010217281084577 0.5160985118193879 0.935380568480216 0.07200980968400868 1.555120689904701e-05 1.451479080299604 5 -0.02195628918960071 0.1494186406785151 -0.006441085915958216 0.00343183908336681 0.1466666666666667 0.2067514142190904 -0.02876912133692314 0.04529490877097057 0.0009667570404181911 0.001216620193579442 0.02566612766457166 0.0004086511804082783 0.0004534669727884213 0.02688274785815107 1.346244711978686 0.4786540015508846 0.08606406167224334 2.095336214098603e-05 1.824898713529572 diff --git a/tests/data/ds000201-der/sub-9013/ses-1/func/sub-9013_ses-1_task-rest_desc-preproc_eyetrack.tsv b/tests/data/ds000201-der/sub-9013/ses-1/func/sub-9013_ses-1_task-rest_desc-preproc_eyetrack.tsv index 52e6eb8..12b89aa 100644 --- a/tests/data/ds000201-der/sub-9013/ses-1/func/sub-9013_ses-1_task-rest_desc-preproc_eyetrack.tsv +++ b/tests/data/ds000201-der/sub-9013/ses-1/func/sub-9013_ses-1_task-rest_desc-preproc_eyetrack.tsv @@ -1,4 +1,4 @@ -eye_timestamp eye1_x_coordinate eye1_y_coordinate eye1_pupil_size pup_sizeDet blinks eye1_x_velocity eye1_y_velocity eye1_pupil_velocity vel_pup_sizeDet eye1_x_coordinate_squared eye1_y_coordinate_squared eye1_pupil_size_squared pup_sizeDet2 gaze_amplitude eye1_x_coordinate_squared_velocity eye1_y_coordinate_squared_velocity eye1_pupil_size_squared_velocity vel_pup_sizeDet2 gaze_amplitude_velocity +timestamp x_coordinate y_coordinate eye1_pupil_size pup_sizeDet blinks eye1_x_velocity eye1_y_velocity eye1_pupil_velocity vel_pup_sizeDet x_coordinate_squared y_coordinate_squared eye1_pupil_size_squared pup_sizeDet2 gaze_amplitude x_coordinate_squared_velocity y_coordinate_squared_velocity eye1_pupil_size_squared_velocity vel_pup_sizeDet2 gaze_amplitude_velocity 0 0.1228439459098761 -0.04363106645129554 0.01055186691460473 0.02810569314647659 0.18 -0.02252483727090581 0.1107483728473178 -0.007592258645792173 -0.000132783286776813 0.01885023481192407 0.002910545691325619 0.0002830960535861867 0.00111908784628542 0.02176078050324968 0.02152312948578106 0.1602121720193706 0.008077441536998249 2.219063968434526e-06 0.1817353015051516 2.5 0.1241509146977424 0.004410098154503896 0.03865407754229901 0.05658444406603658 0.2266666666666667 -0.006195326027977333 -0.0269121875040174 0.01928957058441428 0.0002580935234283905 0.02025972378517528 0.0009874678853206466 0.001937111399051495 0.004153650850580535 0.02124719167049592 0.09882695276457494 0.3735188483309257 0.01504314155520032 5.859011266882711e-06 0.4723458010955005 5 -0.1099876605127478 0.06437858577873816 -0.01363444975704567 -0.02010589091767669 0.1266666666666667 0.1594527191763548 0.05294005891376504 0.043518947957084 0.0005554515599762832 0.02489845505895359 0.00805699654067559 0.001192982435956677 0.002183006101791283 0.0329554515996292 0.08102927368260926 0.1371981787178698 0.01071604742660882 3.254273865972635e-06 0.2182274524004788 diff --git a/tests/data/ds000201-der/sub-9016/ses-2/func/sub-9016_ses-2_task-rest_desc-preproc_eyetrack.tsv b/tests/data/ds000201-der/sub-9016/ses-2/func/sub-9016_ses-2_task-rest_desc-preproc_eyetrack.tsv index 7964784..19fd273 100644 --- a/tests/data/ds000201-der/sub-9016/ses-2/func/sub-9016_ses-2_task-rest_desc-preproc_eyetrack.tsv +++ b/tests/data/ds000201-der/sub-9016/ses-2/func/sub-9016_ses-2_task-rest_desc-preproc_eyetrack.tsv @@ -1,4 +1,4 @@ -eye_timestamp eye1_x_coordinate eye1_y_coordinate eye1_pupil_size pup_sizeDet blinks eye1_x_velocity eye1_y_velocity eye1_pupil_velocity vel_pup_sizeDet eye1_x_coordinate_squared eye1_y_coordinate_squared eye1_pupil_size_squared pup_sizeDet2 gaze_amplitude eye1_x_coordinate_squared_velocity eye1_y_coordinate_squared_velocity eye1_pupil_size_squared_velocity vel_pup_sizeDet2 gaze_amplitude_velocity +timestamp x_coordinate y_coordinate eye1_pupil_size pup_sizeDet blinks eye1_x_velocity eye1_y_velocity eye1_pupil_velocity vel_pup_sizeDet x_coordinate_squared y_coordinate_squared eye1_pupil_size_squared pup_sizeDet2 gaze_amplitude x_coordinate_squared_velocity y_coordinate_squared_velocity eye1_pupil_size_squared_velocity vel_pup_sizeDet2 gaze_amplitude_velocity 0 0.05080173701370743 0.06819163544469703 0.02131508519450024 0.01321399989151944 0 0.001786144088891413 -0.01745877281674369 -0.004488518458448053 -7.760062671769417e-05 0.002602941272289256 0.005094630468217914 0.0004952938417376925 0.0002150844110146307 0.007697571740507165 0.05871050836447354 0.1446082373062025 0.009436925495505653 2.695767915863929e-06 0.2033187456706759 2.5 0.03953090564575539 0.05491368885776839 0.01799975186116691 0.01082793748630915 0 -0.00363471425934407 -0.007380488777538932 -0.0005378319784445608 -7.362240183951842e-06 0.001619552939074273 0.003079622990671467 0.0003263234332858038 0.0001194374690282349 0.004699175929745742 0.06926143037130932 0.09163782871459833 0.005145073131372355 1.619935566472441e-06 0.1608992590859076 5 0.03406140761113666 0.0478177422708398 0.01848841852783357 0.01177379586170007 0 4.652169018835417e-05 -0.008529685877584544 0.0009359746301986024 1.908348490390034e-05 0.001181405655229642 0.00247877007335268 0.0003498506089936732 0.000146620231429283 0.003660175728582323 0.08384247834010836 0.1065807588393148 0.008891759863413449 2.895749069289884e-06 0.1904232371794231 diff --git a/tests/data/ds000201-der/sub-9022/ses-2/func/sub-9022_ses-2_task-rest_desc-preproc_eyetrack.tsv b/tests/data/ds000201-der/sub-9022/ses-2/func/sub-9022_ses-2_task-rest_desc-preproc_eyetrack.tsv index 54838ef..b604b95 100644 --- a/tests/data/ds000201-der/sub-9022/ses-2/func/sub-9022_ses-2_task-rest_desc-preproc_eyetrack.tsv +++ b/tests/data/ds000201-der/sub-9022/ses-2/func/sub-9022_ses-2_task-rest_desc-preproc_eyetrack.tsv @@ -1,4 +1,4 @@ -eye_timestamp eye1_x_coordinate eye1_y_coordinate eye1_pupil_size pup_sizeDet blinks eye1_x_velocity eye1_y_velocity eye1_pupil_velocity vel_pup_sizeDet eye1_x_coordinate_squared eye1_y_coordinate_squared eye1_pupil_size_squared pup_sizeDet2 gaze_amplitude eye1_x_coordinate_squared_velocity eye1_y_coordinate_squared_velocity eye1_pupil_size_squared_velocity vel_pup_sizeDet2 gaze_amplitude_velocity +timestamp x_coordinate y_coordinate eye1_pupil_size pup_sizeDet blinks eye1_x_velocity eye1_y_velocity eye1_pupil_velocity vel_pup_sizeDet x_coordinate_squared y_coordinate_squared eye1_pupil_size_squared pup_sizeDet2 gaze_amplitude x_coordinate_squared_velocity y_coordinate_squared_velocity eye1_pupil_size_squared_velocity vel_pup_sizeDet2 gaze_amplitude_velocity 0 0.05779156756212137 -0.1518478112283952 0.01242829863969288 -0.00880086782663474 0.1533333333333333 0.03042058157538671 -0.1200624951443147 0.0004740280484461811 -0.0002038516829511285 0.003868726397083114 0.02595650739037664 0.0002875985532907811 0.0002977715512579605 0.02982523378745978 0.178547629632196 0.8001797869887977 0.06086167202040568 9.522580184226476e-06 0.9787274166209932 2.5 0.07593255377826967 -0.1298657381849509 0.0444442271448055 0.02371389257994604 0 0.00498040886594632 -0.00566692074679837 0.02019035238612569 0.0003244194133972863 0.005842226846629842 0.01721472803850731 0.002185920879387953 0.0007865675992002487 0.02305695488513716 0.1444812523367608 0.2111061210226527 0.01841957070441271 4.931320528091898e-06 0.3555873733594134 5 0.04892607272015095 -0.079705961670151 0.02581197322076216 0.01165031302307442 0.1 -0.00427358678954674 -0.09269234357173772 0.02147724226086499 0.0002125299572012795 0.003991110176880175 0.01848393184429225 0.001974235897182295 0.0007188259323829993 0.02247504202117244 0.6292477403990286 2.636142880327783 0.4084318474311071 7.078686654631587e-05 3.26539062072681 diff --git a/tests/test_bids_utils.py b/tests/test_bids_utils.py index 900fd46..b417a52 100644 --- a/tests/test_bids_utils.py +++ b/tests/test_bids_utils.py @@ -87,7 +87,7 @@ def test_save_sampling_frequency_to_json(data_dir, pybids_test_dataset): ) source = "foo" save_sampling_frequency_to_json(layout_in, bf[0], source) - sidecar_name = create_bidsname(layout_in, bf[0].path, "confounds_json") + sidecar_name = create_bidsname(layout_in, bf[0].path, "no_label_json") with open(sidecar_name) as f: content = json.load(f) assert content["Sources"][0] == "foo" diff --git a/tests/test_generalize.py b/tests/test_generalize.py index 21e621c..906f209 100644 --- a/tests/test_generalize.py +++ b/tests/test_generalize.py @@ -1,6 +1,6 @@ from __future__ import annotations -import shutil +import json from bidsmreye.bids_utils import get_dataset_layout from bidsmreye.generalize import convert_confounds @@ -13,14 +13,12 @@ def test_convert_confounds(output_dir): output_dir / "sub-01" / "func" - / "sub-01_task-nback_space-MNI152NLin2009cAsym_desc-bidsmreye_confounds.npy" + / "sub-01_task-nback_space-MNI152NLin2009cAsym_desc-1to6_confounds.npy" ) - shutil.copy(file, file.with_suffix(".bak")) + file.parent.mkdir(parents=True, exist_ok=True) + with open(file.with_suffix(".json"), "w") as f: + json.dump({"SamplingFrequency": 2.0}, f) confound_name = convert_confounds(layout_out, file) assert confound_name.is_file() - - confound_name.unlink() - shutil.copy(file.with_suffix(".bak"), file) - file.with_suffix(".bak").unlink() diff --git a/tests/test_prepare.py b/tests/test_prepare.py index cbb5637..6e6bd8d 100644 --- a/tests/test_prepare.py +++ b/tests/test_prepare.py @@ -20,8 +20,6 @@ def test_combine_data_with_empty_labels(output_dir): assert no_label_file.exists() - output_file = create_bidsname(layout_out, file, "no_label") + output_file = create_bidsname(layout_out, file, "no_label_bold") file_to_move = Path(layout_out.root) / ".." / "bidsmreye" / output_file.name assert no_label_file == file_to_move - - no_label_file.unlink() diff --git a/tests/test_visualize.py b/tests/test_visualize.py index ab97ba1..355a667 100644 --- a/tests/test_visualize.py +++ b/tests/test_visualize.py @@ -45,7 +45,7 @@ def test_group_report_missing_qc(tmp_path, data_dir): / "sub-9001" / "ses-1" / "func" - / "sub-9001_ses-1_task-rest_desc-bidsmreye_eyetrack.json" + / "sub-9001_ses-1_task-rest_desc-1to6_eyetrack.json" ) with open(file_to_modify, "w") as f: