-
Notifications
You must be signed in to change notification settings - Fork 5
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
[ENH] start bidsifying output #80
Changes from 18 commits
547d888
4649ea1
ef48177
614b8a8
e3a36ca
14415ef
6eb1126
e91e91b
15441d3
ec0a33d
3c0e72e
3b12bf5
2538c43
3eb3061
3e8570c
21fa3db
0d5db0b
5224759
49cbf3a
2100612
c82f3d2
7eb15f6
405c6ac
e4a88c9
c463fdd
784d9b5
808dd65
29efb3e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,52 @@ | ||
# Outputs | ||
|
||
The output of this app aims to follow the guideline | ||
of the [BIDS extension proposal 17 - Generic BIDS connectivity data schema](https://bids.neuroimaging.io/bep017). | ||
|
||
Metadata files content is described in this BIDS extension proposal. | ||
|
||
## participant level | ||
|
||
When performing `participant` level analysis, the output is a HDF5 file per participant that was passed to `--participant_label` or all subjects under `bids_dir`. | ||
The output file name is: `sub-<participant_id>_atlas-<atlas_name>_desc-<denoising_strategy>.h5` | ||
|
||
When performing `group` level analysis, the file will contain time series and connectomes of each subject, as well as group average connectomes. The output is a HDF5 file per participant that was passed to `--participant_label` or all subjects under `bids_dir`. | ||
The output file name is: `atlas-<atlas_name>_desc-<denoising_strategy>.h5` | ||
The output file name is: | ||
|
||
``` | ||
sub-<participant_id>/[ses-<ses_id>]/func/<source_filename>_atlas-<atlas_name>_meas-PearsonCorrelation_desc-<denoising_strategy>_relmat.h5 | ||
``` | ||
|
||
## group level | ||
|
||
When performing `group` level analysis, | ||
the file will contain time series and connectomes of each subject, | ||
as well as group average connectomes. | ||
|
||
The output is a HDF5 file per participant that was passed to `--participant_label` or all subjects under `bids_dir`. | ||
|
||
### Example | ||
|
||
``` | ||
giga_connectome/data/test_data/output | ||
├── dataset_description.json | ||
├── meas-PearsonCorrelation_desc-simple_relmat.json | ||
├── group | ||
│ └── atlas-Schaefer20187Networks_meas-PearsonCorrelation_desc-simple_relmat.h5 | ||
├── sub-1 | ||
│ ├── ses-timepoint1 | ||
│ │ └── func | ||
│ │ ├── sub-1_ses-timepoint1_task-probabilisticclassification_run-01_space-MNI152NLin2009cAsym_res-2_atlas-Schaefer20187Networks_meas-PearsonCorrelation_desc-simple_relmat.h5 | ||
│ │ └── sub-1_ses-timepoint1_task-probabilisticclassification_run-02_space-MNI152NLin2009cAsym_res-2_atlas-Schaefer20187Networks_meas-PearsonCorrelation_desc-simple_relmat.h5 | ||
│ └── ses-timepoint2 | ||
│ └── func | ||
│ ├── sub-1_ses-timepoint2_task-probabilisticclassification_run-01_space-MNI152NLin2009cAsym_res-2_atlas-Schaefer20187Networks_meas-PearsonCorrelation_desc-simple_relmat.h5 | ||
│ └── sub-1_ses-timepoint2_task-probabilisticclassification_run-02_space-MNI152NLin2009cAsym_res-2_atlas-Schaefer20187Networks_meas-PearsonCorrelation_desc-simple_relmat.h5 | ||
└── sub-2 | ||
├── ses-timepoint1 | ||
│ └── func | ||
│ ├── sub-2_ses-timepoint1_task-probabilisticclassification_run-01_space-MNI152NLin2009cAsym_res-2_atlas-Schaefer20187Networks_meas-PearsonCorrelation_desc-simple_relmat.h5 | ||
│ └── sub-2_ses-timepoint1_task-probabilisticclassification_run-02_space-MNI152NLin2009cAsym_res-2_atlas-Schaefer20187Networks_meas-PearsonCorrelation_desc-simple_relmat.h5 | ||
└── ses-timepoint2 | ||
└── func | ||
├── sub-2_ses-timepoint2_task-probabilisticclassification_run-01_space-MNI152NLin2009cAsym_res-2_atlas-Schaefer20187Networks_meas-PearsonCorrelation_desc-simple_relmat.h5 | ||
└── sub-2_ses-timepoint2_task-probabilisticclassification_run-02_space-MNI152NLin2009cAsym_res-2_atlas-Schaefer20187Networks_meas-PearsonCorrelation_desc-simple_relmat.h5 | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,15 @@ | ||
from typing import Union, List | ||
from pathlib import Path | ||
|
||
import json | ||
|
||
import h5py | ||
from tqdm import tqdm | ||
import numpy as np | ||
from nilearn.connectome import ConnectivityMeasure | ||
from nilearn.maskers import NiftiLabelsMasker, NiftiMapsMasker | ||
from bids.layout import BIDSImageFile | ||
import pandas as pd | ||
|
||
from giga_connectome import utils | ||
from giga_connectome.connectome import generate_timeseries_connectomes | ||
|
@@ -18,6 +21,7 @@ | |
|
||
def run_postprocessing_dataset( | ||
strategy: dict, | ||
atlas: str, | ||
resampled_atlases: List[Union[str, Path]], | ||
images: List[BIDSImageFile], | ||
group_mask: Union[str, Path], | ||
|
@@ -61,6 +65,9 @@ def run_postprocessing_dataset( | |
strategy : dict | ||
Parameters for `load_confounds_strategy` or `load_confounds`. | ||
|
||
atlas : dict | ||
Atlas settings. | ||
|
||
resampled_atlases : list of str or pathlib.Path | ||
Atlas niftis resampled to the common space of the dataset. | ||
|
||
|
@@ -78,16 +85,14 @@ def run_postprocessing_dataset( | |
Smoothing kernel size, passed to nilearn masker. | ||
|
||
output_path: | ||
Full path to output file, named in the following format: | ||
output_dir / atlas-<atlas>_desc-<strategy_name>.h5 | ||
Full path to output directory. | ||
|
||
analysis_level : str | ||
Level of analysis, either "participant" or "group". | ||
|
||
calculate_average_correlation : bool | ||
Whether to calculate average correlation within each parcel. | ||
""" | ||
atlas = output_path.name.split("atlas-")[-1].split("_")[0] | ||
atlas_maskers, connectomes = {}, {} | ||
for atlas_path in resampled_atlases: | ||
if isinstance(atlas_path, str): | ||
|
@@ -104,7 +109,6 @@ def run_postprocessing_dataset( | |
gc_log.info("Processing subject") | ||
|
||
for img in tqdm(images): | ||
|
||
print() | ||
gc_log.info(f"Processing image:\n{img.filename}") | ||
|
||
|
@@ -114,8 +118,32 @@ def run_postprocessing_dataset( | |
) | ||
# parse file name | ||
subject, session, specifier = utils.parse_bids_name(img.path) | ||
|
||
# folder for this subject output | ||
connectome_path = output_path / subject | ||
if session: | ||
connectome_path = connectome_path / session | ||
connectome_path = connectome_path / "func" | ||
|
||
# All timeseries derivatives have the same metadata | ||
# so one json file for them all. | ||
json_filename = connectome_path / utils.output_filename( | ||
source_file=Path(img.filename).stem, | ||
atlas=atlas["name"], | ||
extension="json", | ||
) | ||
utils.check_path(json_filename) | ||
with open(json_filename, "w") as f: | ||
json.dump( | ||
{"RepetitionTime": img.entities["RepetitionTime"]}, | ||
f, | ||
indent=4, | ||
) | ||
|
||
for desc, masker in atlas_maskers.items(): | ||
attribute_name = f"{subject}_{specifier}_atlas-{atlas}_desc-{desc}" | ||
attribute_name = ( | ||
f"{subject}_{specifier}_atlas-{atlas['name']}_desc-{desc}" | ||
) | ||
if not denoised_img: | ||
time_series_atlas, correlation_matrix = None, None | ||
|
||
|
@@ -136,21 +164,37 @@ def run_postprocessing_dataset( | |
) | ||
connectomes[desc].append(correlation_matrix) | ||
|
||
# dump to h5 | ||
flag = _set_file_flag(output_path) | ||
with h5py.File(output_path, flag) as f: | ||
# one output file per input file per atlas | ||
|
||
# dump correlation_matrix to tsv | ||
tsv_filename = connectome_path / utils.output_filename( | ||
source_file=Path(img.filename).stem, | ||
atlas=atlas["name"], | ||
extension="tsv", | ||
strategy=strategy["name"], | ||
desc=desc, | ||
) | ||
utils.check_path(tsv_filename) | ||
df = pd.DataFrame(correlation_matrix) | ||
df.to_csv(tsv_filename, sep="\t", index=False) | ||
|
||
# dump timeseries to h5 | ||
h5_filename = connectome_path / utils.output_filename( | ||
source_file=Path(img.filename).stem, | ||
atlas=atlas["name"], | ||
extension="h5", | ||
strategy=strategy["name"], | ||
desc=desc, | ||
) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we want to be fully BIDS compliant, shall we save time series to h5 as well? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yeah am working on this ideally maybe even in nifti, no? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. no nifty since we are not outputting seed based maps? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ok will dump that in tsv then |
||
utils.check_path(h5_filename) | ||
flag = _set_file_flag(h5_filename) | ||
with h5py.File(h5_filename, flag) as f: | ||
group = _fetch_h5_group(f, subject, session) | ||
timeseries_dset = group.create_dataset( | ||
f"{attribute_name}_timeseries", data=time_series_atlas | ||
) | ||
timeseries_dset.attrs["RepetitionTime"] = img.entities[ | ||
"RepetitionTime" | ||
] | ||
group.create_dataset( | ||
f"{attribute_name}_connectome", data=correlation_matrix | ||
f"{attribute_name}_timeseries", data=time_series_atlas | ||
) | ||
|
||
gc_log.info(f"Saved to:\n{output_path}") | ||
gc_log.info(f"Saved to:\n{connectome_path}") | ||
|
||
if analysis_level == "group": | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A bit extra to this PR but it felt like a minimum description on how to run a demo was necessary