diff --git a/docs/sphinxext/docscrape.py b/docs/sphinxext/docscrape.py
index e5c07f59ded..5654f7e9319 100644
--- a/docs/sphinxext/docscrape.py
+++ b/docs/sphinxext/docscrape.py
@@ -326,8 +326,9 @@ def parse_item_name(text):
description = line_match.group("desc")
if line_match.group("trailing") and description:
self._error_location(
- "Unexpected comma or period after function list at index %d of "
- 'line "%s"' % (line_match.end("trailing"), line),
+ "Unexpected comma or period after function list "
+ f"at index {line_match.end('trailing')} of line "
+ f'"{line}"',
error=False,
)
if not description and line.startswith(" "):
@@ -414,8 +415,8 @@ def _parse(self):
section = " ".join(section)
if self.get(section):
self._error_location(
- "The section %s appears twice in %s"
- % (section, "\n".join(self._doc._str))
+ f"The section {section} appears twice "
+ f"in {'\n'.join(self._doc._str)}"
)
if section in ("Parameters", "Other Parameters", "Attributes", "Methods"):
diff --git a/docs/sphinxext/github.py b/docs/sphinxext/github.py
index 4f74b64d648..c117d492f22 100644
--- a/docs/sphinxext/github.py
+++ b/docs/sphinxext/github.py
@@ -37,7 +37,7 @@ def make_link_node(rawtext, app, type, slug, options):
if not base.endswith('/'):
base += '/'
except AttributeError as err:
- raise ValueError('github_project_url configuration value is not set (%s)' % str(err))
+ raise ValueError(f'github_project_url configuration value is not set ({err})')
ref = base + type + '/' + slug + '/'
set_classes(options)
@@ -71,11 +71,11 @@ def ghissue_role(name, rawtext, text, lineno, inliner, options={}, content=[]):
except ValueError:
msg = inliner.reporter.error(
'GitHub issue number must be a number greater than or equal to 1; '
- '"%s" is invalid.' % text, line=lineno)
+ f'"{text}" is invalid.', line=lineno)
prb = inliner.problematic(rawtext, rawtext, msg)
return [prb], [msg]
app = inliner.document.settings.env.app
- #app.info('issue %r' % text)
+ #app.info(f'issue {text!r}')
if 'pull' in name.lower():
category = 'pull'
elif 'issue' in name.lower():
@@ -83,7 +83,7 @@ def ghissue_role(name, rawtext, text, lineno, inliner, options={}, content=[]):
else:
msg = inliner.reporter.error(
'GitHub roles include "ghpull" and "ghissue", '
- '"%s" is invalid.' % name, line=lineno)
+ f'"{name}" is invalid.', line=lineno)
prb = inliner.problematic(rawtext, rawtext, msg)
return [prb], [msg]
node = make_link_node(rawtext, app, category, str(issue_num), options)
@@ -105,7 +105,7 @@ def ghuser_role(name, rawtext, text, lineno, inliner, options={}, content=[]):
:param content: The directive content for customization.
"""
app = inliner.document.settings.env.app
- #app.info('user link %r' % text)
+ #app.info(f'user link {text!r}')
ref = 'https://www.github.com/' + text
node = nodes.reference(rawtext, text, refuri=ref, **options)
return [node], []
@@ -126,7 +126,7 @@ def ghcommit_role(name, rawtext, text, lineno, inliner, options={}, content=[]):
:param content: The directive content for customization.
"""
app = inliner.document.settings.env.app
- #app.info('user link %r' % text)
+ #app.info(f'user link {text!r}')
try:
base = app.config.github_project_url
if not base:
@@ -134,7 +134,7 @@ def ghcommit_role(name, rawtext, text, lineno, inliner, options={}, content=[]):
if not base.endswith('/'):
base += '/'
except AttributeError as err:
- raise ValueError('github_project_url configuration value is not set (%s)' % str(err))
+ raise ValueError(f'github_project_url configuration value is not set ({err})')
ref = base + text
node = nodes.reference(rawtext, text[:6], refuri=ref, **options)
diff --git a/docs/sphinxext/math_dollar.py b/docs/sphinxext/math_dollar.py
index ad415deb905..665f2fff2c7 100644
--- a/docs/sphinxext/math_dollar.py
+++ b/docs/sphinxext/math_dollar.py
@@ -33,7 +33,7 @@ def dollars_to_math(source):
def repl(matchobj):
global _data
s = matchobj.group(0)
- t = "___XXX_REPL_%d___" % len(_data)
+ t = f"___XXX_REPL_{len(_data)}___"
_data[t] = s
return t
s = re.sub(r"({[^{}$]*\$[^{}$]*\$[^{}]*})", repl, s)
diff --git a/niworkflows/__about__.py b/niworkflows/__about__.py
index e0923bf4334..fc446d83146 100644
--- a/niworkflows/__about__.py
+++ b/niworkflows/__about__.py
@@ -29,9 +29,7 @@
from datetime import datetime
__packagename__ = "niworkflows"
-__copyright__ = "Copyright {}, The NiPreps Developers".format(
- datetime.now().year
-)
+__copyright__ = f"Copyright {datetime.now().year}, The NiPreps Developers"
__credits__ = [
"Oscar Esteban",
"Ross Blair",
diff --git a/niworkflows/anat/ants.py b/niworkflows/anat/ants.py
index 5854f7c9d64..afe1a1fb4f7 100644
--- a/niworkflows/anat/ants.py
+++ b/niworkflows/anat/ants.py
@@ -721,19 +721,19 @@ def init_atropos_wf(
# De-pad
depad_mask = pe.Node(
- ImageMath(operation="PadImage", op2="-%d" % padding), name="23_depad_mask"
+ ImageMath(operation="PadImage", op2=f"-{padding}"), name="23_depad_mask"
)
depad_segm = pe.Node(
- ImageMath(operation="PadImage", op2="-%d" % padding), name="24_depad_segm"
+ ImageMath(operation="PadImage", op2=f"-{padding}"), name="24_depad_segm"
)
depad_gm = pe.Node(
- ImageMath(operation="PadImage", op2="-%d" % padding), name="25_depad_gm"
+ ImageMath(operation="PadImage", op2=f"-{padding}"), name="25_depad_gm"
)
depad_wm = pe.Node(
- ImageMath(operation="PadImage", op2="-%d" % padding), name="26_depad_wm"
+ ImageMath(operation="PadImage", op2=f"-{padding}"), name="26_depad_wm"
)
depad_csf = pe.Node(
- ImageMath(operation="PadImage", op2="-%d" % padding), name="27_depad_csf"
+ ImageMath(operation="PadImage", op2=f"-{padding}"), name="27_depad_csf"
)
msk_conform = pe.Node(niu.Function(function=_conform_mask), name="msk_conform")
@@ -1061,7 +1061,7 @@ def _select_labels(in_segm, labels):
for label in labels:
newnii = nii.__class__(np.uint8(label_data == label), nii.affine, nii.header)
newnii.set_data_dtype("uint8")
- out_file = fname_presuffix(in_segm, suffix="_class-%02d" % label, newpath=cwd)
+ out_file = fname_presuffix(in_segm, suffix=f"_class-{label:%02d}", newpath=cwd)
newnii.to_filename(out_file)
out_files.append(out_file)
return out_files
diff --git a/niworkflows/data/__init__.py b/niworkflows/data/__init__.py
index ef1bddab104..b69eb32ffaf 100644
--- a/niworkflows/data/__init__.py
+++ b/niworkflows/data/__init__.py
@@ -110,7 +110,7 @@ class Loader:
.. automethod:: cached
"""
- def __init__(self, anchor: Union[str, ModuleType]):
+ def __init__(self, anchor: str | ModuleType):
self._anchor = anchor
self.files = files(anchor)
self.exit_stack = ExitStack()
diff --git a/niworkflows/func/tests/test_util.py b/niworkflows/func/tests/test_util.py
index 76fd652a3a1..ffdcb292128 100755
--- a/niworkflows/func/tests/test_util.py
+++ b/niworkflows/func/tests/test_util.py
@@ -85,11 +85,10 @@
parameters = zip(bold_datasets, exp_masks)
if not bold_datasets:
+ _folder_contents = "\n".join([str(p) for p in datapath.glob("ds*/*.nii.gz")])
raise RuntimeError(
f"Data folder <{datapath}> was provided, but no images were found. "
- "Folder contents:\n{}".format(
- "\n".join([str(p) for p in datapath.glob("ds*/*.nii.gz")])
- )
+ f"Folder contents:\n{_folder_contents}"
)
diff --git a/niworkflows/interfaces/bids.py b/niworkflows/interfaces/bids.py
index 2c139c6796f..6009d82ceec 100644
--- a/niworkflows/interfaces/bids.py
+++ b/niworkflows/interfaces/bids.py
@@ -858,8 +858,7 @@ def _run_interface(self, runtime):
for fname in self._fields:
if not self._undef_fields and fname not in metadata:
raise KeyError(
- 'Metadata field "%s" not found for file %s'
- % (fname, self.inputs.in_file)
+ f'Metadata field "{fname}" not found for file {self.inputs.in_file}'
)
self._results[fname] = metadata.get(fname, Undefined)
return runtime
@@ -945,7 +944,7 @@ def _run_interface(self, runtime):
if dest.exists():
continue
else:
- raise FileNotFoundError("Expected to find '%s' to copy" % source)
+ raise FileNotFoundError(f"Expected to find '{source}' to copy")
if (
space == 'fsaverage'
diff --git a/niworkflows/interfaces/confounds.py b/niworkflows/interfaces/confounds.py
index 267652674ab..9ce2bcf2548 100644
--- a/niworkflows/interfaces/confounds.py
+++ b/niworkflows/interfaces/confounds.py
@@ -298,13 +298,13 @@ def spike_regressors(
mask = reduce((lambda x, y: x | y), mask.values())
for lag in lags:
- mask = set([m + lag for m in mask]) | mask
+ mask = {m + lag for m in mask} | mask
mask = mask.intersection(indices)
if minimum_contiguous is not None:
post_final = data.shape[0] + 1
- epoch_length = np.diff(sorted(mask | set([-1, post_final]))) - 1
- epoch_end = sorted(mask | set([post_final]))
+ epoch_length = np.diff(sorted(mask | {-1, post_final})) - 1
+ epoch_end = sorted(mask | {post_final})
for end, length in zip(epoch_end, epoch_length):
if length < minimum_contiguous:
mask = mask | set(range(end - length, end))
@@ -357,7 +357,7 @@ def temporal_derivatives(order, variables, data):
if 0 in order:
data_deriv[0] = data[variables]
variables_deriv[0] = variables
- order = set(order) - set([0])
+ order = set(order) - {0}
for o in order:
variables_deriv[o] = [f"{v}_derivative{o}" for v in variables]
data_deriv[o] = np.tile(np.nan, data[variables].shape)
@@ -400,7 +400,7 @@ def exponential_terms(order, variables, data):
if 1 in order:
data_exp[1] = data[variables]
variables_exp[1] = variables
- order = set(order) - set([1])
+ order = set(order) - {1}
for o in order:
variables_exp[o] = [f"{v}_power{o}" for v in variables]
data_exp[o] = data[variables] ** o
diff --git a/niworkflows/interfaces/freesurfer.py b/niworkflows/interfaces/freesurfer.py
index 392bbe01cfb..092728f2cb7 100644
--- a/niworkflows/interfaces/freesurfer.py
+++ b/niworkflows/interfaces/freesurfer.py
@@ -139,7 +139,7 @@ def cmdline(self):
if source is None:
return cmd
- return "cp {} {}".format(source, self._list_outputs()["out_file"])
+ return f"cp {source} {self._list_outputs()['out_file']}"
class _FSInjectBrainExtractedInputSpec(BaseInterfaceInputSpec):
diff --git a/niworkflows/interfaces/header.py b/niworkflows/interfaces/header.py
index 657c7f0f35d..df301aeb0b4 100644
--- a/niworkflows/interfaces/header.py
+++ b/niworkflows/interfaces/header.py
@@ -100,7 +100,7 @@ def _run_interface(self, runtime):
_copyxform(
self.inputs.hdr_file,
out_name,
- message="CopyXForm (niworkflows v%s)" % __version__,
+ message=f"CopyXForm (niworkflows v{__version__})",
)
self._results[f].append(out_name)
@@ -543,10 +543,7 @@ def _run_interface(self, runtime):
img.to_filename(out_fname)
if warning_txt:
- snippet = '
%s
\n%s\n' % (
- warning_txt,
- description,
- )
+ snippet = f'{warning_txt}
\n{description}\n'
with open(out_report, "w") as fobj:
fobj.write(indent(snippet, "\t" * 3))
diff --git a/niworkflows/interfaces/images.py b/niworkflows/interfaces/images.py
index aafb791fb4b..20b6bcb2fef 100644
--- a/niworkflows/interfaces/images.py
+++ b/niworkflows/interfaces/images.py
@@ -139,7 +139,7 @@ def _run_interface(self, runtime):
filenii = nb.load(f)
filenii = nb.squeeze_image(filenii)
if len(filenii.shape) == 5:
- raise RuntimeError("Input image (%s) is 5D." % f)
+ raise RuntimeError(f"Input image ({f}) is 5D.")
if filenii.dataobj.ndim == 4:
nii_list += nb.four_to_three(filenii)
else:
diff --git a/niworkflows/interfaces/itk.py b/niworkflows/interfaces/itk.py
index ce9ad7fed22..403bc52daa0 100644
--- a/niworkflows/interfaces/itk.py
+++ b/niworkflows/interfaces/itk.py
@@ -188,7 +188,7 @@ def _applytfms(args):
in_file, in_xform, ifargs, index, newpath = args
out_file = fname_presuffix(
- in_file, suffix="_xform-%05d" % index, newpath=newpath, use_ext=True
+ in_file, suffix=f"_xform-{index:05d}", newpath=newpath, use_ext=True
)
copy_dtype = ifargs.pop("copy_dtype", False)
@@ -250,8 +250,8 @@ def _arrange_xfms(transforms, num_files, tmp_folder):
if nxforms != num_files:
raise RuntimeError(
- "Number of transforms (%d) found in the ITK file does not match"
- " the number of input image files (%d)." % (nxforms, num_files)
+ f"Number of transforms ({nxforms}) found in the ITK file does"
+ f" not match the number of input image files ({num_files})."
)
# At this point splitting transforms will be necessary, generate a base name
@@ -262,7 +262,7 @@ def _arrange_xfms(transforms, num_files, tmp_folder):
split_xfms = []
for xform_i in range(nxforms):
# Find start token to extract
- startidx = tfdata.index("#Transform %d" % xform_i)
+ startidx = tfdata.index(f"#Transform {xform_i}")
next_xform = base_xform + tfdata[startidx + 1:startidx + 4] + [""]
xfm_file = out_base(xform_i)
with open(xfm_file, "w") as out_xfm:
diff --git a/niworkflows/interfaces/nibabel.py b/niworkflows/interfaces/nibabel.py
index 58766138581..eee3d587ddc 100644
--- a/niworkflows/interfaces/nibabel.py
+++ b/niworkflows/interfaces/nibabel.py
@@ -661,9 +661,8 @@ def _gen_reference(
# Keep 0, 2, 3, 4 unchanged
resampled.header.set_qform(xform, int(xform_code))
resampled.header.set_sform(xform, int(xform_code))
- resampled.header["descrip"] = "reference image generated by %s." % (
- message or "(unknown software)"
- )
+ message = message or "(unknown software)"
+ resampled.header["descrip"] = f"reference image generated by {message}."
resampled.to_filename(out_file)
return out_file
diff --git a/niworkflows/interfaces/norm.py b/niworkflows/interfaces/norm.py
index 4c4875cd597..2103b02eaf8 100644
--- a/niworkflows/interfaces/norm.py
+++ b/niworkflows/interfaces/norm.py
@@ -162,9 +162,7 @@ def _get_settings(self):
return self.inputs.settings
# Define a prefix for output files based on the modality of the moving image.
- filestart = "{}-mni_registration_{}_".format(
- self.inputs.moving.lower(), self.inputs.flavor
- )
+ filestart = f"{self.inputs.moving.lower()}-mni_registration_{self.inputs.flavor}_"
data_dir = load_data()
# Get a list of settings files that match the flavor.
@@ -224,7 +222,7 @@ def _run_interface(self, runtime):
NIWORKFLOWS_LOG.warning("Retry #%d failed.", self.retry)
# Save outputs (if available)
term_out = _write_outputs(
- interface_result.runtime, ".nipype-%04d" % self.retry
+ interface_result.runtime, f".nipype-{self.retry:04d}"
)
if term_out:
NIWORKFLOWS_LOG.warning(
@@ -243,7 +241,7 @@ def _run_interface(self, runtime):
# If all tries fail, raise an error.
raise RuntimeError(
- "Robust spatial normalization failed after %d retries." % (self.retry - 1)
+ f"Robust spatial normalization failed after {self.retry - 1} retries."
)
def _get_ants_args(self):
@@ -435,10 +433,9 @@ def _get_ants_args(self):
self._reference_image = ref_template
if not op.isfile(self._reference_image):
raise ValueError(
- """\
-The registration reference must be an existing file, but path "%s" \
+ f"""\
+The registration reference must be an existing file, but path "{ref_template}" \
cannot be found."""
- % ref_template
)
# Get the template specified by the user.
diff --git a/niworkflows/interfaces/reportlets/masks.py b/niworkflows/interfaces/reportlets/masks.py
index bac370fe280..ad3277801bb 100644
--- a/niworkflows/interfaces/reportlets/masks.py
+++ b/niworkflows/interfaces/reportlets/masks.py
@@ -140,7 +140,7 @@ def _post_run_hook(self, runtime):
if len(self.inputs.mask_files) != 1:
raise ValueError(
"ACompCorRPT only supports a single input mask. "
- "A list %s was found." % self.inputs.mask_files
+ f"A list {self.inputs.mask_files} was found."
)
self._anat_file = self.inputs.realigned_file
self._mask_file = self.inputs.mask_files[0]
@@ -182,7 +182,7 @@ def _post_run_hook(self, runtime):
if isinstance(high_variance_masks, list):
raise ValueError(
"TCompCorRPT only supports a single output high variance mask. "
- "A list %s was found." % high_variance_masks
+ f"A list {high_variance_masks} was found."
)
self._anat_file = self.inputs.realigned_file
self._mask_file = high_variance_masks
diff --git a/niworkflows/interfaces/surf.py b/niworkflows/interfaces/surf.py
index 0606805bf0e..3fc9c228ba8 100644
--- a/niworkflows/interfaces/surf.py
+++ b/niworkflows/interfaces/surf.py
@@ -509,13 +509,12 @@ def _run_interface(self, runtime):
"VolGeomC_A": "0.0",
"VolGeomC_S": "0.0",
}
- meta["AnatomicalStructurePrimary"] = "Cortex%s" % (
- "Left" if self.inputs.surf_key.startswith("lh") else "Right"
- )
+ _lr = "Left" if self.inputs.surf_key.startswith("lh") else "Right"
+ meta["AnatomicalStructurePrimary"] = f"Cortex{_lr}"
meta["AnatomicalStructureSecondary"] = SECONDARY_ANAT_STRUC[
self.inputs.surf_key.split(".")[-1]
]
- meta["Name"] = "%s_average.gii" % self.inputs.surf_key
+ meta["Name"] = f"{self.inputs.surf_key}_average.gii"
out_file = Path(runtime.cwd) / meta["Name"]
out_file = ply2gii(self.inputs.in_file, meta, out_file=out_file)
@@ -754,7 +753,7 @@ def ply2gii(in_file, metadata, out_file=None):
metadata.update(
zip(
("SurfaceCenterX", "SurfaceCenterY", "SurfaceCenterZ"),
- ["%.4f" % c for c in surf.centroid],
+ [f"{c:.4f}" for c in surf.centroid],
)
)
diff --git a/niworkflows/interfaces/tests/test_bids.py b/niworkflows/interfaces/tests/test_bids.py
index 0119aa883e2..6b2401e335f 100644
--- a/niworkflows/interfaces/tests/test_bids.py
+++ b/niworkflows/interfaces/tests/test_bids.py
@@ -652,7 +652,7 @@ def test_ReadSidecarJSON_connection(testdata_dir, field):
"derivatives, subjects_dir",
[
(os.getenv("FREESURFER_HOME"), "subjects"),
- ("/tmp", "{}/{}".format((os.getenv("FREESURFER_HOME"), "subjects"))),
+ ("/tmp", "{}/{}".format(os.getenv("FREESURFER_HOME"), "subjects")),
],
)
def test_fsdir_noaction(derivatives, subjects_dir):
@@ -661,7 +661,7 @@ def test_fsdir_noaction(derivatives, subjects_dir):
res = bintfs.BIDSFreeSurferDir(
derivatives=derivatives, subjects_dir=subjects_dir, freesurfer_home=fshome
).run()
- assert res.outputs.subjects_dir == "%s/subjects" % fshome
+ assert res.outputs.subjects_dir == f"{fshome}/subjects"
@pytest.mark.skipif(not os.getenv("FREESURFER_HOME"), reason="No FreeSurfer")
diff --git a/niworkflows/interfaces/tests/test_cifti.py b/niworkflows/interfaces/tests/test_cifti.py
index 2a18de7cb71..ae4086aaa7e 100644
--- a/niworkflows/interfaces/tests/test_cifti.py
+++ b/niworkflows/interfaces/tests/test_cifti.py
@@ -79,7 +79,7 @@ def test__create_cifti_image(tmp_path):
cifti_file = _create_cifti_image(bold_file, volume_label, dummy_fnames, dummy_fnames, 2.0)
cimg = nb.load(cifti_file)
- series, bm = [cimg.header.get_axis(i) for i in (0, 1)]
+ series, bm = (cimg.header.get_axis(i) for i in (0, 1))
assert len(series) == 1 # Time
assert len(bm) == 8 # Voxel
diff --git a/niworkflows/interfaces/tests/test_images.py b/niworkflows/interfaces/tests/test_images.py
index a013a7dcad0..3c2302219a8 100644
--- a/niworkflows/interfaces/tests/test_images.py
+++ b/niworkflows/interfaces/tests/test_images.py
@@ -58,13 +58,13 @@ def test_signal_extraction_equivalence(tmp_path, nvols, nmasks, ext, factor):
se1 = nl.SignalExtraction(
in_file=img_fname,
label_files=masks_fname,
- class_labels=["a%d" % i for i in range(nmasks)],
+ class_labels=[f"a{i}" for i in range(nmasks)],
out_file=nlsignals,
)
se2 = im.SignalExtraction(
in_file=img_fname,
label_files=masks_fname,
- class_labels=["a%d" % i for i in range(nmasks)],
+ class_labels=[f"a{i}" for i in range(nmasks)],
out_file=imsignals,
)
diff --git a/niworkflows/interfaces/tests/test_itk.py b/niworkflows/interfaces/tests/test_itk.py
index 7fd015f5b73..7811c3a3db2 100644
--- a/niworkflows/interfaces/tests/test_itk.py
+++ b/niworkflows/interfaces/tests/test_itk.py
@@ -52,7 +52,7 @@ def test_applytfms(tmpdir, ext, copy_dtype, in_dtype):
args = (in_file, in_xform, ifargs, 0, str(tmpdir))
out_file, cmdline = _applytfms(args)
- assert out_file == str(tmpdir / ("src_xform-%05d%s" % (0, ext)))
+ assert out_file == str(tmpdir / ("src_xform-{0:05d}{ext}"))
out_nii = nb.load(out_file)
assert np.allclose(nii.affine, out_nii.affine)
diff --git a/niworkflows/interfaces/tests/test_utility.py b/niworkflows/interfaces/tests/test_utility.py
index 0b18b55b2c2..3c66e8150e6 100644
--- a/niworkflows/interfaces/tests/test_utility.py
+++ b/niworkflows/interfaces/tests/test_utility.py
@@ -36,7 +36,7 @@ def test_KeySelect():
def test_tsv2json(tmp_path):
- Path.write_bytes(tmp_path / 'empty.tsv', bytes())
+ Path.write_bytes(tmp_path / 'empty.tsv', b'')
res = _tsv2json(tmp_path / 'empty.tsv', None, 'any_column')
assert res == {}
res = _tsv2json(tmp_path / 'empty.tsv', None, 'any_column', additional_metadata={'a': 'b'})
diff --git a/niworkflows/interfaces/utility.py b/niworkflows/interfaces/utility.py
index 6b9412dd129..a107008f74a 100644
--- a/niworkflows/interfaces/utility.py
+++ b/niworkflows/interfaces/utility.py
@@ -169,7 +169,8 @@ def __init__(self, keys=None, fields=None, **inputs):
_invalid = set(self.input_spec.class_editable_traits()).intersection(fields)
if _invalid:
- raise ValueError("Some fields are invalid (%s)." % ", ".join(_invalid))
+ _invalid = ", ".join(_invalid)
+ raise ValueError(f"Some fields are invalid ({_invalid}).")
self._fields = fields
@@ -196,7 +197,7 @@ def _check_len(self, name, new):
return
if name == "key" and new not in self.inputs.keys:
- raise ValueError('Selected key "%s" not found in the index' % new)
+ raise ValueError(f'Selected key "{new}" not found in the index')
if name in self._fields:
if isinstance(new, str) or len(new) < 1:
@@ -532,10 +533,10 @@ def _tsv2json(
re_to_snake = r"(^.+?|.*?)((?
@@ -548,7 +548,7 @@ def generate_reports(
logger = logging.getLogger("cli")
error_list = ", ".join(
- "%s (%d)" % (subid, err)
+ f"{subid} ({err})"
for subid, err in zip(subject_list, report_errors)
if err
)
diff --git a/niworkflows/tests/test_confounds.py b/niworkflows/tests/test_confounds.py
index 0cd871a417f..5d000869f14 100644
--- a/niworkflows/tests/test_confounds.py
+++ b/niworkflows/tests/test_confounds.py
@@ -37,7 +37,7 @@ def _smoke_test_report(report_interface, artifact_name):
save_artifacts = os.getenv("SAVE_CIRCLE_ARTIFACTS", False)
if save_artifacts:
copy(out_report, os.path.join(save_artifacts, artifact_name))
- assert os.path.isfile(out_report), 'Report "%s" does not exist' % out_report
+ assert os.path.isfile(out_report), f'Report "{out_report}" does not exist'
def _expand_test(model_formula):
diff --git a/niworkflows/tests/test_segmentation.py b/niworkflows/tests/test_segmentation.py
index 8022452ae55..e8de6114210 100644
--- a/niworkflows/tests/test_segmentation.py
+++ b/niworkflows/tests/test_segmentation.py
@@ -47,7 +47,7 @@ def _smoke_test_report(report_interface, artifact_name):
save_artifacts = os.getenv("SAVE_CIRCLE_ARTIFACTS", False)
if save_artifacts:
copy(out_report, os.path.join(save_artifacts, artifact_name))
- assert os.path.isfile(out_report), 'Report "%s" does not exist' % out_report
+ assert os.path.isfile(out_report), f'Report "{out_report}" does not exist'
@pytest.mark.skipif(not has_fsl, reason="No FSL")
@@ -129,7 +129,7 @@ def test_ROIsPlot2(tmp_path):
for i in range(1, 5):
seg = np.zeros_like(newdata, dtype="uint8")
seg[(newdata > 0) & (newdata <= i)] = 1
- out_file = str(tmp_path / ("segments%02d.nii.gz" % i))
+ out_file = str(tmp_path / (f"segments{i:02d}.nii.gz"))
nb.Nifti1Image(seg, im.affine, hdr).to_filename(out_file)
out_files.append(out_file)
roi_rpt = ROIsPlot(
diff --git a/niworkflows/tests/test_utils.py b/niworkflows/tests/test_utils.py
index 5f69bfaa534..848c11558f0 100644
--- a/niworkflows/tests/test_utils.py
+++ b/niworkflows/tests/test_utils.py
@@ -88,6 +88,6 @@ def test_compression(tmp_path):
size = int(os.stat(uncompressed).st_size)
size_compress = int(os.stat(compressed).st_size)
assert size >= size_compress, (
- "The uncompressed report is smaller (%d)"
- "than the compressed report (%d)" % (size, size_compress)
+ f"The uncompressed report is smaller ({size})"
+ f"than the compressed report ({size_compress})"
)
diff --git a/niworkflows/utils/images.py b/niworkflows/utils/images.py
index c75a238b1b8..2f5499e33b3 100644
--- a/niworkflows/utils/images.py
+++ b/niworkflows/utils/images.py
@@ -95,7 +95,8 @@ def _copyxform(ref_image, out_image, message=None):
header = resampled.header.copy()
header.set_qform(qform, int(qform_code))
header.set_sform(sform, int(sform_code))
- header["descrip"] = "xform matrices modified by %s." % (message or "(unknown)")
+ message = message or "(unknown)"
+ header["descrip"] = f"xform matrices modified by {message}."
newimg = resampled.__class__(resampled.dataobj, orig.affine, header)
newimg.to_filename(out_image)
diff --git a/niworkflows/utils/misc.py b/niworkflows/utils/misc.py
index 3c0fc798db0..1186415ab0f 100644
--- a/niworkflows/utils/misc.py
+++ b/niworkflows/utils/misc.py
@@ -155,7 +155,7 @@ def fix_multi_T1w_source_name(in_files):
base, in_file = os.path.split(in_file)
subject_label = in_file.split("_", 1)[0].split("-")[1]
- return os.path.join(base, "sub-%s_T1w.nii.gz" % subject_label)
+ return os.path.join(base, f"sub-{subject_label}_T1w.nii.gz")
def add_suffix(in_files, suffix):
diff --git a/niworkflows/utils/spaces.py b/niworkflows/utils/spaces.py
index aec2337137f..e3bb4e9a8a7 100644
--- a/niworkflows/utils/spaces.py
+++ b/niworkflows/utils/spaces.py
@@ -171,24 +171,25 @@ def __attrs_post_init__(self):
if self.space in self._standard_spaces:
object.__setattr__(self, "standard", True)
- _cohorts = ["%s" % t for t in _tfapi.TF_LAYOUT.get_cohorts(template=self.space)]
+ _cohorts = [f"{t}" for t in _tfapi.TF_LAYOUT.get_cohorts(template=self.space)]
if "cohort" in self.spec:
if not _cohorts:
raise ValueError(
- 'standard space "%s" does not accept a cohort '
- "specification." % self.space
+ f'standard space "{self.space}" does not accept a cohort '
+ "specification."
)
- if str(self.spec["cohort"]) not in _cohorts:
+ _cohort = str(self.spec["cohort"])
+ if _cohort not in _cohorts:
raise ValueError(
- 'standard space "%s" does not contain any cohort '
- 'named "%s".' % (self.space, self.spec["cohort"])
+ f'standard space "{self.space}" does not contain any cohort '
+ f'named "{_cohort}".'
)
elif _cohorts:
- _cohorts = ", ".join(['"cohort-%s"' % c for c in _cohorts])
+ _cohorts = ", ".join([f'"cohort-{c}"' for c in _cohorts])
raise ValueError(
- 'standard space "%s" is not fully defined.\n'
- "Set a valid cohort selector from: %s." % (self.space, _cohorts)
+ f'standard space "{self.space}" is not fully defined.\n'
+ f"Set a valid cohort selector from: {_cohorts}."
)
@property
@@ -207,8 +208,8 @@ def fullname(self):
"""
if "cohort" not in self.spec:
return self.space
- cohort = self.spec["cohort"]
- return f"{self.space}:cohort-{self.spec['cohort']}"
+ _cohort = self.spec["cohort"]
+ return f"{self.space}:cohort-{_cohort}"
@property
def legacyname(self):
@@ -245,8 +246,8 @@ def _check_name(self, attribute, value):
valid = list(self._standard_spaces) + NONSTANDARD_REFERENCES
if value not in valid:
raise ValueError(
- 'space identifier "%s" is invalid.\nValid '
- "identifiers are: %s" % (value, ", ".join(valid))
+ f'space identifier "{value}" is invalid.\n'
+ f"Valid identifiers are: {', '.join(valid)}"
)
def __str__(self):
@@ -530,7 +531,7 @@ def __str__(self):
"""
spaces = ", ".join([str(s) for s in self.references]) or "."
- return "Spatial References: %s" % spaces
+ return f"Spatial References: {spaces}"
@property
def references(self):
@@ -564,14 +565,14 @@ def append(self, value):
self._refs += [self.check_space(value)]
return
- raise ValueError('space "%s" already in spaces.' % str(value))
+ raise ValueError(f'space "{value}" already in spaces.')
def insert(self, index, value, error=True):
"""Concatenate one more space."""
if value not in self:
self._refs.insert(index, self.check_space(value))
elif error is True:
- raise ValueError('space "%s" already in spaces.' % str(value))
+ raise ValueError(f'space "{value}" already in spaces.')
def get_spaces(self, standard=True, nonstandard=True, dim=(2, 3)):
"""
diff --git a/niworkflows/viz/plots.py b/niworkflows/viz/plots.py
index a2091bf1aab..d6f369fd75f 100644
--- a/niworkflows/viz/plots.py
+++ b/niworkflows/viz/plots.py
@@ -426,7 +426,7 @@ def spikesplot(
ax.set_xlabel("time (frame #)")
else:
ax.set_xlabel("time (s)")
- ax.set_xticklabels(["%.02f" % t for t in (tr * np.array(xticks)).tolist()])
+ ax.set_xticklabels([f"{t:.02f}" for t in (tr * np.array(xticks)).tolist()])
# Handle Y axis
ylabel = "slice-wise noise average on background"
@@ -488,7 +488,7 @@ def spikesplot(
# if yticks:
# # ax.set_yticks(yticks)
- # # ax.set_yticklabels(['%.02f' % y for y in yticks])
+ # # ax.set_yticklabels([f'{y:.02f}' for y in yticks])
# # Plot maximum and minimum horizontal lines
# ax.plot((0, ntsteps - 1), (yticks[0], yticks[0]), 'k:')
# ax.plot((0, ntsteps - 1), (yticks[-1], yticks[-1]), 'k:')
@@ -577,13 +577,13 @@ def confoundplot(
else:
ax_ts.set_xlabel("time (s)")
labels = tr * np.array(xticks)
- ax_ts.set_xticklabels(["%.02f" % t for t in labels.tolist()])
+ ax_ts.set_xticklabels([f"{t:%.02f}" for t in labels.tolist()])
else:
ax_ts.set_xticklabels([])
if name is not None:
if units is not None:
- name += " [%s]" % units
+ name += f" [{units}]"
ax_ts.annotate(
name,
@@ -651,10 +651,11 @@ def confoundplot(
stdv = 0
p95 = 0
+ units = units or ""
stats_label = (
- r"max: {max:.3f}{units} $\bullet$ mean: {mean:.3f}{units} "
- r"$\bullet$ $\sigma$: {sigma:.3f}"
- ).format(max=maxv, mean=mean, units=units or "", sigma=stdv)
+ fr"max: {maxv:.3f}{units} $\bullet$ mean: {mean:.3f}{units} "
+ fr"$\bullet$ $\sigma$: {stdv:.3f}"
+ )
ax_ts.annotate(
stats_label,
xy=(0.98, 0.7),
@@ -678,7 +679,7 @@ def confoundplot(
# Annotate percentile 95
ax_ts.plot((0, ntsteps - 1), [p95] * 2, linewidth=0.1, color="lightgray")
ax_ts.annotate(
- "%.2f" % p95,
+ f"{p95:%.2f}",
xy=(0, p95),
xytext=(-1, 0),
textcoords="offset points",
@@ -695,7 +696,7 @@ def confoundplot(
ax_ts.plot((0, ntsteps - 1), [thr] * 2, linewidth=0.2, color="dimgray")
ax_ts.annotate(
- "%.2f" % thr,
+ f"{thr:.2f}",
xy=(0, thr),
xytext=(-1, 0),
textcoords="offset points",
@@ -822,14 +823,14 @@ def compcor_variance_plot(
ax[m].text(
0,
100 * thr,
- "{:.0f}".format(100 * thr),
+ f"{100 * thr:.0f}",
fontsize="x-small",
bbox=bbox_txt,
)
ax[m].text(
varexp[thr][0],
25,
- "{} components explain\n{:.0f}% of variance".format(varexp[thr][0], 100 * thr),
+ f"{varexp[thr][0]} components explain\n{100 * thr:.0f}% of variance",
rotation=90,
horizontalalignment="center",
fontsize="xx-small",