Skip to content

Commit f1cee5f

Browse files
committed
RF+BF: report that diff if any header of data differs, return dict of diffs
Also just include data difference into the same diff structure as DATA(md5)
1 parent 41caade commit f1cee5f

File tree

3 files changed

+72
-117
lines changed

3 files changed

+72
-117
lines changed

nibabel/cmdline/diff.py

Lines changed: 35 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@
1212
"""
1313
from __future__ import division, print_function, absolute_import
1414

15+
import re
1516
import sys
17+
from collections import OrderedDict
1618
from optparse import OptionParser, Option
1719

1820
import numpy as np
@@ -101,17 +103,22 @@ def diff_header_fields(key, inputs):
101103

102104

103105
def get_headers_diff(files, opts):
104-
"""
105-
Getting the difference of headers.
106-
Returns a dictionary that is later processed.
107-
108-
Parameters
109-
----------
110-
files: list of files
111-
opts: any options included from the command line
106+
"""Get difference between headers
107+
108+
Parameters
109+
----------
110+
files: list of files
111+
opts: any options included from the command line
112+
113+
Returns
114+
-------
115+
dict
116+
str: list for each header field which differs, return list of
117+
values per each file
112118
"""
113119

114120
header_list = [nib.load(f).header for f in files]
121+
output = OrderedDict()
115122

116123
if opts.header_fields: # will almost always have a header field
117124
# signals "all fields"
@@ -121,18 +128,13 @@ def get_headers_diff(files, opts):
121128
else:
122129
header_fields = opts.header_fields.split(',')
123130

124-
output = []
125-
126131
for f in header_fields:
127132
val = diff_header_fields(f, header_list)
128133

129134
if val:
130-
loader = {f: val}
131-
output.append(loader)
135+
output[f] = val
132136

133-
return output
134-
else:
135-
return []
137+
return output
136138

137139

138140
def get_data_md5sums(files):
@@ -162,10 +164,13 @@ def main():
162164
# suppress nibabel format-compliance warnings
163165
nib.imageglobals.logger.level = 50
164166

165-
header_diff = get_headers_diff(files, opts)
167+
diff = get_headers_diff(files, opts)
166168
data_diff = get_data_md5sums(files)
169+
if data_diff:
170+
diff['DATA(md5)'] = data_diff
167171

168-
if len(data_diff) != 0 and len(header_diff) != 0:
172+
if diff:
173+
print("These files are different.")
169174
print("{:<11}".format('Field'), end="")
170175

171176
for f in files:
@@ -182,23 +187,22 @@ def main():
182187

183188
print()
184189

185-
for x in header_diff:
186-
for key, value in x.items():
187-
print("{:<11}".format(key), end="")
190+
for key, value in diff.items():
191+
print("{:<11}".format(key), end="")
188192

189-
for item in value:
190-
print("{:<45}".format(str(item)), end="")
193+
for item in value:
194+
item_str = str(item)
195+
# Value might start/end with some invisible spacing characters so we
196+
# would "condition" it on both ends a bit
197+
item_str = re.sub('^[ \t]+', '<', item_str)
198+
item_str = re.sub('[ \t]+$', '>', item_str)
199+
# and also replace some other invisible symbols with a question
200+
# mark
201+
item_str = re.sub('[\x00]', '?', item_str)
202+
print("{:<45}".format(item_str), end="")
191203

192204
print()
193205

194-
print("DATA: ", end="")
195-
196-
if len(data_diff) != 0:
197-
print("These files are different.")
198-
print("{:<11}".format("Checksum"), end="")
199-
for i in data_diff:
200-
print("{:45}".format(i[0:8]), end="")
201-
print()
202206
raise SystemExit(1)
203207
else:
204-
print("These files are identical!")
208+
print("These files are identical.")

nibabel/tests/test_diff.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*-
22
# vi: set ft=python sts=4 ts=4 sw=4 et:
3-
""" Test scripts
4-
5-
Test running scripts
3+
""" Test diff
64
"""
75
from __future__ import division, print_function, absolute_import
86

@@ -16,7 +14,9 @@
1614

1715
from nibabel.cmdline.diff import diff_values
1816

19-
# TODO: MAJOR TO DO IS TO FIGURE OUT HOW TO USE HYPOTHESIS FOR LONGER LIST LENGTHS WHILE STILL CONTROLLING FOR OUTCOMES
17+
# TODO: MAJOR TO DO IS TO FIGURE OUT HOW TO USE HYPOTHESIS FOR LONGER LIST
18+
# LENGTHS WHILE STILL CONTROLLING FOR OUTCOMES
19+
2020

2121
@given(st.data())
2222
def test_diff_values_int(data):
@@ -33,8 +33,8 @@ def test_diff_values_int(data):
3333
@given(st.data())
3434
def test_diff_values_float(data):
3535
x = data.draw(st.just(0), label='x')
36-
y = data.draw(st.floats(min_value = 1e8), label='y')
37-
z = data.draw(st.floats(max_value = -1e8), label='z')
36+
y = data.draw(st.floats(min_value=1e8), label='y')
37+
z = data.draw(st.floats(max_value=-1e8), label='z')
3838

3939
assert not diff_values(x, x)
4040
assert diff_values(x, y)

nibabel/tests/test_scripts.py

Lines changed: 31 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -73,91 +73,42 @@ def check_nib_diff_examples(opts=[], hdrs_str="", other_str=""):
7373
# test nib-diff script
7474
fnames = [pjoin(DATA_PATH, f)
7575
for f in ('example4d.nii.gz', 'standard.nii.gz')]
76+
target_output = """\
77+
These files are different.
78+
Field example4d.nii.gz standard.nii.gz
79+
regular r
80+
dim_info 57 0
81+
dim [4, 128, 96, 24, 2, 1, 1, 1] [3, 4, 5, 7, 1, 1, 1, 1]
82+
datatype 4 2
83+
bitpix 16 8
84+
pixdim [-1.0, 2.0, 2.0, 2.199999, 2000.0, 1.0, 1.0, 1.0][1.0, 1.0, 3.0, 2.0, 1.0, 1.0, 1.0, 1.0]
85+
slice_end 23 0
86+
xyzt_units 10 0
87+
cal_max 1162.0 0.0
88+
descrip FSL3.3? v2.25 NIfTI-1 Single file format
89+
qform_code 1 0
90+
sform_code 1 2
91+
quatern_b -1.94510681403e-26 0.0
92+
quatern_c -0.996708512306 0.0
93+
quatern_d -0.081068739295 0.0
94+
qoffset_x 117.855102539 0.0
95+
qoffset_y -35.7229423523 0.0
96+
qoffset_z -7.24879837036 0.0
97+
srow_x [-2.0, 6.7147157e-19, 9.0810245e-18, 117.8551][1.0, 0.0, 0.0, 0.0]
98+
srow_y [-6.7147157e-19, 1.9737115, -0.35552824, -35.722942][0.0, 3.0, 0.0, 0.0]
99+
srow_z [8.255481e-18, 0.32320762, 2.1710818, -7.2487984][0.0, 0.0, 2.0, 0.0]
100+
DATA(md5) b0abbc492b4fd533b2c80d82570062cf 0a2576dd6badbb25bfb3b12076df986b"""
76101
fnames2 = [pjoin(DATA_PATH, f)
77102
for f in ('example4d.nii.gz', 'example4d.nii.gz')]
78103
code, stdout, stderr = run_command(['nib-diff'] + fnames, check_code=False)
79-
hi = difflib.context_diff(stdout, "Field " + "{:<45}".format("example4d.nii.gz") + "{:<45}".format("standard.nii.gz")
80-
+ "\n" + "regular b'r' b'' "
81-
" " + "\n" + "dim_info 57 "
82-
" 0 "
83-
" "
84-
" " + "\n"
85-
"dim [4, 128, 96, 24, 2, 1, 1, 1] [3, 4, 5, 7, 1, 1, 1, 1] "
86-
+ "\n" + "datatype 4 2 "
87-
" " + "\n" + "bitpix 16 8 "
88-
" " + "\n" + "pixdim [-1.0, 2.0, 2.0, "
89-
"2.1999991, 2000.0, 1.0, 1.0,"
90-
" 1.0][1.0, 1.0, 3.0, 2.0, "
91-
"1.0, 1.0, 1.0, 1.0] " +
92-
"\n" + "slice_end 23 0 "
93-
" " + "\n" + "xyzt_units 10 0 "
94-
" " + "\n" + "cal_max 1162.0 "
95-
" 0.0 "
96-
" " + "\n" +
97-
"descrip b'FSL3.3\\x00 v2.25 NIfTI-1 Single file format'b'' "
98-
" \n" + "qform_code 1 0 "
99-
" " + "\n" + "sform_code 1 2 "
100-
" \n" +"quatern_b -1.9451068140294884e-26 "
101-
" 0.0 "
102-
" " + "\n" +
103-
"quatern_c -0.9967085123062134 0.0 "
104-
+ "\n" + "quatern_d -0.0810687392950058 0.0 "
105-
" " + "\n" + "qoffset_x 117.8551025390625 0.0 "
106-
" " + "\n" + "qoffset_y -35.72294235229492"
107-
" 0."
108-
"0 "
109-
" " + "\n" +
110-
"qoffset_z -7.248798370361328 0.0 "
111-
+ "\n" + "srow_x [-2.0, 6.7147157e-19, 9.0810245e-18, 117.8551][1.0, 0.0, 0.0, 0.0] "
112-
" " + "\n" + "srow_y [-6.7147157e-19, 1.9737115, -0.35552824, -35.722942][0.0, 3"
113-
".0, 0.0, 0.0] " + "\n" +
114-
"srow_z [8.2554809e-18, 0.32320762, 2.1710818, -7.2487984][0.0, 0.0, 2.0, 0.0] "
115-
" " + "\n" + "DATA: These files are different.\nChecksum b0abbc49 "
116-
+ " 0a2576dd")
117-
delta = ''.join(hi)
118-
print(delta)
119-
assert_equal(stdout, "Field " + "{:<45}".format("example4d.nii.gz") + "{:<45}".format("standard.nii.gz")
120-
+ "\n" + "regular b'r' b'' "
121-
" " + "\n" + "dim_info 57 "
122-
" 0 "
123-
" "
124-
" " + "\n"
125-
"dim [4, 128, 96, 24, 2, 1, 1, 1] [3, 4, 5, 7, 1, 1, 1, 1] "
126-
+ "\n" + "datatype 4 2 "
127-
" " + "\n" + "bitpix 16 8 "
128-
" " + "\n" + "pixdim [-1.0, 2.0, 2.0, "
129-
"2.1999991, 2000.0, 1.0, 1.0,"
130-
" 1.0][1.0, 1.0, 3.0, 2.0, "
131-
"1.0, 1.0, 1.0, 1.0] " +
132-
"\n" + "slice_end 23 0 "
133-
" " + "\n" + "xyzt_units 10 0 "
134-
" " + "\n" + "cal_max 1162.0 "
135-
" 0.0 "
136-
" " + "\n" +
137-
"descrip b'FSL3.3\\x00 v2.25 NIfTI-1 Single file format'b'' "
138-
" \n" + "qform_code 1 0 "
139-
" " + "\n" + "sform_code 1 2 "
140-
" \n" +"quatern_b -1.9451068140294884e-26 "
141-
" 0.0 "
142-
" " + "\n" +
143-
"quatern_c -0.9967085123062134 0.0 "
144-
+ "\n" + "quatern_d -0.0810687392950058 0.0 "
145-
" " + "\n" + "qoffset_x 117.8551025390625 0.0 "
146-
" " + "\n" + "qoffset_y -35.72294235229492"
147-
" 0."
148-
"0 "
149-
" " + "\n" +
150-
"qoffset_z -7.248798370361328 0.0 "
151-
+ "\n" + "srow_x [-2.0, 6.7147157e-19, 9.0810245e-18, 117.8551][1.0, 0.0, 0.0, 0.0] "
152-
" " + "\n" + "srow_y [-6.7147157e-19, 1.9737115, -0.35552824, -35.722942][0.0, 3"
153-
".0, 0.0, 0.0] " + "\n" +
154-
"srow_z [8.2554809e-18, 0.32320762, 2.1710818, -7.2487984][0.0, 0.0, 2.0, 0.0] "
155-
" " + "\n" + "DATA: These files are different.\nChecksum b0abbc49 "
156-
+ " 0a2576dd")
104+
# n1, n2 = 2300, 2400
105+
# stdout, target_output = stdout[n1:n2], target_output[n1:n2]
106+
delta_diff = difflib.context_diff(stdout, target_output)
107+
print(''.join(delta_diff))
108+
assert_equal(stdout, target_output)
157109

158110
code, stdout, stderr = run_command(['nib-diff'] + fnames2, check_code=False)
159-
assert_equal(stdout, "DATA: These files are identical!")
160-
111+
assert_equal(stdout, "These files are identical.")
161112

162113

163114
@script_test

0 commit comments

Comments
 (0)