# This file was auto generated by Styx.
# Do not edit this file directly.

import typing
import pathlib
from styxdefs import *

VOLUME_GRADIENT_METADATA = Metadata(
    id="5a5d7ede042330cd65eec319159b5ecf75f94aed.workbench",
    name="volume-gradient",
    package="workbench",
    container_image_tag="nx10x/workbench:2.1.0",
)


_VolumeGradientPresmoothParamsDictNoTag = typing.TypedDict('_VolumeGradientPresmoothParamsDictNoTag', {
    "kernel": float,
    "fwhm": bool,
})
VolumeGradientPresmoothParamsDictTagged = typing.TypedDict('VolumeGradientPresmoothParamsDictTagged', {
    "@type": typing.Literal["presmooth"],
    "kernel": float,
    "fwhm": bool,
})
VolumeGradientPresmoothParamsDict = _VolumeGradientPresmoothParamsDictNoTag | VolumeGradientPresmoothParamsDictTagged


_VolumeGradientVectorsParamsDictNoTag = typing.TypedDict('_VolumeGradientVectorsParamsDictNoTag', {
    "vector-volume-out": str,
})
VolumeGradientVectorsParamsDictTagged = typing.TypedDict('VolumeGradientVectorsParamsDictTagged', {
    "@type": typing.Literal["vectors"],
    "vector-volume-out": str,
})
VolumeGradientVectorsParamsDict = _VolumeGradientVectorsParamsDictNoTag | VolumeGradientVectorsParamsDictTagged


_VolumeGradientParamsDictNoTag = typing.TypedDict('_VolumeGradientParamsDictNoTag', {
    "volume-in": InputPathType,
    "volume-out": str,
    "presmooth": typing.NotRequired[VolumeGradientPresmoothParamsDict | None],
    "vectors": typing.NotRequired[VolumeGradientVectorsParamsDict | None],
    "subvol": typing.NotRequired[str | None],
    "roi-volume": typing.NotRequired[InputPathType | None],
})
VolumeGradientParamsDictTagged = typing.TypedDict('VolumeGradientParamsDictTagged', {
    "@type": typing.Literal["workbench/volume-gradient"],
    "volume-in": InputPathType,
    "volume-out": str,
    "presmooth": typing.NotRequired[VolumeGradientPresmoothParamsDict | None],
    "vectors": typing.NotRequired[VolumeGradientVectorsParamsDict | None],
    "subvol": typing.NotRequired[str | None],
    "roi-volume": typing.NotRequired[InputPathType | None],
})
VolumeGradientParamsDict = _VolumeGradientParamsDictNoTag | VolumeGradientParamsDictTagged


def volume_gradient_presmooth(
    kernel: float,
    fwhm: bool = False,
) -> VolumeGradientPresmoothParamsDictTagged:
    """
    Build parameters.
    
    Args:
        kernel: the size of the gaussian smoothing kernel in mm, as sigma by\
            default.
        fwhm: kernel size is FWHM, not sigma.
    Returns:
        Parameter dictionary
    """
    params = {
        "@type": "presmooth",
        "kernel": kernel,
        "fwhm": fwhm,
    }
    return params


def volume_gradient_presmooth_validate(
    params: typing.Any,
) -> None:
    """
    Validate parameters. Throws an error if `params` is not a valid
    `VolumeGradientPresmoothParamsDict` object.
    
    Args:
        params: The parameters object to validate.
    """
    if params is None or not isinstance(params, dict):
        raise StyxValidationError(f'Params object has the wrong type \'{type(params)}\'')
    if params.get("kernel", None) is None:
        raise StyxValidationError("`kernel` must not be None")
    if not isinstance(params["kernel"], (float, int)):
        raise StyxValidationError(f'`kernel` has the wrong type: Received `{type(params.get("kernel", None))}` expected `float`')
    if params.get("fwhm", False) is None:
        raise StyxValidationError("`fwhm` must not be None")
    if not isinstance(params["fwhm"], bool):
        raise StyxValidationError(f'`fwhm` has the wrong type: Received `{type(params.get("fwhm", False))}` expected `bool`')


def volume_gradient_presmooth_cargs(
    params: VolumeGradientPresmoothParamsDict,
    execution: Execution,
) -> list[str]:
    """
    Build command-line arguments from parameters.
    
    Args:
        params: The parameters.
        execution: The execution object for resolving input paths.
    Returns:
        Command-line arguments.
    """
    cargs = []
    cargs.extend([
        "-presmooth",
        str(params.get("kernel", None))
    ])
    if params.get("fwhm", False):
        cargs.append("-fwhm")
    return cargs


class VolumeGradientVectorsOutputs(typing.NamedTuple):
    """
    Output object returned when calling `VolumeGradientVectorsParamsDict | None(...)`.
    """
    root: OutputPathType
    """Output root folder. This is the root folder for all outputs."""
    vector_volume_out: OutputPathType
    """the vectors as a volume file"""


def volume_gradient_vectors(
    vector_volume_out: str,
) -> VolumeGradientVectorsParamsDictTagged:
    """
    Build parameters.
    
    Args:
        vector_volume_out: the vectors as a volume file.
    Returns:
        Parameter dictionary
    """
    params = {
        "@type": "vectors",
        "vector-volume-out": vector_volume_out,
    }
    return params


def volume_gradient_vectors_validate(
    params: typing.Any,
) -> None:
    """
    Validate parameters. Throws an error if `params` is not a valid
    `VolumeGradientVectorsParamsDict` object.
    
    Args:
        params: The parameters object to validate.
    """
    if params is None or not isinstance(params, dict):
        raise StyxValidationError(f'Params object has the wrong type \'{type(params)}\'')
    if params.get("vector-volume-out", None) is None:
        raise StyxValidationError("`vector-volume-out` must not be None")
    if not isinstance(params["vector-volume-out"], str):
        raise StyxValidationError(f'`vector-volume-out` has the wrong type: Received `{type(params.get("vector-volume-out", None))}` expected `str`')


def volume_gradient_vectors_cargs(
    params: VolumeGradientVectorsParamsDict,
    execution: Execution,
) -> list[str]:
    """
    Build command-line arguments from parameters.
    
    Args:
        params: The parameters.
        execution: The execution object for resolving input paths.
    Returns:
        Command-line arguments.
    """
    cargs = []
    cargs.extend([
        "-vectors",
        params.get("vector-volume-out", None)
    ])
    return cargs


def volume_gradient_vectors_outputs(
    params: VolumeGradientVectorsParamsDict,
    execution: Execution,
) -> VolumeGradientVectorsOutputs:
    """
    Build outputs object containing output file paths and possibly stdout/stderr.
    
    Args:
        params: The parameters.
        execution: The execution object for resolving input paths.
    Returns:
        Outputs object.
    """
    ret = VolumeGradientVectorsOutputs(
        root=execution.output_file("."),
        vector_volume_out=execution.output_file(params.get("vector-volume-out", None)),
    )
    return ret


class VolumeGradientOutputs(typing.NamedTuple):
    """
    Output object returned when calling `VolumeGradientParamsDict(...)`.
    """
    root: OutputPathType
    """Output root folder. This is the root folder for all outputs."""
    volume_out: OutputPathType
    """the output gradient magnitude volume"""
    vectors: VolumeGradientVectorsOutputs | None
    """Outputs from `volume_gradient_vectors_outputs`."""


def volume_gradient_params(
    volume_in: InputPathType,
    volume_out: str,
    presmooth: VolumeGradientPresmoothParamsDict | None = None,
    vectors: VolumeGradientVectorsParamsDict | None = None,
    subvol: str | None = None,
    roi_volume: InputPathType | None = None,
) -> VolumeGradientParamsDictTagged:
    """
    Build parameters.
    
    Args:
        volume_in: the input volume.
        volume_out: the output gradient magnitude volume.
        presmooth: smooth the volume before computing the gradient.
        vectors: output vectors.
        subvol: select a single subvolume to take the gradient of\
            \
            the subvolume number or name.
        roi_volume: select a region of interest to take the gradient of\
            \
            the region to take the gradient within.
    Returns:
        Parameter dictionary
    """
    params = {
        "@type": "workbench/volume-gradient",
        "volume-in": volume_in,
        "volume-out": volume_out,
    }
    if presmooth is not None:
        params["presmooth"] = presmooth
    if vectors is not None:
        params["vectors"] = vectors
    if subvol is not None:
        params["subvol"] = subvol
    if roi_volume is not None:
        params["roi-volume"] = roi_volume
    return params


def volume_gradient_validate(
    params: typing.Any,
) -> None:
    """
    Validate parameters. Throws an error if `params` is not a valid
    `VolumeGradientParamsDict` object.
    
    Args:
        params: The parameters object to validate.
    """
    if params is None or not isinstance(params, dict):
        raise StyxValidationError(f'Params object has the wrong type \'{type(params)}\'')
    if params.get("volume-in", None) is None:
        raise StyxValidationError("`volume-in` must not be None")
    if not isinstance(params["volume-in"], (pathlib.Path, str)):
        raise StyxValidationError(f'`volume-in` has the wrong type: Received `{type(params.get("volume-in", None))}` expected `InputPathType`')
    if params.get("volume-out", None) is None:
        raise StyxValidationError("`volume-out` must not be None")
    if not isinstance(params["volume-out"], str):
        raise StyxValidationError(f'`volume-out` has the wrong type: Received `{type(params.get("volume-out", None))}` expected `str`')
    if params.get("presmooth", None) is not None:
        volume_gradient_presmooth_validate(params["presmooth"])
    if params.get("vectors", None) is not None:
        volume_gradient_vectors_validate(params["vectors"])
    if params.get("subvol", None) is not None:
        if not isinstance(params["subvol"], str):
            raise StyxValidationError(f'`subvol` has the wrong type: Received `{type(params.get("subvol", None))}` expected `str | None`')
    if params.get("roi-volume", None) is not None:
        if not isinstance(params["roi-volume"], (pathlib.Path, str)):
            raise StyxValidationError(f'`roi-volume` has the wrong type: Received `{type(params.get("roi-volume", None))}` expected `InputPathType | None`')


def volume_gradient_cargs(
    params: VolumeGradientParamsDict,
    execution: Execution,
) -> list[str]:
    """
    Build command-line arguments from parameters.
    
    Args:
        params: The parameters.
        execution: The execution object for resolving input paths.
    Returns:
        Command-line arguments.
    """
    cargs = []
    cargs.extend([
        "wb_command",
        "-volume-gradient"
    ])
    cargs.append(execution.input_file(params.get("volume-in", None)))
    cargs.append(params.get("volume-out", None))
    if params.get("presmooth", None) is not None or params.get("vectors", None) is not None:
        cargs.extend([
            *(volume_gradient_presmooth_cargs(params.get("presmooth", None), execution) if (params.get("presmooth", None) is not None) else []),
            *(volume_gradient_vectors_cargs(params.get("vectors", None), execution) if (params.get("vectors", None) is not None) else [])
        ])
    if params.get("subvol", None) is not None:
        cargs.extend([
            "-subvolume",
            params.get("subvol", None)
        ])
    if params.get("roi-volume", None) is not None:
        cargs.extend([
            "-roi",
            execution.input_file(params.get("roi-volume", None))
        ])
    return cargs


def volume_gradient_outputs(
    params: VolumeGradientParamsDict,
    execution: Execution,
) -> VolumeGradientOutputs:
    """
    Build outputs object containing output file paths and possibly stdout/stderr.
    
    Args:
        params: The parameters.
        execution: The execution object for resolving input paths.
    Returns:
        Outputs object.
    """
    ret = VolumeGradientOutputs(
        root=execution.output_file("."),
        volume_out=execution.output_file(params.get("volume-out", None)),
        vectors=volume_gradient_vectors_outputs(params.get("vectors"), execution) if params.get("vectors") else None,
    )
    return ret


def volume_gradient_execute(
    params: VolumeGradientParamsDict,
    runner: Runner | None = None,
) -> VolumeGradientOutputs:
    """
    GRADIENT OF A VOLUME FILE.
    
    Computes the gradient of the volume by doing linear regressions for each
    voxel, considering only its face neighbors unless too few face neighbors
    exist. The gradient vector is constructed from the partial derivatives of
    the resulting linear function, and the magnitude of this vector is the
    output. If specified, the volume vector output is arranged with the x, y,
    and z components from a subvolume as consecutive subvolumes.
    
    Args:
        params: The parameters.
        runner: Command runner.
    Returns:
        NamedTuple of outputs (described in `VolumeGradientOutputs`).
    """
    volume_gradient_validate(params)
    runner = runner or get_global_runner()
    execution = runner.start_execution(VOLUME_GRADIENT_METADATA)
    params = execution.params(params)
    cargs = volume_gradient_cargs(params, execution)
    ret = volume_gradient_outputs(params, execution)
    execution.run(cargs)
    return ret


def volume_gradient(
    volume_in: InputPathType,
    volume_out: str,
    presmooth: VolumeGradientPresmoothParamsDict | None = None,
    vectors: VolumeGradientVectorsParamsDict | None = None,
    subvol: str | None = None,
    roi_volume: InputPathType | None = None,
    runner: Runner | None = None,
) -> VolumeGradientOutputs:
    """
    GRADIENT OF A VOLUME FILE.
    
    Computes the gradient of the volume by doing linear regressions for each
    voxel, considering only its face neighbors unless too few face neighbors
    exist. The gradient vector is constructed from the partial derivatives of
    the resulting linear function, and the magnitude of this vector is the
    output. If specified, the volume vector output is arranged with the x, y,
    and z components from a subvolume as consecutive subvolumes.
    
    Args:
        volume_in: the input volume.
        volume_out: the output gradient magnitude volume.
        presmooth: smooth the volume before computing the gradient.
        vectors: output vectors.
        subvol: select a single subvolume to take the gradient of\
            \
            the subvolume number or name.
        roi_volume: select a region of interest to take the gradient of\
            \
            the region to take the gradient within.
        runner: Command runner.
    Returns:
        NamedTuple of outputs (described in `VolumeGradientOutputs`).
    """
    params = volume_gradient_params(
        volume_in=volume_in,
        volume_out=volume_out,
        presmooth=presmooth,
        vectors=vectors,
        subvol=subvol,
        roi_volume=roi_volume,
    )
    return volume_gradient_execute(params, runner)


__all__ = [
    "VOLUME_GRADIENT_METADATA",
    "VolumeGradientOutputs",
    "VolumeGradientParamsDict",
    "VolumeGradientParamsDictTagged",
    "VolumeGradientPresmoothParamsDict",
    "VolumeGradientPresmoothParamsDictTagged",
    "VolumeGradientVectorsOutputs",
    "VolumeGradientVectorsParamsDict",
    "VolumeGradientVectorsParamsDictTagged",
    "volume_gradient",
    "volume_gradient_execute",
    "volume_gradient_params",
    "volume_gradient_presmooth",
    "volume_gradient_vectors",
]
