Skip to content

Commit f329d5e

Browse files
committed
resolved conflict
2 parents 48957bf + d41fa81 commit f329d5e

File tree

11 files changed

+465
-155
lines changed

11 files changed

+465
-155
lines changed

nipype/algorithms/misc.py

Lines changed: 266 additions & 57 deletions
Large diffs are not rendered by default.

nipype/interfaces/fsl/preprocess.py

Lines changed: 102 additions & 94 deletions
Large diffs are not rendered by default.

nipype/interfaces/io.py

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -562,8 +562,12 @@ class SelectFilesInputSpec(DynamicTraitedSpec, BaseInterfaceInputSpec):
562562
desc="When matching mutliple files, return them in sorted order.")
563563
raise_on_empty = traits.Bool(True, usedefault=True,
564564
desc="Raise an exception if a template pattern matches no files.")
565-
force_lists = traits.Bool(False, usedefault=True,
566-
desc="Return all values as lists even when matching a single file.")
565+
force_lists = traits.Either(traits.Bool(), traits.List(traits.Str()),
566+
default=False, usedefault=True,
567+
desc=("Whether to return outputs as a list even when only one file "
568+
"matches the template. Either a boolean that applies to all "
569+
"output fields or a list of output field names to coerce to "
570+
" a list"))
567571

568572

569573
class SelectFiles(IOBase):
@@ -646,6 +650,18 @@ def _list_outputs(self):
646650
info = dict([(k, v) for k, v in self.inputs.__dict__.items()
647651
if k in self._infields])
648652

653+
force_lists = self.inputs.force_lists
654+
if isinstance(force_lists, bool):
655+
force_lists = self._outfields if force_lists else []
656+
bad_fields = set(force_lists) - set(self._outfields)
657+
if bad_fields:
658+
bad_fields = ", ".join(list(bad_fields))
659+
plural = "s" if len(bad_fields) > 1 else ""
660+
verb = "were" if len(bad_fields) > 1 else "was"
661+
msg = ("The field%s '%s' %s set in 'force_lists' and not in "
662+
"'templates'.") % (plural, bad_fields, verb)
663+
raise ValueError(msg)
664+
649665
for field, template in self._templates.iteritems():
650666

651667
# Build the full template path
@@ -673,7 +689,7 @@ def _list_outputs(self):
673689
filelist.sort()
674690

675691
# Handle whether this must be a list or not
676-
if not self.inputs.force_lists:
692+
if field not in force_lists:
677693
filelist = list_to_filename(filelist)
678694

679695
outputs[field] = filelist

nipype/interfaces/nipy/model.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
warnings.warn('nipy not installed')
2121
else:
2222
import nipy.modalities.fmri.design_matrix as dm
23-
import nipy.labs.glm as GLM
23+
import nipy.labs.glm.glm as GLM
2424

2525
if have_nipy:
2626
try:

nipype/interfaces/tests/test_io.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import os.path as op
77
from tempfile import mkstemp, mkdtemp
88

9+
from nose.tools import assert_raises
910
import nipype
1011
from nipype.testing import assert_equal, assert_true, assert_false
1112
import nipype.interfaces.io as nio
@@ -43,6 +44,16 @@ def test_selectfiles():
4344
"interfaces/spm/preprocess.py")
4445
yield assert_equal, res.outputs.preprocess, [wanted]
4546

47+
dg.inputs.package = "fsl"
48+
dg.inputs.force_lists = ["model"]
49+
res = dg.run()
50+
preproc = op.join(op.dirname(nipype.__file__),
51+
"interfaces/fsl/preprocess.py")
52+
model = [op.join(op.dirname(nipype.__file__),
53+
"interfaces/fsl/model.py")]
54+
yield assert_equal, res.outputs.preprocess, preproc
55+
yield assert_equal, res.outputs.model, model
56+
4657
templates = {"converter": "interfaces/dcm{to!s}nii.py"}
4758
dg = nio.SelectFiles(templates, base_directory=base_dir)
4859
dg.inputs.to = 2
@@ -51,6 +62,17 @@ def test_selectfiles():
5162
yield assert_equal, res.outputs.converter, wanted
5263

5364

65+
def test_selectfiles_valueerror():
66+
"""Test ValueError when force_lists has field that isn't in template."""
67+
base_dir = op.dirname(nipype.__file__)
68+
templates = {"model": "interfaces/{package}/model.py",
69+
"preprocess": "interfaces/{package}/pre*.py"}
70+
force_lists = ["model", "preprocess", "registration"]
71+
sf = nio.SelectFiles(templates, base_directory=base_dir,
72+
force_lists=force_lists)
73+
yield assert_raises, ValueError, sf.run
74+
75+
5476
def test_datagrabber_order():
5577
tempdir = mkdtemp()
5678
file1 = mkstemp(prefix='sub002_L1_R1.q', dir=tempdir)

nipype/pipeline/engine.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1209,6 +1209,11 @@ def hash_exists(self, updatehash=False):
12091209
# of the dictionary itself.
12101210
hashed_inputs, hashvalue = self._get_hashval()
12111211
outdir = self.output_dir()
1212+
hashfiles = glob(os.path.join(outdir, '_0x*.json'))
1213+
if len(hashfiles) > 1:
1214+
warn('Removing multiple hashfiles and forcing node to rerun')
1215+
for hashfile in hashfiles:
1216+
os.unlink(hashfile)
12121217
hashfile = os.path.join(outdir, '_0x%s.json' % hashvalue)
12131218
if updatehash and os.path.exists(outdir):
12141219
logger.debug("Updating hash: %s" % hashvalue)
@@ -1302,6 +1307,10 @@ def run(self, updatehash=False):
13021307
logger.debug(("%s found and can_resume is True or Node is a "
13031308
"MapNode - resuming execution") %
13041309
hashfile_unfinished)
1310+
if isinstance(self, MapNode):
1311+
# remove old json files
1312+
for filename in glob(os.path.join(outdir, '_0x*.json')):
1313+
os.unlink(filename)
13051314
outdir = make_output_dir(outdir)
13061315
self._save_hashfile(hashfile_unfinished, hashed_inputs)
13071316
self.write_report(report_type='preexec', cwd=outdir)

nipype/pipeline/tests/test_engine.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"""Tests for the engine module
44
"""
55
from copy import deepcopy
6+
from glob import glob
67
import os
78
from shutil import rmtree
89
from tempfile import mkdtemp
@@ -13,6 +14,7 @@
1314
assert_false)
1415
import nipype.interfaces.base as nib
1516
import nipype.pipeline.engine as pe
17+
from nipype import logging
1618

1719
class InputSpec(nib.TraitedSpec):
1820
input1 = nib.traits.Int(desc='a random int')
@@ -439,3 +441,47 @@ def func2(a):
439441
yield assert_false, error_raised
440442
os.chdir(cwd)
441443
rmtree(wd)
444+
445+
446+
def test_mapnode_json():
447+
"""Tests that mapnodes don't generate excess jsons
448+
"""
449+
cwd = os.getcwd()
450+
wd = mkdtemp()
451+
os.chdir(wd)
452+
from nipype import MapNode, Function, Workflow
453+
def func1(in1):
454+
return in1 + 1
455+
n1 = MapNode(Function(input_names=['in1'],
456+
output_names=['out'],
457+
function=func1),
458+
iterfield=['in1'],
459+
name='n1')
460+
n1.inputs.in1 = [1]
461+
w1 = Workflow(name='test')
462+
w1.base_dir = wd
463+
w1.config = {'crashdump_dir': wd}
464+
w1.add_nodes([n1])
465+
w1.run()
466+
n1.inputs.in1 = [2]
467+
w1.run()
468+
# should rerun
469+
n1.inputs.in1 = [1]
470+
eg = w1.run()
471+
472+
node = eg.nodes()[0]
473+
outjson = glob(os.path.join(node.output_dir(), '_0x*.json'))
474+
yield assert_equal, len(outjson), 1
475+
476+
# check that multiple json's don't trigger rerun
477+
with open(os.path.join(node.output_dir(), 'test.json'), 'wt') as fp:
478+
fp.write('dummy file')
479+
w1.config['execution'].update(**{'stop_on_first_rerun': True})
480+
error_raised = False
481+
try:
482+
w1.run()
483+
except:
484+
error_raised = True
485+
yield assert_false, error_raised
486+
os.chdir(cwd)
487+
rmtree(wd)

nipype/testing/data/ref_class0.nii

Whitespace-only changes.

nipype/testing/data/ref_class1.nii

Whitespace-only changes.

nipype/testing/data/tst_class0.nii

Whitespace-only changes.

0 commit comments

Comments
 (0)