Skip to content

Commit 664c064

Browse files
committed
Merge pull request nipy#348 from yarikoptic/nibls-header
MRG: add -H for nib-ls to list desired header fields saw https://neurostars.org/p/3361/ which triggered to do this tiny hack (time for tests for the beast will come!) Now it should be possible to specify some header fields desired to be output, which will get listed as well, e.g.: ``` $> $PWD/bin/nib-ls -H dim,bitpix /usr/share/data/fsl-mni152-templates/MNI152*brain.nii.gz /usr/share/data/fsl-mni152-templates/MNI152lin_T1_1mm_brain.nii.gz uint8 [182, 218, 182] 1.00x1.00x1.00 [ 3 182 218 182 1 1 1 1] 8 /usr/share/data/fsl-mni152-templates/MNI152lin_T1_2mm_brain.nii.gz uint8 [ 91, 109, 91] 2.00x2.00x2.00 [ 3 91 109 91 1 1 1 1] 8 /usr/share/data/fsl-mni152-templates/MNI152_T1_1mm_brain.nii.gz int16 [182, 218, 182] 1.00x1.00x1.00 [ 3 182 218 182 1 1 1 1] 16 /usr/share/data/fsl-mni152-templates/MNI152_T1_2mm_brain.nii.gz int16 [ 91, 109, 91] 2.00x2.00x2.00 [ 3 91 109 91 1 1 1 1] 16 ``` using '*' as argument would spit out all the header fields
2 parents 5e9e942 + a421517 commit 664c064

File tree

4 files changed

+116
-8
lines changed

4 files changed

+116
-8
lines changed

bin/nib-ls

+22-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ Output a summary table for neuroimaging files (resolution, dimensionality, etc.)
1313
from __future__ import division, print_function, absolute_import
1414

1515
__author__ = 'Yaroslav Halchenko'
16-
__copyright__ = 'Copyright (c) 2011-2012 Yaroslav Halchenko ' \
16+
__copyright__ = 'Copyright (c) 2011-2015 Yaroslav Halchenko ' \
1717
'and NiBabel contributors'
1818
__license__ = 'MIT'
1919

@@ -141,6 +141,10 @@ def get_opt_parser():
141141
dest="verbose", default=0,
142142
help="Make more noise. Could be specified multiple times"),
143143

144+
Option("-H", "--header-fields",
145+
dest="header_fields", default='',
146+
help="Header fields (comma separated) to be printed as well (if present)"),
147+
144148
Option("-s", "--stats",
145149
action="store_true", dest='stats', default=False,
146150
help="Output basic data statistics"),
@@ -180,6 +184,23 @@ def proc_file(f, opts):
180184
else:
181185
row += [ '' ]
182186

187+
if opts.header_fields:
188+
# signals "all fields"
189+
if opts.header_fields == 'all':
190+
# TODO: might vary across file types, thus prior sensing
191+
# would be needed
192+
header_fields = h.keys()
193+
else:
194+
header_fields = opts.header_fields.split(',')
195+
196+
for f in header_fields:
197+
if not f: # skip empty
198+
continue
199+
try:
200+
row += [str(h[f])]
201+
except (KeyError, ValueError):
202+
row += [ 'error' ]
203+
183204
try:
184205
if (hasattr(h, 'get_qform') and hasattr(h, 'get_sform')
185206
and (h.get_qform() != h.get_sform()).any()):

nibabel/testing/__init__.py

+12
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
''' Utilities for testing '''
1010
from __future__ import division, print_function
1111

12+
import re
1213
import os
1314
import sys
1415
import warnings
@@ -59,6 +60,17 @@ def assert_allclose_safely(a, b, match_nans=True):
5960
assert_true(np.allclose(a, b))
6061

6162

63+
def assert_re_in(regex, c, flags=0):
64+
"""Assert that container (list, str, etc) contains entry matching the regex
65+
"""
66+
if not isinstance(c, (list, tuple)):
67+
c = [c]
68+
for e in c:
69+
if re.match(regex, e, flags=flags):
70+
return
71+
raise AssertionError("Not a single entry matched %r in %r" % (regex, c))
72+
73+
6274
def get_fresh_mod(mod_name=__name__):
6375
# Get this module, with warning registry empty
6476
my_mod = sys.modules[mod_name]

nibabel/tests/test_scripts.py

+60-6
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,13 @@
2020

2121
from nose.tools import (assert_true, assert_false, assert_not_equal,
2222
assert_equal)
23+
from nose import SkipTest
2324

2425
from numpy.testing import assert_almost_equal
2526

2627
from .scriptrunner import ScriptRunner
2728
from .nibabel_data import needs_nibabel_data
28-
from ..testing import assert_dt_equal
29+
from ..testing import assert_dt_equal, assert_re_in
2930
from .test_parrec import (DTI_PAR_BVECS, DTI_PAR_BVALS,
3031
EXAMPLE_IMAGES as PARREC_EXAMPLES)
3132
from .test_parrec_data import BALLS, AFF_OFF
@@ -53,16 +54,69 @@ def script_test(func):
5354
DATA_PATH = abspath(pjoin(dirname(__file__), 'data'))
5455

5556

56-
@script_test
57-
def test_nib_ls():
57+
def check_nib_ls_example4d(opts=[], hdrs_str=""):
5858
# test nib-ls script
5959
fname = pjoin(DATA_PATH, 'example4d.nii.gz')
6060
expected_re = (" (int16|[<>]i2) \[128, 96, 24, 2\] "
61-
"2.00x2.00x2.20x2000.00 #exts: 2 sform$")
62-
cmd = ['nib-ls', fname]
61+
"2.00x2.00x2.20x2000.00 #exts: 2%s sform$"
62+
% hdrs_str)
63+
cmd = ['nib-ls'] + opts + [fname]
6364
code, stdout, stderr = run_command(cmd)
6465
assert_equal(fname, stdout[:len(fname)])
65-
assert_not_equal(re.match(expected_re, stdout[len(fname):]), None)
66+
assert_re_in(expected_re, stdout[len(fname):])
67+
68+
@script_test
69+
def test_nib_ls():
70+
yield check_nib_ls_example4d
71+
yield check_nib_ls_example4d, \
72+
['-H', 'dim,bitpix'], " \[ 4 128 96 24 2 1 1 1\] 16"
73+
74+
@script_test
75+
def test_nib_ls_multiple():
76+
# verify that correctly lists/formats for multiple files
77+
fnames = [
78+
pjoin(DATA_PATH, f)
79+
for f in ('example4d.nii.gz', 'example_nifti2.nii.gz',
80+
'small.mnc', 'nifti2.hdr')
81+
]
82+
code, stdout, stderr = run_command(['nib-ls'] + fnames)
83+
stdout_lines = stdout.split('\n')
84+
assert_equal(len(stdout_lines), 4)
85+
try:
86+
load(pjoin(DATA_PATH, 'small.mnc'))
87+
except:
88+
raise SkipTest("For the other tests should be able to load MINC files")
89+
90+
# they should be indented correctly. Since all files are int type -
91+
ln = max(len(f) for f in fnames)
92+
assert_equal([l[ln:ln+2] for l in stdout_lines], [' i']*4,
93+
msg="Type sub-string didn't start with 'i'. "
94+
"Full output was: %s" % stdout_lines)
95+
# and if disregard type indicator which might vary
96+
assert_equal(
97+
[l[l.index('['):] for l in stdout_lines],
98+
[
99+
'[128, 96, 24, 2] 2.00x2.00x2.20x2000.00 #exts: 2 sform',
100+
'[ 32, 20, 12, 2] 2.00x2.00x2.20x2000.00 #exts: 2 sform',
101+
'[ 18, 28, 29] 9.00x8.00x7.00',
102+
'[ 91, 109, 91] 2.00x2.00x2.00'
103+
]
104+
)
105+
106+
# Now run with -s for stats
107+
code, stdout, stderr = run_command(['nib-ls', '-s'] + fnames)
108+
stdout_lines = stdout.split('\n')
109+
assert_equal(len(stdout_lines), 4)
110+
assert_equal(
111+
[l[l.index('['):] for l in stdout_lines],
112+
[
113+
'[128, 96, 24, 2] 2.00x2.00x2.20x2000.00 #exts: 2 sform [229725] 2:1.2e+03',
114+
'[ 32, 20, 12, 2] 2.00x2.00x2.20x2000.00 #exts: 2 sform [15360] 46:7.6e+02',
115+
'[ 18, 28, 29] 9.00x8.00x7.00 [14616] 0.12:93',
116+
'[ 91, 109, 91] 2.00x2.00x2.00 error'
117+
]
118+
)
119+
66120

67121

68122
@script_test

nibabel/tests/test_testing.py

+22-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from nose.tools import assert_raises
1212
from ..testing import (error_warnings, suppress_warnings,
1313
clear_and_catch_warnings, assert_allclose_safely,
14-
get_fresh_mod)
14+
get_fresh_mod, assert_re_in)
1515

1616

1717
def assert_warn_len_equal(mod, n_in_context):
@@ -145,3 +145,24 @@ def f():
145145
with suppress_warnings():
146146
raise ValueError('An error')
147147
assert_raises(ValueError, f)
148+
149+
150+
def test_assert_re_in():
151+
assert_re_in(".*", "")
152+
assert_re_in(".*", ["any"])
153+
154+
# Should do match not search
155+
assert_re_in("ab", "abc")
156+
assert_raises(AssertionError, assert_re_in, "ab", "cab")
157+
assert_raises(AssertionError, assert_re_in, "ab$", "abc")
158+
159+
# Sufficient to have one entry matching
160+
assert_re_in("ab", ["", "abc", "laskdjf"])
161+
assert_raises(AssertionError, assert_re_in, "ab$", ["ddd", ""])
162+
163+
# Tuples should be ok too
164+
assert_re_in("ab", ("", "abc", "laskdjf"))
165+
assert_raises(AssertionError, assert_re_in, "ab$", ("ddd", ""))
166+
167+
# Shouldn't "match" the empty list
168+
assert_raises(AssertionError, assert_re_in, "", [])

0 commit comments

Comments
 (0)