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

import typing
import pathlib
from styxdefs import *

VOLUME_DILATE_METADATA = Metadata(
    id="63f0ca3ad59f9e1f8239c3ea5c2e72dfdc878c7e.workbench",
    name="volume-dilate",
    package="workbench",
    container_image_tag="nx10x/workbench:2.1.0",
)


_VolumeDilatePresmoothParamsDictNoTag = typing.TypedDict('_VolumeDilatePresmoothParamsDictNoTag', {
    "kernel": float,
    "fwhm": bool,
})
VolumeDilatePresmoothParamsDictTagged = typing.TypedDict('VolumeDilatePresmoothParamsDictTagged', {
    "@type": typing.Literal["presmooth"],
    "kernel": float,
    "fwhm": bool,
})
VolumeDilatePresmoothParamsDict = _VolumeDilatePresmoothParamsDictNoTag | VolumeDilatePresmoothParamsDictTagged


_VolumeDilateGradExtrapolateParamsDictNoTag = typing.TypedDict('_VolumeDilateGradExtrapolateParamsDictNoTag', {
    "presmooth": typing.NotRequired[VolumeDilatePresmoothParamsDict | None],
})
VolumeDilateGradExtrapolateParamsDictTagged = typing.TypedDict('VolumeDilateGradExtrapolateParamsDictTagged', {
    "@type": typing.Literal["grad-extrapolate"],
    "presmooth": typing.NotRequired[VolumeDilatePresmoothParamsDict | None],
})
VolumeDilateGradExtrapolateParamsDict = _VolumeDilateGradExtrapolateParamsDictNoTag | VolumeDilateGradExtrapolateParamsDictTagged


_VolumeDilateParamsDictNoTag = typing.TypedDict('_VolumeDilateParamsDictNoTag', {
    "volume": InputPathType,
    "distance": float,
    "method": str,
    "volume-out": str,
    "grad-extrapolate": typing.NotRequired[VolumeDilateGradExtrapolateParamsDict | None],
    "subvol": typing.NotRequired[str | None],
    "roi-volume": typing.NotRequired[InputPathType | None],
    "roi-volume": typing.NotRequired[InputPathType | None],
    "exponent": typing.NotRequired[float | None],
    "legacy-cutoff": bool,
})
VolumeDilateParamsDictTagged = typing.TypedDict('VolumeDilateParamsDictTagged', {
    "@type": typing.Literal["workbench/volume-dilate"],
    "volume": InputPathType,
    "distance": float,
    "method": str,
    "volume-out": str,
    "grad-extrapolate": typing.NotRequired[VolumeDilateGradExtrapolateParamsDict | None],
    "subvol": typing.NotRequired[str | None],
    "roi-volume": typing.NotRequired[InputPathType | None],
    "roi-volume": typing.NotRequired[InputPathType | None],
    "exponent": typing.NotRequired[float | None],
    "legacy-cutoff": bool,
})
VolumeDilateParamsDict = _VolumeDilateParamsDictNoTag | VolumeDilateParamsDictTagged


def volume_dilate_presmooth(
    kernel: float,
    fwhm: bool = False,
) -> VolumeDilatePresmoothParamsDictTagged:
    """
    Build parameters.
    
    Args:
        kernel: the size of 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_dilate_presmooth_validate(
    params: typing.Any,
) -> None:
    """
    Validate parameters. Throws an error if `params` is not a valid
    `VolumeDilatePresmoothParamsDict` 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_dilate_presmooth_cargs(
    params: VolumeDilatePresmoothParamsDict,
    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


def volume_dilate_grad_extrapolate(
    presmooth: VolumeDilatePresmoothParamsDict | None = None,
) -> VolumeDilateGradExtrapolateParamsDictTagged:
    """
    Build parameters.
    
    Args:
        presmooth: apply presmoothing before computing gradient vectors, not\
            recommended.
    Returns:
        Parameter dictionary
    """
    params = {
        "@type": "grad-extrapolate",
    }
    if presmooth is not None:
        params["presmooth"] = presmooth
    return params


def volume_dilate_grad_extrapolate_validate(
    params: typing.Any,
) -> None:
    """
    Validate parameters. Throws an error if `params` is not a valid
    `VolumeDilateGradExtrapolateParamsDict` 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("presmooth", None) is not None:
        volume_dilate_presmooth_validate(params["presmooth"])


def volume_dilate_grad_extrapolate_cargs(
    params: VolumeDilateGradExtrapolateParamsDict,
    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 = []
    if params.get("presmooth", None) is not None:
        cargs.extend([
            "-grad-extrapolate",
            *volume_dilate_presmooth_cargs(params.get("presmooth", None), execution)
        ])
    return cargs


class VolumeDilateOutputs(typing.NamedTuple):
    """
    Output object returned when calling `VolumeDilateParamsDict(...)`.
    """
    root: OutputPathType
    """Output root folder. This is the root folder for all outputs."""
    volume_out: OutputPathType
    """the output volume"""


def volume_dilate_params(
    volume: InputPathType,
    distance: float,
    method: str,
    volume_out: str,
    grad_extrapolate: VolumeDilateGradExtrapolateParamsDict | None = None,
    subvol: str | None = None,
    roi_volume: InputPathType | None = None,
    roi_volume_: InputPathType | None = None,
    exponent: float | None = None,
    legacy_cutoff: bool = False,
) -> VolumeDilateParamsDictTagged:
    """
    Build parameters.
    
    Args:
        volume: the volume to dilate.
        distance: distance in mm to dilate.
        method: dilation method to use.
        volume_out: the output volume.
        grad_extrapolate: additionally use the gradient to extrapolate,\
            intended to be used with WEIGHTED.
        subvol: select a single subvolume to dilate\
            \
            the subvolume number or name.
        roi_volume: specify an roi of where there is data\
            \
            volume file, positive values denote voxels that have data.
        roi_volume_: specify an roi of voxels to overwrite, rather than voxels\
            with value zero\
            \
            volume file, positive values denote voxels to have their values\
            replaced.
        exponent: use a different exponent in the weighting function\
            \
            exponent 'n' to use in (1 / (distance ^ n)) as the weighting\
            function (default 7).
        legacy_cutoff: use the v1.3.2 method of excluding voxels further than\
            the dilation distance when calculating the dilated value.
    Returns:
        Parameter dictionary
    """
    params = {
        "@type": "workbench/volume-dilate",
        "volume": volume,
        "distance": distance,
        "method": method,
        "volume-out": volume_out,
        "legacy-cutoff": legacy_cutoff,
    }
    if grad_extrapolate is not None:
        params["grad-extrapolate"] = grad_extrapolate
    if subvol is not None:
        params["subvol"] = subvol
    if roi_volume is not None:
        params["roi-volume"] = roi_volume
    if roi_volume_ is not None:
        params["roi-volume"] = roi_volume_
    if exponent is not None:
        params["exponent"] = exponent
    return params


def volume_dilate_validate(
    params: typing.Any,
) -> None:
    """
    Validate parameters. Throws an error if `params` is not a valid
    `VolumeDilateParamsDict` 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", None) is None:
        raise StyxValidationError("`volume` must not be None")
    if not isinstance(params["volume"], (pathlib.Path, str)):
        raise StyxValidationError(f'`volume` has the wrong type: Received `{type(params.get("volume", None))}` expected `InputPathType`')
    if params.get("distance", None) is None:
        raise StyxValidationError("`distance` must not be None")
    if not isinstance(params["distance"], (float, int)):
        raise StyxValidationError(f'`distance` has the wrong type: Received `{type(params.get("distance", None))}` expected `float`')
    if params.get("method", None) is None:
        raise StyxValidationError("`method` must not be None")
    if not isinstance(params["method"], str):
        raise StyxValidationError(f'`method` has the wrong type: Received `{type(params.get("method", None))}` expected `str`')
    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("grad-extrapolate", None) is not None:
        volume_dilate_grad_extrapolate_validate(params["grad-extrapolate"])
    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`')
    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`')
    if params.get("exponent", None) is not None:
        if not isinstance(params["exponent"], (float, int)):
            raise StyxValidationError(f'`exponent` has the wrong type: Received `{type(params.get("exponent", None))}` expected `float | None`')
    if params.get("legacy-cutoff", False) is None:
        raise StyxValidationError("`legacy-cutoff` must not be None")
    if not isinstance(params["legacy-cutoff"], bool):
        raise StyxValidationError(f'`legacy-cutoff` has the wrong type: Received `{type(params.get("legacy-cutoff", False))}` expected `bool`')


def volume_dilate_cargs(
    params: VolumeDilateParamsDict,
    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-dilate"
    ])
    cargs.append(execution.input_file(params.get("volume", None)))
    cargs.append(str(params.get("distance", None)))
    cargs.append(params.get("method", None))
    cargs.append(params.get("volume-out", None))
    if params.get("grad-extrapolate", None) is not None:
        cargs.extend(volume_dilate_grad_extrapolate_cargs(params.get("grad-extrapolate", None), execution))
    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([
            "-data-roi",
            execution.input_file(params.get("roi-volume", None))
        ])
    if params.get("roi-volume", None) is not None:
        cargs.extend([
            "-bad-voxel-roi",
            execution.input_file(params.get("roi-volume", None))
        ])
    if params.get("exponent", None) is not None:
        cargs.extend([
            "-exponent",
            str(params.get("exponent", None))
        ])
    if params.get("legacy-cutoff", False):
        cargs.append("-legacy-cutoff")
    return cargs


def volume_dilate_outputs(
    params: VolumeDilateParamsDict,
    execution: Execution,
) -> VolumeDilateOutputs:
    """
    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 = VolumeDilateOutputs(
        root=execution.output_file("."),
        volume_out=execution.output_file(params.get("volume-out", None)),
    )
    return ret


def volume_dilate_execute(
    params: VolumeDilateParamsDict,
    runner: Runner | None = None,
) -> VolumeDilateOutputs:
    """
    DILATE A VOLUME FILE.
    
    For all voxels that are designated as bad, if they neighbor a non-bad voxel
    with data or are within the specified distance of such a voxel, replace the
    value in the bad voxel with a value calculated from nearby non-bad voxels
    that have data, otherwise set the value to zero. No matter how small
    <distance> is, dilation will always use at least the face neighbor voxels.
    
    By default, voxels that have data with the value 0 are bad, specify
    -bad-voxel-roi to only count voxels as bad if they are selected by the roi.
    If -data-roi is not specified, all voxels are assumed to have data.
    
    To get the behavior of version 1.3.2 or earlier, use '-legacy-cutoff
    -exponent 2'.
    
    Valid values for <method> are:
    
    NEAREST - use the value from the nearest good voxel
    WEIGHTED - use a weighted average based on distance.
    
    Args:
        params: The parameters.
        runner: Command runner.
    Returns:
        NamedTuple of outputs (described in `VolumeDilateOutputs`).
    """
    volume_dilate_validate(params)
    runner = runner or get_global_runner()
    execution = runner.start_execution(VOLUME_DILATE_METADATA)
    params = execution.params(params)
    cargs = volume_dilate_cargs(params, execution)
    ret = volume_dilate_outputs(params, execution)
    execution.run(cargs)
    return ret


def volume_dilate(
    volume: InputPathType,
    distance: float,
    method: str,
    volume_out: str,
    grad_extrapolate: VolumeDilateGradExtrapolateParamsDict | None = None,
    subvol: str | None = None,
    roi_volume: InputPathType | None = None,
    roi_volume_: InputPathType | None = None,
    exponent: float | None = None,
    legacy_cutoff: bool = False,
    runner: Runner | None = None,
) -> VolumeDilateOutputs:
    """
    DILATE A VOLUME FILE.
    
    For all voxels that are designated as bad, if they neighbor a non-bad voxel
    with data or are within the specified distance of such a voxel, replace the
    value in the bad voxel with a value calculated from nearby non-bad voxels
    that have data, otherwise set the value to zero. No matter how small
    <distance> is, dilation will always use at least the face neighbor voxels.
    
    By default, voxels that have data with the value 0 are bad, specify
    -bad-voxel-roi to only count voxels as bad if they are selected by the roi.
    If -data-roi is not specified, all voxels are assumed to have data.
    
    To get the behavior of version 1.3.2 or earlier, use '-legacy-cutoff
    -exponent 2'.
    
    Valid values for <method> are:
    
    NEAREST - use the value from the nearest good voxel
    WEIGHTED - use a weighted average based on distance.
    
    Args:
        volume: the volume to dilate.
        distance: distance in mm to dilate.
        method: dilation method to use.
        volume_out: the output volume.
        grad_extrapolate: additionally use the gradient to extrapolate,\
            intended to be used with WEIGHTED.
        subvol: select a single subvolume to dilate\
            \
            the subvolume number or name.
        roi_volume: specify an roi of where there is data\
            \
            volume file, positive values denote voxels that have data.
        roi_volume_: specify an roi of voxels to overwrite, rather than voxels\
            with value zero\
            \
            volume file, positive values denote voxels to have their values\
            replaced.
        exponent: use a different exponent in the weighting function\
            \
            exponent 'n' to use in (1 / (distance ^ n)) as the weighting\
            function (default 7).
        legacy_cutoff: use the v1.3.2 method of excluding voxels further than\
            the dilation distance when calculating the dilated value.
        runner: Command runner.
    Returns:
        NamedTuple of outputs (described in `VolumeDilateOutputs`).
    """
    params = volume_dilate_params(
        volume=volume,
        distance=distance,
        method=method,
        volume_out=volume_out,
        grad_extrapolate=grad_extrapolate,
        subvol=subvol,
        roi_volume=roi_volume,
        roi_volume_=roi_volume_,
        exponent=exponent,
        legacy_cutoff=legacy_cutoff,
    )
    return volume_dilate_execute(params, runner)


__all__ = [
    "VOLUME_DILATE_METADATA",
    "VolumeDilateGradExtrapolateParamsDict",
    "VolumeDilateGradExtrapolateParamsDictTagged",
    "VolumeDilateOutputs",
    "VolumeDilateParamsDict",
    "VolumeDilateParamsDictTagged",
    "VolumeDilatePresmoothParamsDict",
    "VolumeDilatePresmoothParamsDictTagged",
    "volume_dilate",
    "volume_dilate_execute",
    "volume_dilate_grad_extrapolate",
    "volume_dilate_params",
    "volume_dilate_presmooth",
]
