Skip to content
1 change: 1 addition & 0 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
All configuration values have a default; values that are commented out
serve to show the default.
"""

import os

from packaging.version import Version
Expand Down
1 change: 1 addition & 0 deletions mriqc/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
:abbr:`IQMs (image quality metrics)` to used in :abbr:`QAPs (quality
assessment protocols)` for :abbr:`MRI (magnetic resonance imaging)`.
"""

from mriqc._version import __version__

__copyright__ = 'Copyright 2022, The NiPreps Developers'
Expand Down
8 changes: 6 additions & 2 deletions mriqc/_warnings.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
# https://www.nipreps.org/community/licensing/
#
"""Manipulate Python warnings."""

import logging
import sys

Expand Down Expand Up @@ -64,12 +65,15 @@ def __init__(self, datefmt=None, colored=True, **kwargs):
def format(self, record):
reset = CONSOLE_COLORS['reset'] if self._colored else ''
self._style._fmt = (
'%(message)s' if record.levelno == 26
'%(message)s'
if record.levelno == 26
else LOGGER_FMT.format(
color=CONSOLE_COLORS.get(
record.levelno,
CONSOLE_COLORS['reset'],
) if self._colored else '',
)
if self._colored
else '',
reset=reset,
)
)
Expand Down
9 changes: 3 additions & 6 deletions mriqc/bin/abide2bids.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
# https://www.nipreps.org/community/licensing/
#
"""ABIDE2BIDS download tool."""

from __future__ import annotations

import errno
Expand Down Expand Up @@ -50,12 +51,8 @@ def main():
)
g_input = parser.add_argument_group('Inputs')
g_input.add_argument('-i', '--input-abide-catalog', action='store', required=True)
g_input.add_argument(
'-n', '--dataset-name', action='store', default='ABIDE Dataset'
)
g_input.add_argument(
'-u', '--nitrc-user', action='store', default=os.getenv('NITRC_USER')
)
g_input.add_argument('-n', '--dataset-name', action='store', default='ABIDE Dataset')
g_input.add_argument('-u', '--nitrc-user', action='store', default=os.getenv('NITRC_USER'))
g_input.add_argument(
'-p',
'--nitrc-password',
Expand Down
13 changes: 4 additions & 9 deletions mriqc/bin/dfcheck.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"""
Compares pandas dataframes by columns.
"""

import sys
from argparse import ArgumentParser, RawTextHelpFormatter
from pathlib import Path
Expand All @@ -39,9 +40,7 @@ def read_iqms(feat_file):
feat_file = Path(feat_file)

if feat_file.suffix == '.csv':
x_df = pd.read_csv(
feat_file, index_col=False, dtype={col: str for col in BIDS_COMP}
)
x_df = pd.read_csv(feat_file, index_col=False, dtype={col: str for col in BIDS_COMP})
# Find present bids bits and sort by them
bids_comps_present = list(set(x_df.columns) & set(BIDS_COMP))
bids_comps_present = [bit for bit in BIDS_COMP if bit in bids_comps_present]
Expand All @@ -58,9 +57,7 @@ def read_iqms(feat_file):
pass
else:
bids_comps_present = ['subject_id']
x_df = pd.read_csv(
feat_file, index_col=False, sep='\t', dtype={'bids_name': str}
)
x_df = pd.read_csv(feat_file, index_col=False, sep='\t', dtype={'bids_name': str})
x_df = x_df.sort_values(by=['bids_name'])
x_df['subject_id'] = x_df.bids_name.str.lstrip('sub-')
x_df = x_df.drop(columns=['bids_name'])
Expand Down Expand Up @@ -134,9 +131,7 @@ def main():
tst_keep = np.sum(tst_rows.isin(ref_rows).values.ravel().tolist())
print(tst_keep)

diff = ~np.isclose(
ref_df[ref_names].values, tst_df[tst_names].values, rtol=opts.tolerance
)
diff = ~np.isclose(ref_df[ref_names].values, tst_df[tst_names].values, rtol=opts.tolerance)
if np.any(diff):
# ne_stacked = pd.DataFrame(data=diff, columns=ref_names).stack()
# ne_stacked = np.isclose(ref_df[ref_names], tst_df[ref_names]).stack()
Expand Down
24 changes: 6 additions & 18 deletions mriqc/bin/fs2gif.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"""
Batch export freesurfer results to animated gifs.
"""

import os
import os.path as op
import subprocess as sp
Expand Down Expand Up @@ -129,10 +130,7 @@ def main():
)
tclfp.write(' SetSlice $slice\n')
tclfp.write(' RedrawScreen\n')
tclfp.write(
f' SaveTIFF [format "{tmp_sub}/{subid}-'
'%03d.tif" $i]\n'
)
tclfp.write(f' SaveTIFF [format "{tmp_sub}/{subid}-' '%03d.tif" $i]\n')
tclfp.write(' incr i\n')
tclfp.write('}\n')
tclfp.write('QuitMedit\n')
Expand Down Expand Up @@ -175,15 +173,10 @@ def main():
'for { set slice %d } { $slice < %d } { incr slice } {'
% (bbox_min[2], bbox_max[2])
)
tclfp.write(
' SetZoomCenter %d %d $slice\n'
% (center[0] + 30, center[1] - 10)
)
tclfp.write(' SetZoomCenter %d %d $slice\n' % (center[0] + 30, center[1] - 10))
tclfp.write(' SetSlice $slice\n')
tclfp.write(' RedrawScreen\n')
tclfp.write(
f' SaveTIFF [format "{tmp_sub}/{subid}-lh-%03d.tif" $i]\n'
)
tclfp.write(f' SaveTIFF [format "{tmp_sub}/{subid}-lh-%03d.tif" $i]\n')
tclfp.write(' incr i\n')
tclfp.write('}\n')
tclfp.write('QuitMedit\n')
Expand All @@ -205,15 +198,10 @@ def main():
'for { set slice %d } { $slice < %d } { incr slice } {'
% (bbox_min[2], bbox_max[2])
)
tclfp.write(
' SetZoomCenter %d %d $slice\n'
% (center[0] - 30, center[1] - 10)
)
tclfp.write(' SetZoomCenter %d %d $slice\n' % (center[0] - 30, center[1] - 10))
tclfp.write(' SetSlice $slice\n')
tclfp.write(' RedrawScreen\n')
tclfp.write(
f' SaveTIFF [format "{tmp_sub}/{subid}-rh-%03d.tif" $slice]\n'
)
tclfp.write(f' SaveTIFF [format "{tmp_sub}/{subid}-rh-%03d.tif" $slice]\n')
tclfp.write(' incr i\n')
tclfp.write('}\n')
tclfp.write('QuitMedit\n')
Expand Down
16 changes: 4 additions & 12 deletions mriqc/bin/messages.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,20 +20,12 @@
#
# https://www.nipreps.org/community/licensing/
#
ABIDE_SUBJECT_FETCHED = (
'Successfully processed subject {subject_id} from site {site_name}'
)
ABIDE_SUBJECT_FETCHED = 'Successfully processed subject {subject_id} from site {site_name}'
ABIDE_TEMPORAL_WARNING = 'WARNING: Error deleting temporal files: {message}'
BIDS_LABEL_MISSING = (
'Participant label(s) not found in the BIDS root directory: {label}'
)
BIDS_GROUP_SIZE = (
'Group size should be at least 0 (i.e. all participants assigned to same group).'
)
BIDS_LABEL_MISSING = 'Participant label(s) not found in the BIDS root directory: {label}'
BIDS_GROUP_SIZE = 'Group size should be at least 0 (i.e. all participants assigned to same group).'
CLF_CAPTURED_WARNING = 'Captured warning ({category}): {message}'
CLF_CLASSIFIER_MISSING = (
'No training samples were given, and the --load-classifier option {info}.'
)
CLF_CLASSIFIER_MISSING = 'No training samples were given, and the --load-classifier option {info}.'
CLF_SAVED_RESULTS = 'Results saved as {path}.'
CLF_TRAIN_LOAD_ERROR = 'Errors ({n_errors}) loading training set: {errors}.'
CLF_WRONG_PARAMETER_COUNT = 'Wrong number of parameters.'
Expand Down
1 change: 1 addition & 0 deletions mriqc/bin/nib_hash.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"""
Extracts the sha hash of the contents of a nifti file.
"""

from argparse import ArgumentParser, RawTextHelpFormatter
from hashlib import sha1

Expand Down
5 changes: 2 additions & 3 deletions mriqc/bin/subject_wrangler.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
# https://www.nipreps.org/community/licensing/
#
"""BIDS-Apps subject wrangler."""

import glob
import os.path as op
from argparse import ArgumentParser, RawTextHelpFormatter
Expand Down Expand Up @@ -124,9 +125,7 @@ def main():

if list(set(subject_list) - set(all_subjects)):
non_exist = list(set(subject_list) - set(all_subjects))
missing_label_error = messages.BIDS_LABEL_MISSING.format(
label=' '.join(non_exist)
)
missing_label_error = messages.BIDS_LABEL_MISSING.format(label=' '.join(non_exist))
raise RuntimeError(missing_label_error)

if not opts.no_randomize:
Expand Down
74 changes: 32 additions & 42 deletions mriqc/cli/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
# https://www.nipreps.org/community/licensing/
#
"""Parser."""

import re

from mriqc import config
Expand All @@ -42,10 +43,9 @@ def _parse_participant_labels(value):
['s060']

"""
return sorted({
re.sub(r'^sub-', '', item.strip())
for item in re.split(r'\s+', f'{value}'.strip())
})
return sorted(
{re.sub(r'^sub-', '', item.strip()) for item in re.split(r'\s+', f'{value}'.strip())}
)


def _build_parser():
Expand Down Expand Up @@ -176,10 +176,13 @@ def _bids_filter(value):
'identifier (the sub- prefix can be removed).',
)
g_bids.add_argument(
'--bids-filter-file', action='store', type=Path, metavar='PATH',
'--bids-filter-file',
action='store',
type=Path,
metavar='PATH',
help='a JSON file describing custom BIDS input filter using pybids '
'{<suffix>:{<entity>:<filter>,...},...} '
'(https://github.com/bids-standard/pybids/blob/master/bids/layout/config/bids.json)'
'{<suffix>:{<entity>:<filter>,...},...} '
'(https://github.com/bids-standard/pybids/blob/master/bids/layout/config/bids.json)',
)
g_bids.add_argument(
'--session-id',
Expand Down Expand Up @@ -280,7 +283,7 @@ def _bids_filter(value):
action='store_true',
default=True,
help="Cast the input data to float32 if it's represented in higher precision "
"(saves space and improves performance).",
'(saves space and improves performance).',
)
g_perfm.add_argument(
'--pdb',
Expand Down Expand Up @@ -333,8 +336,7 @@ def _bids_filter(value):
'--no-sub',
default=False,
action='store_true',
help="Turn off submission of anonymized quality metrics "
"to MRIQC's metrics repository.",
help="Turn off submission of anonymized quality metrics to MRIQC's metrics repository.",
)
g_outputs.add_argument(
'--email',
Expand Down Expand Up @@ -423,15 +425,13 @@ def _bids_filter(value):
'--deoblique',
action='store_true',
default=False,
help='Deoblique the functional scans during head motion correction '
'preprocessing.',
help='Deoblique the functional scans during head motion correction preprocessing.',
)
g_func.add_argument(
'--despike',
action='store_true',
default=False,
help='Despike the functional scans during head motion correction '
'preprocessing.',
help='Despike the functional scans during head motion correction preprocessing.',
)
g_func.add_argument(
'--start-idx',
Expand Down Expand Up @@ -491,18 +491,16 @@ def parse_args(args=None, namespace=None):

config.loggers.init()

_log_file = (
Path(opts.output_dir)
/ 'logs'
/ f'mriqc-{config.execution.run_uuid}.log'
)
_log_file = Path(opts.output_dir) / 'logs' / f'mriqc-{config.execution.run_uuid}.log'
_log_file.parent.mkdir(exist_ok=True, parents=True)
_handler = FileHandler(_log_file)
_handler.setFormatter(_LogFormatter(
fmt=LOGGER_FMT.format(color='', reset=''),
datefmt=DATE_FMT,
colored=False,
))
_handler.setFormatter(
_LogFormatter(
fmt=LOGGER_FMT.format(color='', reset=''),
datefmt=DATE_FMT,
colored=False,
)
)
config.loggers.default.addHandler(_handler)

extra_messages = ['']
Expand All @@ -521,7 +519,7 @@ def parse_args(args=None, namespace=None):
output_dir=opts.output_dir,
analysis_level=opts.analysis_level,
extra_messages='\n'.join(extra_messages),
)
),
)
config.from_dict(vars(opts))

Expand All @@ -535,9 +533,7 @@ def parse_args(args=None, namespace=None):
if _plugin:
config.nipype.plugin = _plugin
config.nipype.plugin_args = plugin_settings.get('plugin_args', {})
config.nipype.nprocs = config.nipype.plugin_args.get(
'nprocs', config.nipype.nprocs
)
config.nipype.nprocs = config.nipype.plugin_args.get('nprocs', config.nipype.nprocs)

# Load BIDS filters
if opts.bids_filter_file:
Expand Down Expand Up @@ -575,13 +571,12 @@ def parse_args(args=None, namespace=None):
config.execution.init()

participant_label = [
d.name[4:] for d in config.execution.bids_dir.glob('sub-*')
if d.is_dir() and d.exists()
d.name[4:] for d in config.execution.bids_dir.glob('sub-*') if d.is_dir() and d.exists()
]

if config.execution.participant_label is not None:
selected_label = set(config.execution.participant_label)
if (missing_subjects := selected_label - set(participant_label)):
if missing_subjects := selected_label - set(participant_label):
parser.error(
"One or more participant labels were not found in the BIDS directory: "
f"{', '.join(missing_subjects)}."
Expand All @@ -604,23 +599,19 @@ def parse_args(args=None, namespace=None):
session_id=config.execution.session_id,
task=config.execution.task_id,
group_echos=True,
bids_filters={
mod: config.execution.bids_filters.get(mod, {})
for mod in lc_modalities
},
queries={mod: DEFAULT_BIDS_QUERIES[mod] for mod in lc_modalities}
bids_filters={mod: config.execution.bids_filters.get(mod, {}) for mod in lc_modalities},
queries={mod: DEFAULT_BIDS_QUERIES[mod] for mod in lc_modalities},
)

# Drop empty queries
bids_dataset = {
mod: files for mod, files in bids_dataset.items() if files
}
bids_dataset = {mod: files for mod, files in bids_dataset.items() if files}
config.workflow.inputs = bids_dataset

# Check the query is not empty
if not list(config.workflow.inputs.values()):
ffile = (
'(--bids-filter-file was not set)' if not opts.bids_filter_file
'(--bids-filter-file was not set)'
if not opts.bids_filter_file
else f"(with '--bids-filter-file {opts.bids_filter_file}')"
)
parser.error(
Expand All @@ -636,8 +627,7 @@ def parse_args(args=None, namespace=None):
}
if unknown_mods:
parser.error(
'MRIQC is unable to process the following modalities: '
f'{", ".join(unknown_mods)}.'
f'MRIQC is unable to process the following modalities: {", ".join(unknown_mods)}.'
)

# Estimate the biggest file size / leave 1GB if some file does not exist (datalad)
Expand Down
Loading