Skip to content

Commit 12d9858

Browse files
committed
Merge tag '1.1.12'
1.1.12 (March 19, 2020) Bug-fix release in the 1.1.x series. * FIX: Update naming patterns in figures.json (nipreps#483) * FIX: Add CE agent to output figure filename templates (nipreps#482)
2 parents bfffaf8 + 0277b6e commit 12d9858

File tree

5 files changed

+107
-25
lines changed

5 files changed

+107
-25
lines changed

CHANGES.rst

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,16 @@
1+
1.1.12 (March 19, 2020)
2+
=======================
3+
Bug-fix release in the 1.1.x series.
4+
5+
* FIX: Update naming patterns in figures.json (#483)
6+
* FIX: Add CE agent to output figure filename templates (#482)
7+
8+
1.1.11 (March 17, 2020)
9+
=======================
10+
Bug-fix release to improve CIFTI compatibility with workbench tools.
11+
12+
* FIX: Ensure BOLD and label orientations are equal (#477)
13+
114
1.1.10 (March 11, 2020)
215
=======================
316
Bug-fix release in the 1.1.x series.

niworkflows/interfaces/cifti.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,8 @@ def _create_cifti_image(bold_file, label_file, bold_surfs, annotation_files, tr,
318318
warnings.warn("Resampling bold volume to match label dimensions")
319319
bold_img = resample_to_img(bold_img, label_img)
320320

321+
bold_img = _reorient_image(bold_img, target_img=label_img)
322+
321323
bold_data = bold_img.get_fdata(dtype='float32')
322324
timepoints = bold_img.shape[3]
323325
label_data = np.asanyarray(label_img.dataobj).astype('int16')
@@ -422,3 +424,66 @@ def _create_cifti_image(bold_file, label_file, bold_surfs, annotation_files, tr,
422424
out_file = "{}.dtseries.nii".format(split_filename(bold_file)[1])
423425
ci.save(img, out_file)
424426
return Path.cwd() / out_file
427+
428+
429+
def _reorient_image(img, *, target_img=None, orientation=None):
430+
"""
431+
Coerce an image to a target orientation.
432+
433+
.. note::
434+
Only RAS -> LAS conversion is currently supported
435+
436+
Parameters
437+
----------
438+
img : :obj:`SpatialImage`
439+
image to be reoriented
440+
target_img : :obj:`SpatialImage`, optional
441+
target in desired orientation
442+
orientation : :obj:`str` or :obj:`tuple`, optional
443+
desired orientation, if no target image is provided
444+
445+
.. testsetup::
446+
>>> img = nb.load(Path(test_data) / 'testRobustMNINormalizationRPTMovingWarpedImage.nii.gz')
447+
>>> las_img = img.as_reoriented([[0, -1], [1, 1], [2, 1]])
448+
449+
Examples
450+
--------
451+
>>> nimg = _reorient_image(img, target_img=img)
452+
>>> nb.aff2axcodes(nimg.affine)
453+
('R', 'A', 'S')
454+
455+
>>> nimg = _reorient_image(img, target_img=las_img)
456+
>>> nb.aff2axcodes(nimg.affine)
457+
('L', 'A', 'S')
458+
459+
>>> nimg = _reorient_image(img, orientation='LAS')
460+
>>> nb.aff2axcodes(nimg.affine)
461+
('L', 'A', 'S')
462+
463+
>>> _reorient_image(img, orientation='LPI')
464+
Traceback (most recent call last):
465+
...
466+
NotImplementedError: Cannot reorient ...
467+
468+
>>> _reorient_image(img)
469+
Traceback (most recent call last):
470+
...
471+
RuntimeError: No orientation ...
472+
473+
"""
474+
orient0 = nb.aff2axcodes(img.affine)
475+
if target_img is not None:
476+
orient1 = nb.aff2axcodes(target_img.affine)
477+
elif orientation is not None:
478+
orient1 = tuple(orientation)
479+
else:
480+
raise RuntimeError("No orientation to reorient to!")
481+
482+
if orient0 == orient1: # already in desired orientation
483+
return img
484+
elif orient0 == tuple('RAS') and orient1 == tuple('LAS'): # RAS -> LAS
485+
return img.as_reoriented([[0, -1], [1, 1], [2, 1]])
486+
else:
487+
raise NotImplementedError(
488+
"Cannot reorient {0} to {1}.".format(orient0, orient1)
489+
)

niworkflows/reports/core.py

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ class Report(object):
234234
>>> robj.generate_report()
235235
0
236236
>>> len((testdir / 'out' / 'fmriprep' / 'sub-01.html').read_text())
237-
36450
237+
36540
238238
239239
.. testcleanup::
240240
@@ -311,17 +311,14 @@ def index(self, config):
311311
reportlets = []
312312
for c in list_combos:
313313
# do not display entities with the value None.
314-
c = list(filter(None, c))
315-
ent = list(compress(entities, c))
316-
missing_entities = list(set(entities) - set(ent))
314+
c_filt = list(filter(None, c))
315+
ent_filt = list(compress(entities, c))
317316
# Set a common title for this particular combination c
318317
title = 'Reports for: %s.' % ', '.join(
319-
['%s <span class="bids-entity">%s</span>' % (ent[i], c[i])
320-
for i in range(len(c))])
318+
['%s <span class="bids-entity">%s</span>' % (ent_filt[i], c_filt[i])
319+
for i in range(len(c_filt))])
321320
for cfg in subrep_cfg['reportlets']:
322-
for m_e in missing_entities:
323-
cfg['bids'].pop(m_e, None)
324-
cfg['bids'].update({ent[i]: c[i] for i in range(len(c))})
321+
cfg['bids'].update({entities[i]: c[i] for i in range(len(c))})
325322
rlet = Reportlet(self.layout, self.out_dir, config=cfg)
326323
if not rlet.is_empty():
327324
rlet.title = title

niworkflows/reports/figures.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,15 @@
2121
"pattern": "[_/\\\\]acq-([a-zA-Z0-9]+)"
2222
},
2323
{
24-
"name": "ce",
24+
"name": "ceagent",
2525
"pattern": "[_/\\\\]ce-([a-zA-Z0-9]+)"
2626
},
2727
{
2828
"name": "reconstruction",
2929
"pattern": "[_/\\\\]rec-([a-zA-Z0-9]+)"
3030
},
3131
{
32-
"name": "dir",
32+
"name": "direction",
3333
"pattern": "[_/\\\\]dir-([a-zA-Z0-9]+)"
3434
},
3535
{
@@ -47,7 +47,7 @@
4747
},
4848
{
4949
"name": "echo",
50-
"pattern": "[_/\\\\]echo-([0-9]+)\\_bold."
50+
"pattern": "[_/\\\\]echo-([0-9]+)"
5151
},
5252
{
5353
"name": "recording",
@@ -112,7 +112,7 @@
112112
],
113113

114114
"default_path_patterns": [
115-
"sub-{subject}[/ses-{session}]/{datatype<anat|figures>}/sub-{subject}[_ses-{session}][_acq-{acquisition}][_ce-{contrast}][_rec-{reconstruction}][_space-{space}][_desc-{desc}]_{suffix<T1w|T2w|T1rho|T1map|T2map|T2star|FLAIR|FLASH|PDmap|PD|PDT2|inplaneT[12]|angio|dseg|mask>}.{extension<html|svg>}",
116-
"sub-{subject}[/ses-{session}]/{datatype<func|figures>}/sub-{subject}[_ses-{session}]_task-{task}[_acq-{acquisition}][_rec-{reconstruction}][_run-{run}][_echo-{echo}][_space-{space}][_desc-{desc}]_{suffix<bold>}.{extension<html|svg>}"
115+
"sub-{subject}[/ses-{session}]/{datatype<anat|figures>}/sub-{subject}[_ses-{session}][_acq-{acquisition}][_ce-{ceagent}][_rec-{reconstruction}][_space-{space}][_desc-{desc}]_{suffix<T1w|T2w|T1rho|T1map|T2map|T2star|FLAIR|FLASH|PDmap|PD|PDT2|inplaneT[12]|angio|dseg|mask>}.{extension<html|svg>}",
116+
"sub-{subject}[/ses-{session}]/{datatype<func|figures>}/sub-{subject}[_ses-{session}]_task-{task}[_acq-{acquisition}][_ce-{ceagent}][_dir-{direction}][_rec-{reconstruction}][_run-{run}][_echo-{echo}][_space-{space}][_desc-{desc}]_{suffix<bold>}.{extension<html|svg>}"
117117
]
118118
}

niworkflows/reports/tests/test_core.py

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
import matplotlib.pyplot as plt
1111
from bids.layout.writing import build_path
12+
from bids.layout import BIDSLayout
1213

1314
import pytest
1415

@@ -24,26 +25,28 @@ def bids_sessions(tmpdir_factory):
2425
pattern = (
2526
"sub-{subject}[/ses-{session}]/{datatype<anat|func>}/"
2627
"sub-{subject}[_ses-{session}][_task-{task}][_acq-{acquisition}]"
27-
"[_ce-{contrast}][_dir-{direction}][_rec-{reconstruction}]"
28+
"[_ce-{ceagent}][_dir-{direction}][_rec-{reconstruction}]"
2829
"[_mod-{modality}][_run-{run}][_echo-{echo}][_space-{space}]"
2930
"[_desc-{desc}]_{suffix<dseg|T1w|bold>}.{extension<svg>}"
3031
)
3132
subjects = ['01']
3233
tasks = ['t1', 't2', 't3']
3334
runs = ['01', '02', None]
35+
ces = ['none', 'Gd']
3436
descs = ['aroma', 'bbregister', 'carpetplot', 'rois']
3537
# create functional data for both sessions
36-
ses1_combos = product(subjects, ['1'], tasks, runs, descs)
37-
ses2_combos = product(subjects, ['2'], tasks, [None], descs)
38+
ses1_combos = product(subjects, ['1'], tasks, [None], runs, descs)
39+
ses2_combos = product(subjects, ['2'], tasks, ces, [None], descs)
3840
# have no runs in the second session (ex: dmriprep test data)
3941
# https://github.com/nipreps/dmriprep/pull/59
4042
all_combos = list(ses1_combos) + list(ses2_combos)
4143

42-
for subject, session, task, run, desc in all_combos:
44+
for subject, session, task, ce, run, desc in all_combos:
4345
entities = {
4446
'subject': subject,
4547
'session': session,
4648
'task': task,
49+
'ceagent': ce,
4750
'run': run,
4851
'desc': desc,
4952
'extension': 'svg',
@@ -143,10 +146,10 @@ def test_process_orderings_small(test_report1, orderings,
143146
@pytest.mark.parametrize(
144147
"orderings,expected_entities,first_value_combo,last_value_combo",
145148
[
146-
(['session', 'task', 'run'],
147-
['session', 'task', 'run'],
148-
('1', 't1', None),
149-
('2', 't3', None),
149+
(['session', 'task', 'ceagent', 'run'],
150+
['session', 'task', 'ceagent', 'run'],
151+
('1', 't1', None, None),
152+
('2', 't3', 'none', None),
150153
),
151154
(['run', 'task', 'session'],
152155
['run', 'task', 'session'],
@@ -182,6 +185,7 @@ def test_process_orderings_large(test_report2, orderings,
182185
("run"),
183186
("session,task"),
184187
("session,task,run"),
188+
("session,task,ceagent,run"),
185189
("session,task,acquisition,ceagent,reconstruction,direction,run,echo"),
186190
("session,task,run,madeupentity"),
187191
])
@@ -198,12 +202,15 @@ def test_generated_reportlets(bids_sessions, ordering):
198202
# expected number of reportlets
199203
expected_reportlets_num = len(report.layout.get(extension='svg'))
200204
# bids_session uses these entities
201-
needed_entities = ['session', 'task', 'run']
205+
needed_entities = ['session', 'task', 'ceagent', 'run']
202206
# the last section is the most recently run
203207
reportlets_num = len(report.sections[-1].reportlets)
208+
# get the number of figures in the output directory
209+
out_layout = BIDSLayout(out_dir, config='figures', validate=False)
210+
out_figs = len(out_layout.get())
204211
# if ordering does not contain all the relevent entities
205212
# then there should be fewer reportlets than expected
206213
if all(ent in ordering for ent in needed_entities):
207-
assert reportlets_num == expected_reportlets_num
214+
assert reportlets_num == expected_reportlets_num == out_figs
208215
else:
209-
assert reportlets_num < expected_reportlets_num
216+
assert reportlets_num < expected_reportlets_num == out_figs

0 commit comments

Comments
 (0)