Skip to content

Commit c7c20ea

Browse files
authored
Merge pull request #578 from effigies/fix/legacy_dtseries_json
FIX: Cordon off .dtseries.json contents
2 parents 48a9cd9 + 87a93db commit c7c20ea

File tree

2 files changed

+56
-3
lines changed

2 files changed

+56
-3
lines changed

niworkflows/interfaces/bids.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -653,9 +653,21 @@ def _run_interface(self, runtime):
653653
}
654654
)
655655
if self._metadata:
656-
sidecar = Path(self._results["out_file"][0]).parent / (
657-
"%s.json" % _splitext(self._results["out_file"][0])[0]
658-
)
656+
out_file = Path(self._results["out_file"][0])
657+
# 1.3.x hack
658+
# For dtseries, we have been generating weird non-BIDS JSON files.
659+
# We can safely keep producing them to avoid breaking derivatives, but
660+
# only the existing keys should keep going into them.
661+
if out_file.name.endswith(".dtseries.nii"):
662+
legacy_metadata = {}
663+
for key in ("grayordinates", "space", "surface", "surface_density", "volume"):
664+
if key in self._metadata:
665+
legacy_metadata[key] = self._metadata.pop(key)
666+
if legacy_metadata:
667+
sidecar = out_file.parent / f"{_splitext(str(out_file))[0]}.json"
668+
sidecar.write_text(dumps(legacy_metadata, sort_keys=True, indent=2))
669+
# The future: the extension is the first . and everything after
670+
sidecar = out_file.parent / f"{out_file.name.split('.', 1)[0]}.json"
659671
sidecar.write_text(dumps(self._metadata, sort_keys=True, indent=2))
660672
self._results["out_meta"] = str(sidecar)
661673
return runtime

niworkflows/interfaces/tests/test_bids.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"""Tests on BIDS compliance."""
22
import os
33
from pathlib import Path
4+
import json
45

56
import numpy as np
67
import nibabel as nb
@@ -278,6 +279,46 @@ def test_DerivativesDataSink_build_path(
278279
assert Path(out).relative_to(tmp_path) == Path(base) / exp
279280

280281

282+
def test_DerivativesDataSink_dtseries_json_hack(tmp_path):
283+
cifti_fname = str(tmp_path / "test.dtseries.nii")
284+
285+
axes = (nb.cifti2.SeriesAxis(start=0, step=2, size=20),
286+
nb.cifti2.BrainModelAxis.from_mask(np.ones((5, 5, 5))))
287+
hdr = nb.cifti2.cifti2_axes.to_header(axes)
288+
cifti = nb.Cifti2Image(np.zeros(hdr.matrix.get_data_shape(), dtype=np.float32),
289+
header=hdr)
290+
cifti.nifti_header.set_intent("ConnDenseSeries")
291+
cifti.to_filename(cifti_fname)
292+
293+
source_file = tmp_path / "bids" / "sub-01" / "func" / "sub-01_task-rest_bold.nii.gz"
294+
source_file.parent.mkdir(parents=True)
295+
source_file.touch()
296+
297+
dds = bintfs.DerivativesDataSink(
298+
in_file=cifti_fname,
299+
base_directory=str(tmp_path),
300+
source_file=str(source_file),
301+
compress=False,
302+
out_path_base="",
303+
space="fsLR",
304+
grayordinates="91k",
305+
RepetitionTime=2.0,
306+
)
307+
308+
res = dds.run()
309+
310+
out_path = Path(res.outputs.out_file)
311+
312+
assert out_path.name == "sub-01_task-rest_space-fsLR_bold.dtseries.nii"
313+
old_sidecar = out_path.with_name("sub-01_task-rest_space-fsLR_bold.dtseries.json")
314+
new_sidecar = out_path.with_name("sub-01_task-rest_space-fsLR_bold.json")
315+
316+
assert old_sidecar.exists()
317+
assert "grayordinates" in json.loads(old_sidecar.read_text())
318+
assert new_sidecar.exists()
319+
assert "RepetitionTime" in json.loads(new_sidecar.read_text())
320+
321+
281322
@pytest.mark.parametrize(
282323
"space, size, units, xcodes, zipped, fixed, data_dtype",
283324
[

0 commit comments

Comments
 (0)