Repository: nipype/pydra

Issue:
error returning numpy arrays with more than one element in workflow output
version: pydra master

the key piece appears to be the fact that a numpy array is being returned with more than 1 element. i.e the error goes away if the output of the function is changed to `np.array([val])` or `np.array([val, val]).tolist()` 

i think this is the same error that @nicolocin ran into.

<details> <summary> error </summary>

```shell
$ python multiout.py 
Traceback (most recent call last):
  File "multiout.py", line 24, in <module>
    sub(runnable=wf)
  File "/Users/satra/software/nipy-repo/pydra/pydra/engine/submitter.py", line 57, in __call__
    self.loop.run_until_complete(self.submit_workflow(runnable, rerun=rerun))
  File "/Users/satra/software/miniconda3/envs/mee-voice/lib/python3.8/asyncio/base_events.py", line 612, in run_until_complete
    return future.result()
  File "/Users/satra/software/nipy-repo/pydra/pydra/engine/submitter.py", line 71, in submit_workflow
    await workflow._run(self, rerun=rerun)
  File "/Users/satra/software/nipy-repo/pydra/pydra/engine/core.py", line 869, in _run
    save(odir, result=result, task=self)
  File "/Users/satra/software/nipy-repo/pydra/pydra/engine/helpers.py", line 117, in save
    result = copyfile_workflow(wf_path=task_path, result=result)
  File "/Users/satra/software/nipy-repo/pydra/pydra/engine/helpers.py", line 129, in copyfile_workflow
    new_value = _copyfile_single_value(wf_path=wf_path, value=value)
  File "/Users/satra/software/nipy-repo/pydra/pydra/engine/helpers.py", line 138, in _copyfile_single_value
    return [_copyfile_single_value(wf_path, val) for val in value]
  File "/Users/satra/software/nipy-repo/pydra/pydra/engine/helpers.py", line 138, in <listcomp>
    return [_copyfile_single_value(wf_path, val) for val in value]
  File "/Users/satra/software/nipy-repo/pydra/pydra/engine/helpers.py", line 143, in _copyfile_single_value
    elif is_existing_file(value):
  File "/Users/satra/software/nipy-repo/pydra/pydra/engine/helpers_file.py", line 540, in is_existing_file
    if not f:
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
```
</details>

To replicate run this code
<details> <summary> code </summary>

```python
import numpy as np
import pydra
import typing as ty
import os

@pydra.mark.task
@pydra.mark.annotate({"return": {"b": ty.Any}})
def test_multiout(val):
    return np.array([val, val])

if __name__ == "__main__":
    cache_dir = os.path.join(os.getcwd(), 'cache3')
    wf = pydra.Workflow("", input_spec=['val'], val=[0, 1, 2],
                        cache_dir=cache_dir)
    wf.add(test_multiout(name="mo",
                         val=wf.lzin.val,
                         cache_dir=cache_dir))
    wf.mo.split('val').combine('val')
    wf.set_output([("b", wf.mo.lzout.b)])

    with pydra.Submitter(plugin="cf", n_procs=2) as sub:
        sub(runnable=wf)
    results = wf.result(return_inputs=True)
```
</details>

Discussion:

Patch:
diff --git a/pydra/engine/helpers_file.py b/pydra/engine/helpers_file.py
index f15e2028..39f38785 100644
--- a/pydra/engine/helpers_file.py
+++ b/pydra/engine/helpers_file.py
@@ -535,11 +535,11 @@ def is_local_file(f):
     return f.type is File and "container_path" not in f.metadata
 
 
-def is_existing_file(f):
+def is_existing_file(value):
     """ checking if an object is an existing file"""
-    if not f:
+    if value == "":
         return False
     try:
-        return Path(f).exists()
+        return Path(value).exists()
     except TypeError:
         return False


Test patch:
diff --git a/pydra/engine/tests/test_numpy_examples.py b/pydra/engine/tests/test_numpy_examples.py
new file mode 100644
index 00000000..55884ac2
--- /dev/null
+++ b/pydra/engine/tests/test_numpy_examples.py
@@ -0,0 +1,35 @@
+import numpy as np
+import typing as ty
+import importlib
+import pytest
+
+from ..submitter import Submitter
+from ..core import Workflow
+from ...mark import task, annotate
+
+if importlib.util.find_spec("numpy") is None:
+    pytest.skip("can't find numpy library", allow_module_level=True)
+
+
+@task
+@annotate({"return": {"b": ty.Any}})
+def arrayout(val):
+    return np.array([val, val])
+
+
+def test_multiout(plugin):
+    """ testing a simple function that returns a numpy array"""
+    wf = Workflow("wf", input_spec=["val"], val=[0, 1, 2])
+    wf.add(arrayout(name="mo", val=wf.lzin.val))
+    wf.mo.split("val").combine("val")
+
+    wf.set_output([("array", wf.mo.lzout.b)])
+
+    with Submitter(plugin=plugin, n_procs=2) as sub:
+        sub(runnable=wf)
+
+    results = wf.result(return_inputs=True)
+
+    assert results[0] == {"wf.val": [0, 1, 2]}
+    for el in range(3):
+        assert np.array_equal(results[1].output.array[el], np.array([el, el]))