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

import typing
import pathlib
from styxdefs import *

VOLUME_SMOOTHING_METADATA = Metadata(
    id="d799671856dffbf8bcd37b5fc4f2635099c3c22c.workbench",
    name="volume-smoothing",
    package="workbench",
    container_image_tag="nx10x/workbench:2.1.0",
)


_VolumeSmoothingParamsDictNoTag = typing.TypedDict('_VolumeSmoothingParamsDictNoTag', {
    "volume-in": InputPathType,
    "kernel": float,
    "volume-out": str,
    "subvol": typing.NotRequired[str | None],
    "roivol": typing.NotRequired[InputPathType | None],
    "fix-zeros": bool,
    "fwhm": bool,
})
VolumeSmoothingParamsDictTagged = typing.TypedDict('VolumeSmoothingParamsDictTagged', {
    "@type": typing.Literal["workbench/volume-smoothing"],
    "volume-in": InputPathType,
    "kernel": float,
    "volume-out": str,
    "subvol": typing.NotRequired[str | None],
    "roivol": typing.NotRequired[InputPathType | None],
    "fix-zeros": bool,
    "fwhm": bool,
})
VolumeSmoothingParamsDict = _VolumeSmoothingParamsDictNoTag | VolumeSmoothingParamsDictTagged


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


def volume_smoothing_params(
    volume_in: InputPathType,
    kernel: float,
    volume_out: str,
    subvol: str | None = None,
    roivol: InputPathType | None = None,
    fix_zeros: bool = False,
    fwhm: bool = False,
) -> VolumeSmoothingParamsDictTagged:
    """
    Build parameters.
    
    Args:
        volume_in: the volume to smooth.
        kernel: the size of the gaussian smoothing kernel in mm, as sigma by\
            default.
        volume_out: the output volume.
        subvol: select a single subvolume to smooth\
            \
            the subvolume number or name.
        roivol: smooth only from data within an ROI\
            \
            the volume to use as an ROI.
        fix_zeros: treat zero values as not being data.
        fwhm: kernel size is FWHM, not sigma.
    Returns:
        Parameter dictionary
    """
    params = {
        "@type": "workbench/volume-smoothing",
        "volume-in": volume_in,
        "kernel": kernel,
        "volume-out": volume_out,
        "fix-zeros": fix_zeros,
        "fwhm": fwhm,
    }
    if subvol is not None:
        params["subvol"] = subvol
    if roivol is not None:
        params["roivol"] = roivol
    return params


def volume_smoothing_validate(
    params: typing.Any,
) -> None:
    """
    Validate parameters. Throws an error if `params` is not a valid
    `VolumeSmoothingParamsDict` 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("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("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("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("roivol", None) is not None:
        if not isinstance(params["roivol"], (pathlib.Path, str)):
            raise StyxValidationError(f'`roivol` has the wrong type: Received `{type(params.get("roivol", None))}` expected `InputPathType | None`')
    if params.get("fix-zeros", False) is None:
        raise StyxValidationError("`fix-zeros` must not be None")
    if not isinstance(params["fix-zeros"], bool):
        raise StyxValidationError(f'`fix-zeros` has the wrong type: Received `{type(params.get("fix-zeros", False))}` expected `bool`')
    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_smoothing_cargs(
    params: VolumeSmoothingParamsDict,
    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-smoothing"
    ])
    cargs.append(execution.input_file(params.get("volume-in", None)))
    cargs.append(str(params.get("kernel", None)))
    cargs.append(params.get("volume-out", None))
    if params.get("subvol", None) is not None:
        cargs.extend([
            "-subvolume",
            params.get("subvol", None)
        ])
    if params.get("roivol", None) is not None:
        cargs.extend([
            "-roi",
            execution.input_file(params.get("roivol", None))
        ])
    if params.get("fix-zeros", False):
        cargs.append("-fix-zeros")
    if params.get("fwhm", False):
        cargs.append("-fwhm")
    return cargs


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


def volume_smoothing_execute(
    params: VolumeSmoothingParamsDict,
    runner: Runner | None = None,
) -> VolumeSmoothingOutputs:
    """
    SMOOTH A VOLUME FILE.
    
    Gaussian smoothing for volumes. By default, smooths all subvolumes with no
    ROI, if ROI is given, only positive voxels in the ROI volume have their
    values used, and all other voxels are set to zero. Smoothing a
    non-orthogonal volume will be significantly slower, because the operation
    cannot be separated into 1-dimensional smoothings without distorting the
    kernel shape.
    
    The -fix-zeros option causes the smoothing to not use an input value if it
    is zero, but still write a smoothed value to the voxel. This is useful for
    zeros that indicate lack of information, preventing them from pulling down
    the intensity of nearby voxels, while giving the zero an extrapolated value.
    
    Args:
        params: The parameters.
        runner: Command runner.
    Returns:
        NamedTuple of outputs (described in `VolumeSmoothingOutputs`).
    """
    volume_smoothing_validate(params)
    runner = runner or get_global_runner()
    execution = runner.start_execution(VOLUME_SMOOTHING_METADATA)
    params = execution.params(params)
    cargs = volume_smoothing_cargs(params, execution)
    ret = volume_smoothing_outputs(params, execution)
    execution.run(cargs)
    return ret


def volume_smoothing(
    volume_in: InputPathType,
    kernel: float,
    volume_out: str,
    subvol: str | None = None,
    roivol: InputPathType | None = None,
    fix_zeros: bool = False,
    fwhm: bool = False,
    runner: Runner | None = None,
) -> VolumeSmoothingOutputs:
    """
    SMOOTH A VOLUME FILE.
    
    Gaussian smoothing for volumes. By default, smooths all subvolumes with no
    ROI, if ROI is given, only positive voxels in the ROI volume have their
    values used, and all other voxels are set to zero. Smoothing a
    non-orthogonal volume will be significantly slower, because the operation
    cannot be separated into 1-dimensional smoothings without distorting the
    kernel shape.
    
    The -fix-zeros option causes the smoothing to not use an input value if it
    is zero, but still write a smoothed value to the voxel. This is useful for
    zeros that indicate lack of information, preventing them from pulling down
    the intensity of nearby voxels, while giving the zero an extrapolated value.
    
    Args:
        volume_in: the volume to smooth.
        kernel: the size of the gaussian smoothing kernel in mm, as sigma by\
            default.
        volume_out: the output volume.
        subvol: select a single subvolume to smooth\
            \
            the subvolume number or name.
        roivol: smooth only from data within an ROI\
            \
            the volume to use as an ROI.
        fix_zeros: treat zero values as not being data.
        fwhm: kernel size is FWHM, not sigma.
        runner: Command runner.
    Returns:
        NamedTuple of outputs (described in `VolumeSmoothingOutputs`).
    """
    params = volume_smoothing_params(
        volume_in=volume_in,
        kernel=kernel,
        volume_out=volume_out,
        subvol=subvol,
        roivol=roivol,
        fix_zeros=fix_zeros,
        fwhm=fwhm,
    )
    return volume_smoothing_execute(params, runner)


__all__ = [
    "VOLUME_SMOOTHING_METADATA",
    "VolumeSmoothingOutputs",
    "VolumeSmoothingParamsDict",
    "VolumeSmoothingParamsDictTagged",
    "volume_smoothing",
    "volume_smoothing_execute",
    "volume_smoothing_params",
]
