Skip to content

Commit

Permalink
Merge pull request #72 from Remi-Gau/templates
Browse files Browse the repository at this point in the history
[ENH] add support for perf, meeg, pet templates
  • Loading branch information
Remi-Gau committed Feb 7, 2024
2 parents 97bb9ed + 641a017 commit 0a0fc32
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 15 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
bids-examples
report.txt

# do not track _version.py for hatch
bids/ext/reports/_version.py
Expand Down
73 changes: 65 additions & 8 deletions bids/ext/reports/parsing.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ def func_info(files: list[BIDSFile], config: dict[str, dict[str, str]], layout:
A dictionary with relevant information regarding sequences, sequence
variants, phase encoding directions, and task names.
layout : :obj:`bids.layout.BIDSLayout`
Layout object for a BIDS dataset.
Returns
-------
desc : :obj:`str`
Expand Down Expand Up @@ -131,6 +134,9 @@ def anat_info(files: list[BIDSFile], config: dict[str, dict[str, str]], layout:
A dictionary with relevant information regarding sequences, sequence
variants, phase encoding directions, and task names.
layout : :obj:`bids.layout.BIDSLayout`
Layout object for a BIDS dataset.
Returns
-------
desc : :obj:`str`
Expand Down Expand Up @@ -167,6 +173,9 @@ def dwi_info(files: list[BIDSFile], config: dict[str, dict[str, str]], layout: B
A dictionary with relevant information regarding sequences, sequence
variants, phase encoding directions, and task names.
layout : :obj:`bids.layout.BIDSLayout`
Layout object for a BIDS dataset.
Returns
-------
desc : :obj:`str`
Expand Down Expand Up @@ -196,21 +205,22 @@ def dwi_info(files: list[BIDSFile], config: dict[str, dict[str, str]], layout: B
return templates.dwi_info(desc_data)


def fmap_info(layout: BIDSLayout, files: list[BIDSFile], config: dict[str, dict[str, str]]) -> str:
def fmap_info(files: list[BIDSFile], config: dict[str, dict[str, str]], layout: BIDSLayout) -> str:
"""Generate a paragraph describing field map acquisition information.
Parameters
----------
layout : :obj:`bids.layout.BIDSLayout`
Layout object for a BIDS dataset.
files : :obj:`list` of :obj:`bids.layout.models.BIDSFile`
List of nifti files in layout corresponding to field map scan.
config : :obj:`dict`
A dictionary with relevant information regarding sequences, sequence
variants, phase encoding directions, and task names.
layout : :obj:`bids.layout.BIDSLayout`
Layout object for a BIDS dataset.
Returns
-------
desc : :obj:`str`
Expand Down Expand Up @@ -238,6 +248,44 @@ def fmap_info(layout: BIDSLayout, files: list[BIDSFile], config: dict[str, dict[
return templates.fmap_info(desc_data)


def perf_info(files: list[BIDSFile], config: dict[str, dict[str, str]], layout: BIDSLayout) -> str:
first_file = files[0]
metadata = first_file.get_metadata()
img = try_load_nii(first_file.path)
if img is None:
files_not_found_warning(Path(first_file.path).relative_to(layout.root))

all_runs = sorted(list({f.get_entities().get("run", 1) for f in files}))

desc_data = {
**common_mri_desc(img, metadata, config),
"echo_time": parameters.echo_time_ms(files),
"nb_runs": parameters.nb_runs(all_runs),
}

return templates.perf_info(desc_data)


def pet_info(files: list[BIDSFile], layout: BIDSLayout) -> str:
first_file = files[0]
metadata = first_file.get_metadata()
img = try_load_nii(first_file.path)
if img is None:
files_not_found_warning(Path(first_file.path).relative_to(layout.root))

all_runs = sorted(list({f.get_entities().get("run", 1) for f in files}))

desc_data = {
**metadata,
"fov": parameters.field_of_view(img),
"matrix_size": parameters.matrix_size(img),
"voxel_size": parameters.voxel_size(img),
"nb_runs": parameters.nb_runs(all_runs),
}

return templates.pet_info(desc_data)


def meg_info(files: list[BIDSFile]) -> str:
"""Generate a paragraph describing meg acquisition information.
Expand Down Expand Up @@ -343,10 +391,13 @@ def parse_files(
elif group[0].entities["datatype"] == "dwi":
group_description = dwi_info(group, config, layout)

elif group[0].entities["datatype"] == "perf":
group_description = perf_info(group, config, layout)

elif (group[0].entities["datatype"] == "fmap") and group[0].entities[
"suffix"
] == "phasediff":
group_description = fmap_info(layout, group, config)
group_description = fmap_info(group, config, layout)

description_list.append(group_description)

Expand All @@ -358,15 +409,21 @@ def parse_files(

group_description = ""

if group[0].entities["datatype"] in [
if group[0].entities["datatype"] == [
"eeg",
"meg",
"pet",
"ieeg",
]:
group_description = meg_info(group, config, layout)

if group[0].entities["datatype"] == "pet":
group_description = pet_info(group, layout)

if group[0].entities["datatype"] in [
"beh",
"perf",
"fnirs",
"microscopy",
"motion",
]:
LOGGER.warning(f" '{group[0].entities['datatype']}' not yet supported.")

Expand Down
15 changes: 10 additions & 5 deletions bids/ext/reports/templates.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,16 +42,16 @@ def footer() -> str:
return f"This section was (in part) generated automatically using pybids {__version__}."


def mri_scanner_info(desc_data: dict[str, Any]) -> str:
"""Generate mri scanner info report."""
return render(template_name="mri_scanner_info.mustache", data=desc_data)


def institution_info(desc_data: dict[str, Any]) -> str:
"""Generate institution report."""
return render(template_name="institution.mustache", data=desc_data)


def mri_scanner_info(desc_data: dict[str, Any]) -> str:
"""Generate mri scanner info report."""
return render(template_name="mri_scanner_info.mustache", data=desc_data)


def anat_info(desc_data: dict[str, Any]) -> str:
"""Generate anatomical report."""
return render(template_name="anat.mustache", data=desc_data)
Expand All @@ -72,6 +72,11 @@ def fmap_info(desc_data: dict[str, Any]) -> str:
return render(template_name="fmap.mustache", data=desc_data)


def perf_info(desc_data: dict[str, Any]) -> str:
"""Generate ASL report."""
return render(template_name="perf.mustache", data=desc_data)


def pet_info(desc_data: dict[str, Any]) -> str:
"""Generate PET report."""
return render(template_name="pet.mustache", data=desc_data)
Expand Down
2 changes: 1 addition & 1 deletion bids/ext/reports/tests/test_parsing.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ def test_fmap_info_smoke(testlayout, testconfig):
suffix="phasediff",
extension=[".nii.gz"],
)
desc = parsing.fmap_info(testlayout, fmap_files, testconfig)
desc = parsing.fmap_info(fmap_files, testconfig, testlayout)
assert isinstance(desc, str)


Expand Down
2 changes: 1 addition & 1 deletion tools/run_on_examples.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/bin/bash

rc=0;
for pre in asl ds00 eeg meg ieeg; do
for pre in asl ds00 eeg meg ieeg pet; do
for i in $(find bids-examples -maxdepth 1 -type d -name "${pre}*"); do
if [ "$i" == "bids-examples" ]; then
continue
Expand Down

0 comments on commit 0a0fc32

Please sign in to comment.