Skip to content

Commit 7a3317d

Browse files
authored
Merge pull request #1623 from oesteban/fix/FromFileWorkflows
[FIX] Bugs found after #1572 and #1591
2 parents a746633 + e970941 commit 7a3317d

File tree

6 files changed

+118
-54
lines changed

6 files changed

+118
-54
lines changed

examples/smri_ants_registration.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import urllib.error
2525
import urllib.parse
2626
from nipype.interfaces.ants import Registration
27+
from nipype.testing import example_data
2728

2829
"""
2930
2. Download T1 volumes into home directory
@@ -61,11 +62,12 @@
6162

6263
"""
6364
3. Define the parameters of the registration. Settings are
64-
saved in ``smri_ants_registration_settings.json``.
65+
found in the file ``smri_ants_registration_settings.json``
66+
distributed with the ``example_data`` of `nipype`.
6567
6668
"""
6769

68-
reg = Registration(from_file='./smri_ants_registration_settings.json')
70+
reg = Registration(from_file=example_data('smri_ants_registration_settings.json'))
6971
reg.inputs.fixed_image = input_images[0]
7072
reg.inputs.moving_image = input_images[1]
7173

nipype/interfaces/base.py

Lines changed: 41 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
nipype_version = LooseVersion(__version__)
4848
iflogger = logging.getLogger('interface')
4949

50+
FLOAT_FORMAT = '{:.10f}'.format
5051
PY35 = sys.version_info >= (3, 5)
5152
PY3 = sys.version_info[0] > 2
5253

@@ -536,6 +537,14 @@ def _clean_container(self, object, undefinedval=None, skipundefined=False):
536537
out = undefinedval
537538
return out
538539

540+
def has_metadata(self, name, metadata, value=None, recursive=True):
541+
"""
542+
Return has_metadata for the requested trait name in this
543+
interface
544+
"""
545+
return has_metadata(self.trait(name).trait_type, metadata, value,
546+
recursive)
547+
539548
def get_hashval(self, hash_method=None):
540549
"""Return a dictionary of our items with hashes for each file.
541550
@@ -560,61 +569,61 @@ def get_hashval(self, hash_method=None):
560569
dict_withhash = []
561570
dict_nofilename = []
562571
for name, val in sorted(self.get().items()):
563-
if isdefined(val):
564-
trait = self.trait(name)
565-
if has_metadata(trait.trait_type, "nohash", True):
566-
continue
567-
hash_files = (not has_metadata(trait.trait_type, "hash_files",
568-
False) and not
569-
has_metadata(trait.trait_type, "name_source"))
570-
dict_nofilename.append((name,
571-
self._get_sorteddict(val, hash_method=hash_method,
572-
hash_files=hash_files)))
573-
dict_withhash.append((name,
574-
self._get_sorteddict(val, True, hash_method=hash_method,
575-
hash_files=hash_files)))
572+
if not isdefined(val) or self.has_metadata(name, "nohash", True):
573+
# skip undefined traits and traits with nohash=True
574+
continue
575+
576+
hash_files = (not self.has_metadata(name, "hash_files", False) and not
577+
self.has_metadata(name, "name_source"))
578+
dict_nofilename.append((name,
579+
self._get_sorteddict(val, hash_method=hash_method,
580+
hash_files=hash_files)))
581+
dict_withhash.append((name,
582+
self._get_sorteddict(val, True, hash_method=hash_method,
583+
hash_files=hash_files)))
576584
return dict_withhash, md5(encode_dict(dict_nofilename).encode()).hexdigest()
577585

578-
def _get_sorteddict(self, object, dictwithhash=False, hash_method=None,
586+
587+
def _get_sorteddict(self, objekt, dictwithhash=False, hash_method=None,
579588
hash_files=True):
580-
if isinstance(object, dict):
589+
if isinstance(objekt, dict):
581590
out = []
582-
for key, val in sorted(object.items()):
591+
for key, val in sorted(objekt.items()):
583592
if isdefined(val):
584593
out.append((key,
585594
self._get_sorteddict(val, dictwithhash,
586595
hash_method=hash_method,
587596
hash_files=hash_files)))
588-
elif isinstance(object, (list, tuple)):
597+
elif isinstance(objekt, (list, tuple)):
589598
out = []
590-
for val in object:
599+
for val in objekt:
591600
if isdefined(val):
592601
out.append(self._get_sorteddict(val, dictwithhash,
593602
hash_method=hash_method,
594603
hash_files=hash_files))
595-
if isinstance(object, tuple):
604+
if isinstance(objekt, tuple):
596605
out = tuple(out)
597606
else:
598-
if isdefined(object):
599-
if (hash_files and isinstance(object, (str, bytes)) and
600-
os.path.isfile(object)):
607+
if isdefined(objekt):
608+
if (hash_files and isinstance(objekt, (str, bytes)) and
609+
os.path.isfile(objekt)):
601610
if hash_method is None:
602611
hash_method = config.get('execution', 'hash_method')
603612

604613
if hash_method.lower() == 'timestamp':
605-
hash = hash_timestamp(object)
614+
hash = hash_timestamp(objekt)
606615
elif hash_method.lower() == 'content':
607-
hash = hash_infile(object)
616+
hash = hash_infile(objekt)
608617
else:
609618
raise Exception("Unknown hash method: %s" % hash_method)
610619
if dictwithhash:
611-
out = (object, hash)
620+
out = (objekt, hash)
612621
else:
613622
out = hash
614-
elif isinstance(object, float):
615-
out = '%.10f' % object
623+
elif isinstance(objekt, float):
624+
out = FLOAT_FORMAT(objekt)
616625
else:
617-
out = object
626+
out = objekt
618627
return out
619628

620629

@@ -769,7 +778,10 @@ def __init__(self, from_file=None, **inputs):
769778
self.num_threads = 1
770779

771780
if from_file is not None:
772-
self.load_inputs_from_json(from_file, overwrite=False)
781+
self.load_inputs_from_json(from_file, overwrite=True)
782+
783+
for name, value in list(inputs.items()):
784+
setattr(self.inputs, name, value)
773785

774786

775787
@classmethod

nipype/interfaces/tests/test_base.py

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,11 @@
1010
import tempfile
1111
import shutil
1212
import warnings
13+
import simplejson as json
1314

1415
from nipype.testing import (assert_equal, assert_not_equal, assert_raises,
1516
assert_true, assert_false, with_setup, package_check,
16-
skipif)
17+
skipif, example_data)
1718
import nipype.interfaces.base as nib
1819
from nipype.utils.filemanip import split_filename
1920
from nipype.interfaces.base import Undefined, config
@@ -497,10 +498,21 @@ def __init__(self, **inputs):
497498
bif6.load_inputs_from_json(tmp_json)
498499
yield assert_equal, bif6.inputs.get_traitsfree(), inputs_dict
499500

500-
def assert_not_raises(fn, *args, **kwargs):
501-
fn(*args, **kwargs)
502-
return True
501+
# test get hashval in a complex interface
502+
from nipype.interfaces.ants import Registration
503+
settings = example_data(example_data('smri_ants_registration_settings.json'))
504+
with open(settings) as setf:
505+
data_dict = json.load(setf)
506+
507+
tsthash = Registration()
508+
tsthash.load_inputs_from_json(settings)
509+
yield assert_equal, {}, check_dict(data_dict, tsthash.inputs.get_traitsfree())
503510

511+
tsthash2 = Registration(from_file=settings)
512+
yield assert_equal, {}, check_dict(data_dict, tsthash2.inputs.get_traitsfree())
513+
514+
_, hashvalue = tsthash.inputs.get_hashval(hash_method='timestamp')
515+
yield assert_equal, 'ec5755e07287e04a4b409e03b77a517c', hashvalue
504516

505517
def test_input_version():
506518
class InputSpec(nib.TraitedSpec):
@@ -738,3 +750,27 @@ def test_global_CommandLine_output():
738750
yield assert_equal, res.runtime.stdout, ''
739751
os.chdir(pwd)
740752
teardown_file(tmpd)
753+
754+
def assert_not_raises(fn, *args, **kwargs):
755+
fn(*args, **kwargs)
756+
return True
757+
758+
def check_dict(ref_dict, tst_dict):
759+
"""Compare dictionaries of inputs and and those loaded from json files"""
760+
def to_list(x):
761+
if isinstance(x, tuple):
762+
x = list(x)
763+
764+
if isinstance(x, list):
765+
for i, xel in enumerate(x):
766+
x[i] = to_list(xel)
767+
768+
return x
769+
770+
failed_dict = {}
771+
for key, value in list(ref_dict.items()):
772+
newval = to_list(tst_dict[key])
773+
if newval != value:
774+
failed_dict[key] = (value, newval)
775+
return failed_dict
776+

nipype/utils/filemanip.py

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -89,24 +89,38 @@ def encode_dict(value):
8989
9090
"""
9191
if sys.version_info[0] > 2:
92-
return str(value)
93-
94-
if isinstance(value, str):
95-
value = value.encode()
92+
retval = str(value)
93+
else:
94+
retval = encode_dict_py27(value)
95+
return retval
9696

97-
if isinstance(value, tuple):
98-
val0 = encode_dict(value[0])
99-
val1 = encode_dict(value[1])
100-
return '(' + val0 + ', ' + val1 + ')'
97+
def encode_dict_py27(value):
98+
"""
99+
Encode dictionary for python 2
100+
"""
101101

102-
if isinstance(value, list):
103-
retval = '['
102+
istuple = isinstance(value, tuple)
103+
if isinstance(value, (tuple, list)):
104+
retval = '(' if istuple else '['
105+
nels = len(value)
104106
for i, v in enumerate(value):
105-
if i > 0:
107+
venc = encode_dict_py27(v)
108+
if venc.startswith("u'") or venc.startswith('u"'):
109+
venc = venc[1:]
110+
retval += venc
111+
112+
if i < nels - 1:
106113
retval += ', '
107-
retval += encode_dict(v)
108-
return retval + ']'
109-
return repr(value)
114+
115+
if istuple and nels == 1:
116+
retval += ','
117+
retval += ')' if istuple else ']'
118+
return retval
119+
120+
retval = repr(value).decode()
121+
if retval.startswith("u'") or retval.startswith('u"'):
122+
retval = retval[1:]
123+
return retval
110124

111125
def fname_presuffix(fname, prefix='', suffix='', newpath=None, use_ext=True):
112126
"""Manipulates path and name of input filename

nipype/utils/tests/test_filemanip.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@
1010

1111
from ...testing import assert_equal, assert_true, assert_false, TempFATFS
1212
from ...utils.filemanip import (save_json, load_json,
13-
fname_presuffix, fnames_presuffix,
14-
hash_rename, check_forhash,
15-
copyfile, copyfiles,
16-
filename_to_list, list_to_filename,
17-
split_filename, get_related_files)
13+
fname_presuffix, fnames_presuffix,
14+
hash_rename, check_forhash,
15+
copyfile, copyfiles,
16+
filename_to_list, list_to_filename,
17+
split_filename, get_related_files)
1818

1919
import numpy as np
2020

0 commit comments

Comments
 (0)