Skip to content

Commit 0ecd867

Browse files
authored
Merge pull request #10 from dbic/adds_populate_intended_for
Two quick and dirty patches while I have tried to use that branch
2 parents d3b8210 + 141f6e9 commit 0ecd867

File tree

5 files changed

+48
-40
lines changed

5 files changed

+48
-40
lines changed

heudiconv/bids.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import os
55
import os.path as op
66
import logging
7+
import numpy as np
78
import re
89
from collections import OrderedDict
910
from datetime import datetime
@@ -612,8 +613,10 @@ def get_key_info_for_fmap_assignment(json_file, matching_parameter='ImagingVolum
612613
elif matching_parameter == 'ImagingVolume':
613614
from nibabel import load as nb_load
614615
nifti_file = glob(remove_suffix(json_file, '.json') + '.nii*')
616+
assert len(nifti_file) == 1
617+
nifti_file = nifti_file[0]
615618
nifti_header = nb_load(nifti_file).header
616-
key_info = [nifti_header.affine, nifti_header.dim[1:3]]
619+
key_info = [nifti_header.get_best_affine(), nifti_header.get_data_shape()[:3]]
617620
elif matching_parameter == 'AcquisitionLabel':
618621
# Check the acq label for the fmap and the modality for others:
619622
modality = op.basename(op.dirname(json_file))
@@ -677,10 +680,13 @@ def find_compatible_fmaps_for_run(json_file, fmap_groups, matching_parameters=['
677680
compatible = False
678681
for param in matching_parameters:
679682
fm_info = get_key_info_for_fmap_assignment(fm_group[0], param)
680-
if json_info[param] == fm_info:
681-
compatible = True
683+
# for the case in which key_info is a list of strings:
684+
if type(json_info[param][0]):
685+
compatible = json_info[param] == fm_info
682686
else:
683-
compatible = False
687+
# allow for tiny differences between the affines etc
688+
compatible = all(np.allclose(x, y) for x, y in zip(json_info[param], fm_info))
689+
if not compatible:
684690
continue # don't bother checking more params
685691
if compatible:
686692
compatible_fmap_groups[fm_key] = fm_group

heudiconv/main.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,11 +109,15 @@ def process_extra_commands(outdir, command, files, dicom_dir_template,
109109
from .utils import get_heuristic_description
110110
print(get_heuristic_description(heuristic, full=True))
111111
elif command == 'populate-intended-for':
112+
kwargs = {}
113+
if heuristic:
114+
heuristic = load_heuristic(heuristic)
115+
kwargs = getattr(heuristic, 'POPULATE_INTENDED_FOR_OPTS', {})
112116
for subj in subjs:
113117
session_path = op.join(outdir, 'sub-' + subj)
114118
if session:
115119
session_path = op.join(session_path, 'ses-' + session)
116-
populate_intended_for(session_path)
120+
populate_intended_for(session_path, **kwargs)
117121
else:
118122
raise ValueError("Unknown command %s" % command)
119123
return
172 Bytes
Binary file not shown.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
-1.99887669 0.0670080110 0.00144872535 109.236588
2+
0.0650372952 1.94962955 -0.441264838 -71.7261658
3+
0.0161963794 0.440969884 1.95071352 -64.1231308
4+
0 0 0 1
5+
5 5 5 1

heudiconv/tests/test_bids.py

Lines changed: 28 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,20 @@
1010
from datetime import (datetime,
1111
timedelta,
1212
)
13-
from collections import (namedtuple,
14-
OrderedDict,
13+
from collections import (OrderedDict,
1514
)
1615
from glob import glob
1716

1817
import nibabel
18+
from numpy import testing as np_testing
1919

2020
from heudiconv.utils import (
2121
load_json,
2222
save_json,
2323
create_tree,
24+
remove_suffix,
2425
)
26+
2527
from heudiconv.bids import (
2628
maybe_na,
2729
treat_age,
@@ -38,6 +40,10 @@
3840
BIDSFile,
3941
)
4042

43+
from .utils import (
44+
TESTS_DATA_PATH,
45+
)
46+
4147
import pytest
4248

4349
def test_maybe_na():
@@ -63,7 +69,7 @@ def test_treat_age():
6369
TODAY = datetime.today()
6470

6571

66-
A_SHIM = ['{0:.4f}'.format(random()) for i in range(SHIM_LENGTH)]
72+
A_SHIM = [random() for i in range(SHIM_LENGTH)]
6773
def test_get_shim_setting(tmpdir):
6874
""" Tests for get_shim_setting """
6975
json_dir = op.join(str(tmpdir), 'foo')
@@ -80,38 +86,24 @@ def test_get_shim_setting(tmpdir):
8086
assert get_shim_setting(json_name) == A_SHIM
8187

8288

83-
def test_get_key_info_for_fmap_assignment(tmpdir, monkeypatch):
89+
def test_get_key_info_for_fmap_assignment(tmpdir):
8490
"""
8591
Test get_key_info_for_fmap_assignment
8692
"""
8793

88-
# Stuff needed to mock reading of a NIfTI file header:
89-
90-
# affines (qforms/sforms) are 4x4 matrices
91-
MY_AFFINE = [[random() for i in range(4)] for j in range(4)]
92-
# dims are arrays with 8 elements with the first one indicating the number
93-
# of dims in the image; remaining elements are 1:
94-
MY_DIM = [4] + [round(256 * random()) for i in range(4)] + [1] * 3
95-
# We use namedtuples so that we can use the .dot notation, to mock
96-
# nibabel headers:
97-
MyHeader = namedtuple('MyHeader', 'affine dim')
98-
MY_HEADER = MyHeader(MY_AFFINE, MY_DIM)
99-
MyMockNifti = namedtuple('MyMockNifti', 'header')
100-
101-
def mock_nibabel_load(file):
102-
"""
103-
Pretend we run nibabel.load, but return only a header with just a few fields
104-
"""
105-
return MyMockNifti(MY_HEADER)
106-
monkeypatch.setattr(nibabel, "load", mock_nibabel_load)
107-
108-
json_name = op.join(str(tmpdir), 'foo.json')
94+
nifti_file = op.join(TESTS_DATA_PATH, 'sample_nifti.nii.gz')
95+
# Get the expected parameters from the NIfTI header:
96+
MY_HEADER = nibabel.ni1.np.loadtxt(
97+
op.join(TESTS_DATA_PATH, remove_suffix(nifti_file, '.nii.gz') + '_params.txt')
98+
)
99+
json_name = op.join(TESTS_DATA_PATH, remove_suffix(nifti_file, '.nii.gz') + '.json')
109100

110101
# 1) Call for a non-existing file should give an error:
111102
with pytest.raises(FileNotFoundError):
112103
assert get_key_info_for_fmap_assignment('foo.json')
113104

114105
# 2) matching_parameters = 'Shims'
106+
json_name = op.join(TESTS_DATA_PATH, remove_suffix(nifti_file, '.nii.gz') + '.json')
115107
save_json(json_name, {SHIM_KEY: A_SHIM}) # otherwise get_key_info_for_fmap_assignment will give an error
116108
key_info = get_key_info_for_fmap_assignment(
117109
json_name, matching_parameter='Shims'
@@ -122,7 +114,8 @@ def mock_nibabel_load(file):
122114
key_info = get_key_info_for_fmap_assignment(
123115
json_name, matching_parameter='ImagingVolume'
124116
)
125-
assert key_info == [MY_AFFINE, MY_DIM[1:3]]
117+
np_testing.assert_almost_equal(key_info[0], MY_HEADER[:4], decimal=6)
118+
np_testing.assert_almost_equal(key_info[1], MY_HEADER[4][:3], decimal=6)
126119

127120
# 4) matching_parameters = 'Force'
128121
key_info = get_key_info_for_fmap_assignment(
@@ -222,10 +215,10 @@ def create_dummy_pepolar_bids_session(session_path):
222215
# 1) Simulate the file structure for a session:
223216

224217
# Generate some random ShimSettings:
225-
anat_shims = ['{0:.4f}'.format(random()) for i in range(SHIM_LENGTH)]
226-
dwi_shims = ['{0:.4f}'.format(random()) for i in range(SHIM_LENGTH)]
227-
func_shims_A = ['{0:.4f}'.format(random()) for i in range(SHIM_LENGTH)]
228-
func_shims_B = ['{0:.4f}'.format(random()) for i in range(SHIM_LENGTH)]
218+
anat_shims = [random() for i in range(SHIM_LENGTH)]
219+
dwi_shims = [random() for i in range(SHIM_LENGTH)]
220+
func_shims_A = [random() for i in range(SHIM_LENGTH)]
221+
func_shims_B = [random() for i in range(SHIM_LENGTH)]
229222

230223
# Dict with the file structure for the session:
231224
# -anat:
@@ -249,7 +242,7 @@ def create_dummy_pepolar_bids_session(session_path):
249242
'{p}_acq-A_bold.json'.format(p=prefix): {'ShimSetting': func_shims_A},
250243
'{p}_acq-B_bold.json'.format(p=prefix): {'ShimSetting': func_shims_B},
251244
'{p}_acq-unmatched_bold.json'.format(p=prefix): {
252-
'ShimSetting': ['{0:.4f}'.format(random()) for i in range(SHIM_LENGTH)]
245+
'ShimSetting': [random() for i in range(SHIM_LENGTH)]
253246
},
254247
})
255248
# -fmap:
@@ -541,9 +534,9 @@ def create_dummy_magnitude_phase_bids_session(session_path):
541534
# 1) Simulate the file structure for a session:
542535

543536
# Generate some random ShimSettings:
544-
dwi_shims = ['{0:.4f}'.format(random()) for i in range(SHIM_LENGTH)]
545-
func_shims_A = ['{0:.4f}'.format(random()) for i in range(SHIM_LENGTH)]
546-
func_shims_B = ['{0:.4f}'.format(random()) for i in range(SHIM_LENGTH)]
537+
dwi_shims = [random() for i in range(SHIM_LENGTH)]
538+
func_shims_A = [random() for i in range(SHIM_LENGTH)]
539+
func_shims_B = [random() for i in range(SHIM_LENGTH)]
547540

548541
# Dict with the file structure for the session:
549542
# -dwi:
@@ -561,7 +554,7 @@ def create_dummy_magnitude_phase_bids_session(session_path):
561554
'{p}_acq-A_bold.json'.format(p=prefix): {'ShimSetting': func_shims_A},
562555
'{p}_acq-B_bold.json'.format(p=prefix): {'ShimSetting': func_shims_B},
563556
'{p}_acq-unmatched_bold.json'.format(p=prefix): {
564-
'ShimSetting': ['{0:.4f}'.format(random()) for i in range(SHIM_LENGTH)]
557+
'ShimSetting': [random() for i in range(SHIM_LENGTH)]
565558
},
566559
})
567560
# -fmap:

0 commit comments

Comments
 (0)