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

[FIX] Use repetition time from BIDS metadata instead of nifti header #218

Merged
merged 1 commit into from
Aug 5, 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
17 changes: 9 additions & 8 deletions bidsmreye/bids_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
from pathlib import Path
from typing import Any

import nibabel as nib
from bids import BIDSLayout # type: ignore
from bids.layout import BIDSFile

from bidsmreye._version import __version__
from bidsmreye.configuration import (
Expand Down Expand Up @@ -143,15 +143,16 @@


def save_sampling_frequency_to_json(
layout_out: BIDSLayout, img: str, source: str
layout_out: BIDSLayout, img: BIDSFile, source: str
) -> None:
func_img = nib.load(img)
header = func_img.header
sampling_frequency = header.get_zooms()[3]
if sampling_frequency <= 1:
log.warning(f"Found a repetition time of {sampling_frequency} seconds.")
metadata = img.get_metadata()
repetition_time = metadata["RepetitionTime"]
# TODO handle rare edge case where preprocessed data
# does not contain RepetitionTime metadata
if repetition_time <= 1:
log.warning(f"Found a repetition time of {repetition_time} seconds.")

Check warning on line 153 in bidsmreye/bids_utils.py

View check run for this annotation

Codecov / codecov/patch

bidsmreye/bids_utils.py#L153

Added line #L153 was not covered by tests
create_sidecar(
layout_out, img, SamplingFrequency=1 / float(sampling_frequency), source=source
layout_out, img.path, SamplingFrequency=1 / float(repetition_time), source=source
)


Expand Down
9 changes: 4 additions & 5 deletions bidsmreye/generalize.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,19 +158,18 @@
this_filter = set_this_filter(cfg, subject_label, "no_label")

bf = layout_out.get(
return_type="filename",
regex_search=True,
**this_filter,
)

check_if_file_found(bf, this_filter, layout_out)

for file in bf:
log.info(f"Processing file: {Path(file).name}")
log.info(f"Processing file: {Path(file.path).name}")

Check warning on line 168 in bidsmreye/generalize.py

View check run for this annotation

Codecov / codecov/patch

bidsmreye/generalize.py#L168

Added line #L168 was not covered by tests

print("\n")
generators = data_generator.create_generators([file], [file])
generators = (*generators, [file], [file])
generators = data_generator.create_generators([file.path], [file.path])
generators = (*generators, [file.path], [file.path])

Check warning on line 172 in bidsmreye/generalize.py

View check run for this annotation

Codecov / codecov/patch

bidsmreye/generalize.py#L171-L172

Added lines #L171 - L172 were not covered by tests
print("\n")

opts = model_opts.get_opts()
Expand Down Expand Up @@ -200,7 +199,7 @@
percentile_cut=80,
)

create_confounds_tsv(layout_out, file, subject_label)
create_confounds_tsv(layout_out, file.path, subject_label)

Check warning on line 202 in bidsmreye/generalize.py

View check run for this annotation

Codecov / codecov/patch

bidsmreye/generalize.py#L202

Added line #L202 was not covered by tests


def generalize(cfg: Config) -> None:
Expand Down
26 changes: 15 additions & 11 deletions bidsmreye/prepare_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import numpy as np
from bids import BIDSLayout # type: ignore
from bids.layout import BIDSFile
from deepmreye import preprocess

from bidsmreye.bids_utils import (
Expand Down Expand Up @@ -131,7 +132,6 @@
this_filter = set_this_filter(cfg, subject_label, "bold")

bf = layout_in.get(
return_type="filename",
regex_search=True,
**this_filter,
)
Expand All @@ -143,12 +143,14 @@


def prepapre_image(
cfg: Config, layout_in: BIDSLayout, layout_out: BIDSLayout, img: str
cfg: Config, layout_in: BIDSLayout, layout_out: BIDSLayout, img: BIDSFile
) -> None:
"""Preprocess a single functional image."""
report_name = create_bidsname(layout_out, filename=img, filetype="report")
mask_name = create_bidsname(layout_out, filename=img, filetype="mask")
output_file = create_bidsname(layout_out, Path(img), "no_label")
img_path = img.path

Check warning on line 149 in bidsmreye/prepare_data.py

View check run for this annotation

Codecov / codecov/patch

bidsmreye/prepare_data.py#L149

Added line #L149 was not covered by tests

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")

Check warning on line 153 in bidsmreye/prepare_data.py

View check run for this annotation

Codecov / codecov/patch

bidsmreye/prepare_data.py#L151-L153

Added lines #L151 - L153 were not covered by tests

if (
not cfg.force
Expand All @@ -159,21 +161,23 @@
log.debug(
"Output for the following file already exists. "
"Use the '--force' option to overwrite. "
f"\n '{Path(img).name}'"
f"\n '{Path(img_path).name}'"
)
return

log.info(f"Processing file: {Path(img).name}")
log.info(f"Processing file: {Path(img_path).name}")

Check warning on line 168 in bidsmreye/prepare_data.py

View check run for this annotation

Codecov / codecov/patch

bidsmreye/prepare_data.py#L168

Added line #L168 was not covered by tests

coregister_and_extract_data(img, non_linear_coreg=cfg.non_linear_coreg)
coregister_and_extract_data(img_path, non_linear_coreg=cfg.non_linear_coreg)

Check warning on line 170 in bidsmreye/prepare_data.py

View check run for this annotation

Codecov / codecov/patch

bidsmreye/prepare_data.py#L170

Added line #L170 was not covered by tests

deepmreye_mask_report = get_deepmreye_filename(layout_in, img=img, filetype="report")
deepmreye_mask_report = get_deepmreye_filename(

Check warning on line 172 in bidsmreye/prepare_data.py

View check run for this annotation

Codecov / codecov/patch

bidsmreye/prepare_data.py#L172

Added line #L172 was not covered by tests
layout_in, img=img_path, filetype="report"
)
move_file(deepmreye_mask_report, report_name)

deepmreye_mask_name = get_deepmreye_filename(layout_in, img=img, filetype="mask")
deepmreye_mask_name = get_deepmreye_filename(layout_in, img=img_path, filetype="mask")

Check warning on line 177 in bidsmreye/prepare_data.py

View check run for this annotation

Codecov / codecov/patch

bidsmreye/prepare_data.py#L177

Added line #L177 was not covered by tests
move_file(deepmreye_mask_name, mask_name)

source = str(Path(img).relative_to(layout_in.root))
source = str(Path(img_path).relative_to(layout_in.root))

Check warning on line 180 in bidsmreye/prepare_data.py

View check run for this annotation

Codecov / codecov/patch

bidsmreye/prepare_data.py#L180

Added line #L180 was not covered by tests
save_sampling_frequency_to_json(layout_out, img=img, source=source)

combine_data_with_empty_labels(layout_out, mask_name)
Expand Down
3 changes: 1 addition & 2 deletions bidsmreye/quality_control.py
Original file line number Diff line number Diff line change
Expand Up @@ -218,15 +218,14 @@ def qc_subject(
this_filter = set_this_filter(cfg, subject_label, "eyetrack")

bf = layout_in.get(
return_type="filename",
regex_search=True,
**this_filter,
)

check_if_file_found(bf, this_filter, layout_in)

for file in bf:
perform_quality_control(cfg, layout_in, file, layout_out)
perform_quality_control(cfg, layout_in, file.path, layout_out)


def compute_robust_outliers(
Expand Down
9 changes: 6 additions & 3 deletions bidsmreye/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from typing import Any

from bids import BIDSLayout # type: ignore
from bids.layout import BIDSFile
from rich.progress import (
BarColumn,
MofNCompleteColumn,
Expand Down Expand Up @@ -63,11 +64,13 @@ def add_sidecar_in_root(layout_out: BIDSLayout) -> None:
json.dump(content, open(sidecar_name, "w"), indent=4)


def check_if_file_found(bf: Any, this_filter: dict[str, Any], layout: BIDSLayout) -> None:
if len(bf) == 0:
def check_if_file_found(
bf: list[BIDSFile], this_filter: dict[str, Any], layout: BIDSLayout
) -> None:
if not bf:
log.warning(f"No file found for filter {this_filter}")
else:
to_print = [str(Path(x).relative_to(layout.root)) for x in bf]
to_print = [str(Path(x.path).relative_to(layout.root)) for x in bf]
log.debug(f"Found files\n{to_print}")


Expand Down
9 changes: 4 additions & 5 deletions bidsmreye/visualize.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ def collect_group_qc_data(cfg: Config) -> pd.DataFrame | None:
this_filter = set_this_filter(cfg, subjects, "eyetrack_qc")

bf = layout.get(
return_type="filename",
regex_search=True,
**this_filter,
)
Expand All @@ -63,15 +62,15 @@ def collect_group_qc_data(cfg: Config) -> pd.DataFrame | None:

qc_data = None
for i, file in enumerate(bf):
log.info(f"Processing file: {file}")
log.info(f"Processing file: {file.path}")

entities = layout.parse_file_entities(file)
entities = layout.parse_file_entities(file.path)

with open(file) as f:
with open(file.path) as f:
data = json.loads(f.read())

df = pd.json_normalize(data)
df["filename"] = Path(file).name
df["filename"] = Path(file.path).name
df["subject"] = entities["subject"]
qc_data = df if i == 0 else pd.concat([qc_data, df], sort=False)

Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ module = [
ignore_missing_imports = true
module = [
'attrs.*',
'bids.layout.*',
"bidsmreye._version",
'chevron.*',
'deepmreye.*',
Expand Down
3 changes: 1 addition & 2 deletions tests/test_bids_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,13 +82,12 @@ def test_save_sampling_frequency_to_json(data_dir, pybids_test_dataset):
this_filter = set_this_filter(cfg, "01", "bold")

bf = layout_in.get(
return_type="filename",
regex_search=True,
**this_filter,
)
source = "foo"
save_sampling_frequency_to_json(layout_in, bf[0], source)
sidecar_name = create_bidsname(layout_in, bf[0], "confounds_json")
sidecar_name = create_bidsname(layout_in, bf[0].path, "confounds_json")
with open(sidecar_name) as f:
content = json.load(f)
assert content["Sources"][0] == "foo"
Expand Down