Skip to content

Commit

Permalink
Merge branch 'master' into 3.12
Browse files Browse the repository at this point in the history
  • Loading branch information
oesteban authored Jan 30, 2024
2 parents 5cdba0d + fef7289 commit e45537e
Show file tree
Hide file tree
Showing 8 changed files with 320 additions and 82 deletions.
18 changes: 18 additions & 0 deletions .circleci/circle_bold.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,14 @@ sub-ds205s03/figures/sub-ds205s03_task-view_run-02_desc-stdev_bold.svg
sub-ds205s03/figures/sub-ds205s03_task-view_run-02_desc-zoomed_bold.svg
sub-ds205s03/func
sub-ds205s03/func/sub-ds205s03_task-functionallocalizer_run-01_bold.json
sub-ds205s03/func/sub-ds205s03_task-functionallocalizer_run-01_timeseries.json
sub-ds205s03/func/sub-ds205s03_task-functionallocalizer_run-01_timeseries.tsv
sub-ds205s03/func/sub-ds205s03_task-view_run-01_bold.json
sub-ds205s03/func/sub-ds205s03_task-view_run-01_timeseries.json
sub-ds205s03/func/sub-ds205s03_task-view_run-01_timeseries.tsv
sub-ds205s03/func/sub-ds205s03_task-view_run-02_bold.json
sub-ds205s03/func/sub-ds205s03_task-view_run-02_timeseries.json
sub-ds205s03/func/sub-ds205s03_task-view_run-02_timeseries.tsv
sub-ds205s03_task-functionallocalizer_run-01_bold.html
sub-ds205s03_task-view_run-01_bold.html
sub-ds205s03_task-view_run-02_bold.html
Expand Down Expand Up @@ -60,8 +66,14 @@ sub-ds205s07/figures/sub-ds205s07_task-view_run-02_desc-stdev_bold.svg
sub-ds205s07/figures/sub-ds205s07_task-view_run-02_desc-zoomed_bold.svg
sub-ds205s07/func
sub-ds205s07/func/sub-ds205s07_task-functionallocalizer_run-01_bold.json
sub-ds205s07/func/sub-ds205s07_task-functionallocalizer_run-01_timeseries.json
sub-ds205s07/func/sub-ds205s07_task-functionallocalizer_run-01_timeseries.tsv
sub-ds205s07/func/sub-ds205s07_task-view_run-01_bold.json
sub-ds205s07/func/sub-ds205s07_task-view_run-01_timeseries.json
sub-ds205s07/func/sub-ds205s07_task-view_run-01_timeseries.tsv
sub-ds205s07/func/sub-ds205s07_task-view_run-02_bold.json
sub-ds205s07/func/sub-ds205s07_task-view_run-02_timeseries.json
sub-ds205s07/func/sub-ds205s07_task-view_run-02_timeseries.tsv
sub-ds205s07_task-functionallocalizer_run-01_bold.html
sub-ds205s07_task-view_run-01_bold.html
sub-ds205s07_task-view_run-02_bold.html
Expand Down Expand Up @@ -90,8 +102,14 @@ sub-ds205s09/figures/sub-ds205s09_task-view_acq-RL_run-01_desc-stdev_bold.svg
sub-ds205s09/figures/sub-ds205s09_task-view_acq-RL_run-01_desc-zoomed_bold.svg
sub-ds205s09/func
sub-ds205s09/func/sub-ds205s09_task-view_acq-LR_run-01_bold.json
sub-ds205s09/func/sub-ds205s09_task-view_acq-LR_run-01_timeseries.json
sub-ds205s09/func/sub-ds205s09_task-view_acq-LR_run-01_timeseries.tsv
sub-ds205s09/func/sub-ds205s09_task-view_acq-LR_run-02_bold.json
sub-ds205s09/func/sub-ds205s09_task-view_acq-LR_run-02_timeseries.json
sub-ds205s09/func/sub-ds205s09_task-view_acq-LR_run-02_timeseries.tsv
sub-ds205s09/func/sub-ds205s09_task-view_acq-RL_run-01_bold.json
sub-ds205s09/func/sub-ds205s09_task-view_acq-RL_run-01_timeseries.json
sub-ds205s09/func/sub-ds205s09_task-view_acq-RL_run-01_timeseries.tsv
sub-ds205s09_task-view_acq-LR_run-01_bold.html
sub-ds205s09_task-view_acq-LR_run-02_bold.html
sub-ds205s09_task-view_acq-RL_run-01_bold.html
Expand Down
35 changes: 18 additions & 17 deletions mriqc/data/bootstrap-func.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,28 @@ sections:
- bids: {datatype: figures, desc: stdev}
subtitle: Standard deviation of signal through time
caption: The voxel-wise standard deviation of the signal (variability along time).
- bids: {datatype: figures, desc: background}
caption: This panel shows a mosaic enhancing the background around the head.
Artifacts usually unveil themselves in the air surrounding the head, where no signal
sources are present.
subtitle: View of the background of the voxel-wise average of the BOLD timeseries
- bids: {datatype: figures, desc: zoomed}
caption: This panel shows a mosaic of the brain. This mosaic is the most suitable to
screen head-motion intensity inhomogeneities, global/local noise, signal leakage
(for example, from the eyeballs and across the phase-encoding axis), etc.
subtitle: Voxel-wise average of BOLD time-series, zoomed-in covering just the brain
- bids: {datatype: figures, desc: carpet}
subtitle: Carpetplot and nuisance signals
caption: The so-called «carpetplot» may assist in assessing head-motion
derived artifacts and respiation effects.

- name: Extended echo-wise reports
ordering: echo
reportlets:
- bids: {datatype: figures, desc: mean}
subtitle: Voxel-wise average of BOLD time-series
caption: The average signal calculated across the last axis (time).

- name: Extended reports shared across echos
reportlets:
- bids: {datatype: figures, desc: brainmask}
Expand All @@ -54,23 +72,6 @@ sections:
subtitle: Spatial normalization of the anatomical image
static: false

- name: Extended echo-wise reports
ordering: echo
reportlets:
- bids: {datatype: figures, desc: background}
caption: This panel shows a mosaic enhancing the background around the head.
Artifacts usually unveil themselves in the air surrounding the head, where no signal
sources are present.
subtitle: View of the background of the voxel-wise average of the BOLD timeseries
- bids: {datatype: figures, desc: mean}
subtitle: Average signal through time
caption: The average signal calculated across the last axis (time).
- bids: {datatype: figures, desc: zoomed}
caption: This panel shows a mosaic of the brain. This mosaic is the most suitable to
screen head-motion intensity inhomogeneities, global/local noise, signal leakage
(for example, from the eyeballs and across the phase-encoding axis), etc.
subtitle: Voxel-wise average of BOLD time-series, zoomed-in covering just the brain

- name: About
nested: true
reportlets:
Expand Down
3 changes: 2 additions & 1 deletion mriqc/interfaces/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
)
from mriqc.interfaces.bids import IQMFileSink
from mriqc.interfaces.common import ConformImage, EnsureSize
from mriqc.interfaces.functional import FunctionalQC, Spikes
from mriqc.interfaces.functional import FunctionalQC, GatherTimeseries, Spikes
from mriqc.interfaces.webapi import UploadIQMs


Expand All @@ -47,6 +47,7 @@ class DerivativesDataSink(_DDSink):
"DerivativesDataSink",
"EnsureSize",
"FunctionalQC",
"GatherTimeseries",
"Harmonize",
"IQMFileSink",
"RotationMask",
Expand Down
181 changes: 181 additions & 0 deletions mriqc/interfaces/functional.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@
traits,
Undefined,
)
from nipype.utils.misc import normalize_mc_params
import pandas as pd


class FunctionalQCInputSpec(BaseInterfaceInputSpec):
Expand Down Expand Up @@ -309,6 +311,185 @@ def _run_interface(self, runtime):
return runtime


class GatherTimeseriesInputSpec(TraitedSpec):
dvars = File(exists=True, mandatory=True, desc='file containing DVARS')
fd = File(exists=True, mandatory=True, desc='input framewise displacement')
mpars = File(exists=True, mandatory=True, desc='input motion parameters')
mpars_source = traits.Enum(
"FSL",
"AFNI",
"SPM",
"FSFAST",
"NIPY",
desc="Source of movement parameters",
mandatory=True,
)
outliers = File(
exists=True,
mandatory=True,
desc="input file containing timeseries of AFNI's outlier count")
quality = File(
exists=True,
mandatory=True,
desc="input file containing AFNI's Quality Index")


class GatherTimeseriesOutputSpec(TraitedSpec):
timeseries_file = File(desc='output confounds file')
timeseries_metadata = traits.Dict(desc='Metadata dictionary describing columns')


class GatherTimeseries(SimpleInterface):
"""
Gather quality metrics that are timeseries into one TSV file
"""
input_spec = GatherTimeseriesInputSpec
output_spec = GatherTimeseriesOutputSpec

def _run_interface(self, runtime):

# motion parameters
mpars = np.apply_along_axis(
func1d=normalize_mc_params,
axis=1,
arr=np.loadtxt(self.inputs.mpars), # mpars is N_t x 6
source=self.inputs.mpars_source,
)
timeseries = pd.DataFrame(
mpars,
columns=[
"trans_x",
"trans_y",
"trans_z",
"rot_x",
"rot_y",
"rot_z"
])

# DVARS
dvars = pd.read_csv(
self.inputs.dvars,
delim_whitespace=True,
skiprows=1, # column names have spaces
header=None,
names=["dvars_std", "dvars_nstd", "dvars_vstd"])
dvars.index = pd.RangeIndex(1, timeseries.index.max() + 1)

# FD
fd = pd.read_csv(
self.inputs.fd,
delim_whitespace=True,
header=0,
names=["framewise_displacement"])
fd.index = pd.RangeIndex(1, timeseries.index.max() + 1)

# AQI
aqi = pd.read_csv(
self.inputs.quality,
delim_whitespace=True,
header=None,
names=["aqi"])

# Outliers
aor = pd.read_csv(
self.inputs.outliers,
delim_whitespace=True,
header=None,
names=["aor"])

timeseries = pd.concat((timeseries, dvars, fd, aqi, aor), axis=1)

timeseries_file = op.join(runtime.cwd, "timeseries.tsv")

timeseries.to_csv(timeseries_file, sep='\t', index=False, na_rep='n/a')

self._results['timeseries_file'] = timeseries_file
self._results['timeseries_metadata'] = _build_timeseries_metadata()
return runtime


def _build_timeseries_metadata():
return {
"trans_x": {
"LongName": "Translation Along X Axis",
"Description": "Estimated Motion Parameter",
"Units": "mm"
},
"trans_y": {
"LongName": "Translation Along Y Axis",
"Description": "Estimated Motion Parameter",
"Units": "mm"
},
"trans_z": {
"LongName": "Translation Along Z Axis",
"Description": "Estimated Motion Parameter",
"Units": "mm",
},
"rot_x": {
"LongName": "Rotation Around X Axis",
"Description": "Estimated Motion Parameter",
"Units": "rad"
},
"rot_y": {
"LongName": "Rotation Around X Axis",
"Description": "Estimated Motion Parameter",
"Units": "rad"
},
"rot_z": {
"LongName": "Rotation Around X Axis",
"Description": "Estimated Motion Parameter",
"Units": "rad"
},
"dvars_std": {
"LongName": "Derivative of RMS Variance over Voxels, Standardized",
"Description": (
"Indexes the rate of change of BOLD signal across"
"the entire brain at each frame of data, normalized with the"
"standard deviation of the temporal difference time series"
)
},
"dvars_nstd": {
"LongName": (
"Derivative of RMS Variance over Voxels,"
"Non-Standardized"
),
"Description": (
"Indexes the rate of change of BOLD signal across"
"the entire brain at each frame of data, not normalized."
)
},
"dvars_vstd": {
"LongName": "Derivative of RMS Variance over Voxels, Standardized",
"Description": (
"Indexes the rate of change of BOLD signal across"
"the entire brain at each frame of data, normalized across"
"time by that voxel standard deviation across time,"
"before computing the RMS of the temporal difference"
)
},
"framewise_displacement": {
"LongName": "Framewise Displacement",
"Description": (
"A quantification of the estimated bulk-head"
"motion calculated using formula proposed by Power (2012)"
),
"Units": "mm"
},
"aqi": {
"LongName": "AFNI's Quality Index",
"Description": "Mean quality index as computed by AFNI's 3dTqual"
},
"aor": {
"LongName": "AFNI's Fraction of Outliers per Volume",
"Description": (
"Mean fraction of outliers per fMRI volume as"
"given by AFNI's 3dToutcount"
)
}
}


def find_peaks(data):
t_z = [data[:, :, i, :].mean(axis=0).mean(axis=0) for i in range(data.shape[2])]
return t_z
Expand Down
1 change: 1 addition & 0 deletions mriqc/reports/group.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ def gen_html(csv_file, mod, csv_failed=None, out_file=None):
None,
),
],
"dwi": [],
}

if csv_file.suffix == ".csv":
Expand Down
2 changes: 1 addition & 1 deletion mriqc/workflows/diffusion/output.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def init_dwi_report_wf(name="dwi_report_wf"):
wf = init_dwi_report_wf()
"""
from niworkflows.interfaces.plotting import FMRISummary
from nireports.interfaces import FMRISummary
from niworkflows.interfaces.morphology import BinaryDilation, BinarySubtraction

from nireports.interfaces import PlotMosaic, PlotSpikes
Expand Down
Loading

0 comments on commit e45537e

Please sign in to comment.