diff --git a/pydra/engine/core.py b/pydra/engine/core.py
index 5e3e8efe..e630588a 100644
--- a/pydra/engine/core.py
+++ b/pydra/engine/core.py
@@ -381,7 +381,7 @@ class TaskBase:
             orig_inputs = attr.asdict(self.inputs)
             map_copyfiles = copyfile_input(self.inputs, self.output_dir)
             modified_inputs = template_update(self.inputs, map_copyfiles)
-            if modified_inputs is not None:
+            if modified_inputs:
                 self.inputs = attr.evolve(self.inputs, **modified_inputs)
             self.audit.start_audit(odir)
             result = Result(output=None, runtime=None, errored=False)
diff --git a/pydra/engine/helpers_file.py b/pydra/engine/helpers_file.py
index 7c2098b1..2afac73a 100644
--- a/pydra/engine/helpers_file.py
+++ b/pydra/engine/helpers_file.py
@@ -505,7 +505,7 @@ def template_update(inputs, map_copyfiles=None):
                     f"output_file_template metadata for "
                     "{fld.name} should be a string"
                 )
-    return {k: v for k, v in dict_.items() if getattr(inputs, k) != v}
+    return {k: v for k, v in dict_.items() if getattr(inputs, k) is not v}
 
 
 def is_local_file(f):
diff --git a/pydra/engine/task.py b/pydra/engine/task.py
index 4872445a..aa7fff5a 100644
--- a/pydra/engine/task.py
+++ b/pydra/engine/task.py
@@ -176,15 +176,20 @@ class FunctionTask(TaskBase):
                     )
                 else:
                     if not isinstance(return_info, tuple):
-                        return_info = (return_info,)
-                    output_spec = SpecInfo(
-                        name="Output",
-                        fields=[
-                            ("out{}".format(n + 1), t)
-                            for n, t in enumerate(return_info)
-                        ],
-                        bases=(BaseSpec,),
-                    )
+                        output_spec = SpecInfo(
+                            name="Output",
+                            fields=[("out", return_info)],
+                            bases=(BaseSpec,),
+                        )
+                    else:
+                        output_spec = SpecInfo(
+                            name="Output",
+                            fields=[
+                                ("out{}".format(n + 1), t)
+                                for n, t in enumerate(return_info)
+                            ],
+                            bases=(BaseSpec,),
+                        )
         elif "return" in func.__annotations__:
             raise NotImplementedError("Branch not implemented")
         self.output_spec = output_spec

template_update does not take type of value into account
the `template_update` function cannot simply check for equality of objects.

https://github.com/nipype/pydra/blob/master/pydra/engine/helpers_file.py#L508

<summary>
Code 
<details>
```
import numpy as np
fft = pydra.mark.annotate({'a': np.ndarray, 'return': float})(np.fft.fft)
fft = pydra.mark.task(fft)()
foo(a=np.ones((100)))
```
</details>
</summary>

<summary> 
Error
<details>
```
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-34-af82eb0ea503> in <module>
      2 fft = pydra.mark.annotate({'a': np.ndarray, 'return': float})(np.fft.fft)
      3 fft = pydra.mark.task(fft)()
----> 4 foo(a=np.ones((100)))

~/pydra/engine/core.py in __call__(self, submitter, plugin, rerun, **kwargs)
    354                     "TODO: linear workflow execution - assign submitter or plugin for now"
    355                 )
--> 356             res = self._run(rerun=rerun, **kwargs)
    357         return res
    358 

~/pydra/engine/core.py in _run(self, rerun, **kwargs)
    378             orig_inputs = attr.asdict(self.inputs)
    379             map_copyfiles = copyfile_input(self.inputs, self.output_dir)
--> 380             modified_inputs = template_update(self.inputs, map_copyfiles)
    381             if modified_inputs is not None:
    382                 self.inputs = attr.evolve(self.inputs, **modified_inputs)

~/pydra/engine/helpers_file.py in template_update(inputs, map_copyfiles)
    506                     "{fld.name} should be a string"
    507                 )
--> 508     return {k: v for k, v in dict_.items() if getattr(inputs, k) != v}
    509 
    510 

~/pydra/engine/helpers_file.py in <dictcomp>(.0)
    506                     "{fld.name} should be a string"
    507                 )
--> 508     return {k: v for k, v in dict_.items() if getattr(inputs, k) != v}
    509 
    510 

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()```
</details>
</summary>

diff --git a/pydra/engine/tests/test_task.py b/pydra/engine/tests/test_task.py
index 2d6a15e7..e624a39c 100644
--- a/pydra/engine/tests/test_task.py
+++ b/pydra/engine/tests/test_task.py
@@ -27,6 +27,17 @@ def test_output():
     assert res.output.out == 5
 
 
+def test_numpy():
+    """ checking if mark.task works for numpy functions"""
+    np = pytest.importorskip("numpy")
+    fft = mark.annotate({"a": np.ndarray, "return": float})(np.fft.fft)
+    fft = mark.task(fft)()
+    arr = np.array([[1, 10], [2, 20]])
+    fft.inputs.a = arr
+    res = fft()
+    assert np.allclose(np.fft.fft(arr), res.output.out)
+
+
 @pytest.mark.xfail(reason="cp.dumps(func) depends on the system/setup, TODO!!")
 def test_checksum():
     nn = funaddtwo(a=3)
@@ -38,7 +49,9 @@ def test_checksum():
 
 def test_annotated_func():
     @mark.task
-    def testfunc(a: int, b: float = 0.1) -> ty.NamedTuple("Output", [("out1", float)]):
+    def testfunc(
+        a: int, b: float = 0.1
+    ) -> ty.NamedTuple("Output", [("out_out", float)]):
         return a + b
 
     funky = testfunc(a=1)
@@ -48,14 +61,14 @@ def test_annotated_func():
     assert getattr(funky.inputs, "a") == 1
     assert getattr(funky.inputs, "b") == 0.1
     assert getattr(funky.inputs, "_func") is not None
-    assert set(funky.output_names) == set(["out1"])
+    assert set(funky.output_names) == set(["out_out"])
     # assert funky.inputs.hash == '17772c3aec9540a8dd3e187eecd2301a09c9a25c6e371ddd86e31e3a1ecfeefa'
     assert funky.__class__.__name__ + "_" + funky.inputs.hash == funky.checksum
 
     result = funky()
     assert hasattr(result, "output")
-    assert hasattr(result.output, "out1")
-    assert result.output.out1 == 1.1
+    assert hasattr(result.output, "out_out")
+    assert result.output.out_out == 1.1
 
     assert os.path.exists(funky.cache_dir / funky.checksum / "_result.pklz")
     funky.result()  # should not recompute
@@ -64,7 +77,7 @@ def test_annotated_func():
     assert funky.result() is None
     funky()
     result = funky.result()
-    assert result.output.out1 == 2.1
+    assert result.output.out_out == 2.1
 
     help = funky.help(returnhelp=True)
     assert help == [
@@ -74,7 +87,7 @@ def test_annotated_func():
         "- b: float (default: 0.1)",
         "- _func: str",
         "Output Parameters:",
-        "- out1: float",
+        "- out_out: float",
     ]
 
 
@@ -150,13 +163,13 @@ def test_halfannotated_func():
     assert getattr(funky.inputs, "a") == 10
     assert getattr(funky.inputs, "b") == 20
     assert getattr(funky.inputs, "_func") is not None
-    assert set(funky.output_names) == set(["out1"])
+    assert set(funky.output_names) == set(["out"])
     assert funky.__class__.__name__ + "_" + funky.inputs.hash == funky.checksum
 
     result = funky()
     assert hasattr(result, "output")
-    assert hasattr(result.output, "out1")
-    assert result.output.out1 == 30
+    assert hasattr(result.output, "out")
+    assert result.output.out == 30
 
     assert os.path.exists(funky.cache_dir / funky.checksum / "_result.pklz")
 
@@ -165,7 +178,7 @@ def test_halfannotated_func():
     assert funky.result() is None
     funky()
     result = funky.result()
-    assert result.output.out1 == 31
+    assert result.output.out == 31
     help = funky.help(returnhelp=True)
 
     assert help == [
@@ -175,7 +188,7 @@ def test_halfannotated_func():
         "- b: _empty",
         "- _func: str",
         "Output Parameters:",
-        "- out1: int",
+        "- out: int",
     ]
 
 
diff --git a/pydra/mark/tests/test_functions.py b/pydra/mark/tests/test_functions.py
index ae963ebe..31c764ea 100644
--- a/pydra/mark/tests/test_functions.py
+++ b/pydra/mark/tests/test_functions.py
@@ -87,6 +87,16 @@ def test_return_annotated_task():
     assert res.output.squared == 4.0
 
 
+def test_return_halfannotated_annotated_task():
+    @task
+    @annotate({"in_val": float, "return": float})
+    def square(in_val):
+        return in_val ** 2
+
+    res = square(in_val=2.0)()
+    assert res.output.out == 4.0
+
+
 def test_return_annotated_task_multiple_output():
     @task
     @annotate({"in_val": float, "return": {"squared": float, "cubed": float}})

pip install -e .[dev]
parse_log_pytest
pytest
pytest
apt-get update apt-get install -y gcc
3.9
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
asttokens==3.0.0
attrs==25.3.0
beautifulsoup4==4.13.3
black==25.1.0
bleach==6.2.0
cachetools==5.5.2
certifi==2025.1.31
cfgv==3.4.0
charset-normalizer==3.4.1
ci-info==0.3.0
click==8.1.8
cloudpickle==3.1.1
codecov==2.1.13
comm==0.2.2
coverage==7.8.0
debugpy==1.8.13
decorator==5.2.1
defusedxml==0.7.1
distlib==0.3.9
entrypoints==0.4
etelemetry==0.3.1
exceptiongroup @ file:///croot/exceptiongroup_1706031385326/work
execnet==2.1.1
executing==2.2.0
fastjsonschema==2.21.1
filelock==3.18.0
frozendict==2.4.6
identify==2.6.9
idna==3.10
importlib_metadata==8.6.1
iniconfig @ file:///home/linux1/recipes/ci/iniconfig_1610983019677/work
ipykernel==6.9.2
ipython==8.18.1
ipython-genutils==0.2.0
ipywidgets==8.1.5
jedi==0.19.2
Jinja2==3.1.6
json5==0.10.0
jsonschema==4.23.0
jsonschema-specifications==2024.10.1
jupyter==1.1.1
jupyter-client==7.1.2
jupyter-console==6.4.4
jupyter-contrib-nbextensions==0.5.1
jupyter-highlight-selected-word==0.2.0
jupyter_contrib_core==0.4.2
jupyter_core==5.7.2
jupyter_latex_envs==1.4.6
jupyter_nbextensions_configurator==0.4.1
jupyterlab==2.3.2
jupyterlab-server==1.2.0
jupyterlab_pygments==0.3.0
jupyterlab_widgets==3.0.13
lxml==5.3.1
MarkupSafe==3.0.2
matplotlib-inline==0.1.7
mistune==3.1.3
mypy-extensions==1.0.0
nbclient==0.10.2
nbconvert==7.16.6
nbformat==5.10.4
nest-asyncio==1.6.0
nodeenv==1.9.1
notebook==5.7.8
numpy==2.0.2
packaging @ file:///croot/packaging_1734472117206/work
pandocfilters==1.5.1
parso==0.8.4
pathspec==0.12.1
pexpect==4.9.0
platformdirs==4.3.7
pluggy @ file:///croot/pluggy_1733169602837/work
pre_commit==4.2.0
prometheus_client==0.21.1
prompt_toolkit==3.0.50
psutil==7.0.0
ptyprocess==0.7.0
pure_eval==0.2.3
-e git+https://github.com/nipype/pydra.git@73ac9828d1e0a81720907cf2d518cafea34afba9#egg=pydra
Pygments==2.19.1
PyLD==2.0.4
pytest @ file:///croot/pytest_1738938843180/work
pytest-cov==6.0.0
pytest-env==1.1.5
pytest-xdist==3.6.1
python-dateutil==2.9.0.post0
PyYAML==6.0.2
pyzmq==26.3.0
referencing==0.36.2
requests==2.32.3
rpds-py==0.24.0
Send2Trash==1.8.3
six==1.17.0
soupsieve==2.6
stack-data==0.6.3
terminado==0.13.3
tinycss2==1.4.0
tomli @ file:///opt/conda/conda-bld/tomli_1657175507142/work
tornado==4.5.3
traitlets==5.14.3
typing_extensions==4.13.0
urllib3==2.3.0
virtualenv==20.29.3
wcwidth==0.2.13
webencodings==0.5.1
widgetsnbextension==4.0.13
zipp==3.21.0

name: pydra
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - exceptiongroup=1.2.0=py39h06a4308_0
  - iniconfig=1.1.1=pyhd3eb1b0_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=3.0.16=h5eee18b_0
  - packaging=24.2=py39h06a4308_0
  - pip=25.0=py39h06a4308_0
  - pluggy=1.5.0=py39h06a4308_0
  - pytest=8.3.4=py39h06a4308_0
  - python=3.9.21=he870216_1
  - readline=8.2=h5eee18b_0
  - setuptools=75.8.0=py39h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - tomli=2.0.1=py39h06a4308_0
  - tzdata=2025a=h04d1e81_0
  - wheel=0.45.1=py39h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - asttokens==3.0.0
      - attrs==25.3.0
      - beautifulsoup4==4.13.3
      - black==25.1.0
      - bleach==6.2.0
      - cachetools==5.5.2
      - certifi==2025.1.31
      - cfgv==3.4.0
      - charset-normalizer==3.4.1
      - ci-info==0.3.0
      - click==8.1.8
      - cloudpickle==3.1.1
      - codecov==2.1.13
      - comm==0.2.2
      - coverage==7.8.0
      - debugpy==1.8.13
      - decorator==5.2.1
      - defusedxml==0.7.1
      - distlib==0.3.9
      - entrypoints==0.4
      - etelemetry==0.3.1
      - execnet==2.1.1
      - executing==2.2.0
      - fastjsonschema==2.21.1
      - filelock==3.18.0
      - frozendict==2.4.6
      - identify==2.6.9
      - idna==3.10
      - importlib-metadata==8.6.1
      - ipykernel==6.9.2
      - ipython==8.18.1
      - ipython-genutils==0.2.0
      - ipywidgets==8.1.5
      - jedi==0.19.2
      - jinja2==3.1.6
      - json5==0.10.0
      - jsonschema==4.23.0
      - jsonschema-specifications==2024.10.1
      - jupyter==1.1.1
      - jupyter-client==7.1.2
      - jupyter-console==6.4.4
      - jupyter-contrib-core==0.4.2
      - jupyter-contrib-nbextensions==0.5.1
      - jupyter-core==5.7.2
      - jupyter-highlight-selected-word==0.2.0
      - jupyter-latex-envs==1.4.6
      - jupyter-nbextensions-configurator==0.4.1
      - jupyterlab==2.3.2
      - jupyterlab-pygments==0.3.0
      - jupyterlab-server==1.2.0
      - jupyterlab-widgets==3.0.13
      - lxml==5.3.1
      - markupsafe==3.0.2
      - matplotlib-inline==0.1.7
      - mistune==3.1.3
      - mypy-extensions==1.0.0
      - nbclient==0.10.2
      - nbconvert==7.16.6
      - nbformat==5.10.4
      - nest-asyncio==1.6.0
      - nodeenv==1.9.1
      - notebook==5.7.8
      - numpy==2.0.2
      - pandocfilters==1.5.1
      - parso==0.8.4
      - pathspec==0.12.1
      - pexpect==4.9.0
      - platformdirs==4.3.7
      - pre-commit==4.2.0
      - prometheus-client==0.21.1
      - prompt-toolkit==3.0.50
      - psutil==7.0.0
      - ptyprocess==0.7.0
      - pure-eval==0.2.3
      - pydra==0.3+11.g73ac9828
      - pygments==2.19.1
      - pyld==2.0.4
      - pytest-cov==6.0.0
      - pytest-env==1.1.5
      - pytest-xdist==3.6.1
      - python-dateutil==2.9.0.post0
      - pyyaml==6.0.2
      - pyzmq==26.3.0
      - referencing==0.36.2
      - requests==2.32.3
      - rpds-py==0.24.0
      - send2trash==1.8.3
      - six==1.17.0
      - soupsieve==2.6
      - stack-data==0.6.3
      - terminado==0.13.3
      - tinycss2==1.4.0
      - tornado==4.5.3
      - traitlets==5.14.3
      - typing-extensions==4.13.0
      - urllib3==2.3.0
      - virtualenv==20.29.3
      - wcwidth==0.2.13
      - webencodings==0.5.1
      - widgetsnbextension==4.0.13
      - zipp==3.21.0
prefix: /opt/conda/envs/pydra

pydra/engine/tests/test_task.py::test_numpy pydra/engine/tests/test_task.py::test_halfannotated_func pydra/mark/tests/test_functions.py::test_return_halfannotated_annotated_task
pydra/engine/tests/test_task.py::test_output pydra/engine/tests/test_task.py::test_annotated_func pydra/engine/tests/test_task.py::test_annotated_func_multreturn pydra/engine/tests/test_task.py::test_annotated_func_multreturn_exception pydra/engine/tests/test_task.py::test_halfannotated_func_multreturn pydra/engine/tests/test_task.py::test_notannotated_func pydra/engine/tests/test_task.py::test_notannotated_func_returnlist pydra/engine/tests/test_task.py::test_halfannotated_func_multrun_returnlist pydra/engine/tests/test_task.py::test_notannotated_func_multreturn pydra/engine/tests/test_task.py::test_exception_func pydra/engine/tests/test_task.py::test_audit_prov pydra/engine/tests/test_task.py::test_audit_all pydra/engine/tests/test_task.py::test_shell_cmd pydra/engine/tests/test_task.py::test_container_cmds pydra/engine/tests/test_task.py::test_docker_cmd pydra/engine/tests/test_task.py::test_singularity_cmd pydra/engine/tests/test_task.py::test_functask_callable pydra/engine/tests/test_task.py::test_taskhooks pydra/mark/tests/test_functions.py::test_task_equivalence pydra/mark/tests/test_functions.py::test_annotation_equivalence pydra/mark/tests/test_functions.py::test_annotation_override pydra/mark/tests/test_functions.py::test_invalid_annotation pydra/mark/tests/test_functions.py::test_annotated_task pydra/mark/tests/test_functions.py::test_return_annotated_task pydra/mark/tests/test_functions.py::test_return_annotated_task_multiple_output pydra/mark/tests/test_functions.py::test_return_halfannotated_task_multiple_output
pydra/engine/helpers_file.py pydra/engine/core.py pydra/engine/task.py
pydra/engine/helpers_file.py pydra/engine/core.py pydra/engine/task.py