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

import typing
import pathlib
from styxdefs import *

VOLUME_RESAMPLE_METADATA = Metadata(
    id="bc1ecda25e27333d33b361ed48fef4f0c37935a7.workbench",
    name="volume-resample",
    package="workbench",
    container_image_tag="nx10x/workbench:2.1.0",
)


_VolumeResampleFlirtParamsDictNoTag = typing.TypedDict('_VolumeResampleFlirtParamsDictNoTag', {
    "source-volume": str,
    "target-volume": str,
})
VolumeResampleFlirtParamsDictTagged = typing.TypedDict('VolumeResampleFlirtParamsDictTagged', {
    "@type": typing.Literal["flirt"],
    "source-volume": str,
    "target-volume": str,
})
VolumeResampleFlirtParamsDict = _VolumeResampleFlirtParamsDictNoTag | VolumeResampleFlirtParamsDictTagged


_VolumeResampleAffineParamsDictNoTag = typing.TypedDict('_VolumeResampleAffineParamsDictNoTag', {
    "affine": str,
    "flirt": typing.NotRequired[VolumeResampleFlirtParamsDict | None],
})
VolumeResampleAffineParamsDictTagged = typing.TypedDict('VolumeResampleAffineParamsDictTagged', {
    "@type": typing.Literal["affine"],
    "affine": str,
    "flirt": typing.NotRequired[VolumeResampleFlirtParamsDict | None],
})
VolumeResampleAffineParamsDict = _VolumeResampleAffineParamsDictNoTag | VolumeResampleAffineParamsDictTagged


_VolumeResampleFlirtParamsDict_NoTag = typing.TypedDict('_VolumeResampleFlirtParamsDict_NoTag', {
    "source-volume": str,
    "target-volume": str,
})
VolumeResampleFlirtParamsDictTagged_ = typing.TypedDict('VolumeResampleFlirtParamsDictTagged_', {
    "@type": typing.Literal["flirt"],
    "source-volume": str,
    "target-volume": str,
})
VolumeResampleFlirtParamsDict_ = _VolumeResampleFlirtParamsDict_NoTag | VolumeResampleFlirtParamsDictTagged_


_VolumeResampleAffineSeriesParamsDictNoTag = typing.TypedDict('_VolumeResampleAffineSeriesParamsDictNoTag', {
    "affine-series": str,
    "flirt": typing.NotRequired[VolumeResampleFlirtParamsDict_ | None],
})
VolumeResampleAffineSeriesParamsDictTagged = typing.TypedDict('VolumeResampleAffineSeriesParamsDictTagged', {
    "@type": typing.Literal["affine-series"],
    "affine-series": str,
    "flirt": typing.NotRequired[VolumeResampleFlirtParamsDict_ | None],
})
VolumeResampleAffineSeriesParamsDict = _VolumeResampleAffineSeriesParamsDictNoTag | VolumeResampleAffineSeriesParamsDictTagged


_VolumeResampleWarpParamsDictNoTag = typing.TypedDict('_VolumeResampleWarpParamsDictNoTag', {
    "warpfield": str,
    "source-volume": typing.NotRequired[str | None],
})
VolumeResampleWarpParamsDictTagged = typing.TypedDict('VolumeResampleWarpParamsDictTagged', {
    "@type": typing.Literal["warp"],
    "warpfield": str,
    "source-volume": typing.NotRequired[str | None],
})
VolumeResampleWarpParamsDict = _VolumeResampleWarpParamsDictNoTag | VolumeResampleWarpParamsDictTagged


_VolumeResampleParamsDictNoTag = typing.TypedDict('_VolumeResampleParamsDictNoTag', {
    "volume-in": InputPathType,
    "volume-space": str,
    "method": str,
    "volume-out": str,
    "affine": typing.NotRequired[list[VolumeResampleAffineParamsDict] | None],
    "affine-series": typing.NotRequired[list[VolumeResampleAffineSeriesParamsDict] | None],
    "warp": typing.NotRequired[list[VolumeResampleWarpParamsDict] | None],
    "value": typing.NotRequired[float | None],
})
VolumeResampleParamsDictTagged = typing.TypedDict('VolumeResampleParamsDictTagged', {
    "@type": typing.Literal["workbench/volume-resample"],
    "volume-in": InputPathType,
    "volume-space": str,
    "method": str,
    "volume-out": str,
    "affine": typing.NotRequired[list[VolumeResampleAffineParamsDict] | None],
    "affine-series": typing.NotRequired[list[VolumeResampleAffineSeriesParamsDict] | None],
    "warp": typing.NotRequired[list[VolumeResampleWarpParamsDict] | None],
    "value": typing.NotRequired[float | None],
})
VolumeResampleParamsDict = _VolumeResampleParamsDictNoTag | VolumeResampleParamsDictTagged


def volume_resample_flirt(
    source_volume: str,
    target_volume: str,
) -> VolumeResampleFlirtParamsDictTagged:
    """
    Build parameters.
    
    Args:
        source_volume: the source volume used when generating the affine.
        target_volume: the target volume used when generating the affine.
    Returns:
        Parameter dictionary
    """
    params = {
        "@type": "flirt",
        "source-volume": source_volume,
        "target-volume": target_volume,
    }
    return params


def volume_resample_flirt_validate(
    params: typing.Any,
) -> None:
    """
    Validate parameters. Throws an error if `params` is not a valid
    `VolumeResampleFlirtParamsDict` 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("source-volume", None) is None:
        raise StyxValidationError("`source-volume` must not be None")
    if not isinstance(params["source-volume"], str):
        raise StyxValidationError(f'`source-volume` has the wrong type: Received `{type(params.get("source-volume", None))}` expected `str`')
    if params.get("target-volume", None) is None:
        raise StyxValidationError("`target-volume` must not be None")
    if not isinstance(params["target-volume"], str):
        raise StyxValidationError(f'`target-volume` has the wrong type: Received `{type(params.get("target-volume", None))}` expected `str`')


def volume_resample_flirt_cargs(
    params: VolumeResampleFlirtParamsDict,
    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([
        "-flirt",
        params.get("source-volume", None),
        params.get("target-volume", None)
    ])
    return cargs


def volume_resample_affine(
    affine: str,
    flirt: VolumeResampleFlirtParamsDict | None = None,
) -> VolumeResampleAffineParamsDictTagged:
    """
    Build parameters.
    
    Args:
        affine: the affine file to use.
        flirt: MUST be used if affine is a flirt affine.
    Returns:
        Parameter dictionary
    """
    params = {
        "@type": "affine",
        "affine": affine,
    }
    if flirt is not None:
        params["flirt"] = flirt
    return params


def volume_resample_affine_validate(
    params: typing.Any,
) -> None:
    """
    Validate parameters. Throws an error if `params` is not a valid
    `VolumeResampleAffineParamsDict` 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("affine", None) is None:
        raise StyxValidationError("`affine` must not be None")
    if not isinstance(params["affine"], str):
        raise StyxValidationError(f'`affine` has the wrong type: Received `{type(params.get("affine", None))}` expected `str`')
    if params.get("flirt", None) is not None:
        volume_resample_flirt_validate(params["flirt"])


def volume_resample_affine_cargs(
    params: VolumeResampleAffineParamsDict,
    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([
        "-affine",
        params.get("affine", None),
        *(volume_resample_flirt_cargs(params.get("flirt", None), execution) if (params.get("flirt", None) is not None) else [])
    ])
    return cargs


def volume_resample_flirt_(
    source_volume: str,
    target_volume: str,
) -> VolumeResampleFlirtParamsDictTagged_:
    """
    Build parameters.
    
    Args:
        source_volume: the source volume used when generating the affine.
        target_volume: the target volume used when generating the affine.
    Returns:
        Parameter dictionary
    """
    params = {
        "@type": "flirt",
        "source-volume": source_volume,
        "target-volume": target_volume,
    }
    return params


def volume_resample_flirt_validate_(
    params: typing.Any,
) -> None:
    """
    Validate parameters. Throws an error if `params` is not a valid
    `VolumeResampleFlirtParamsDict_` 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("source-volume", None) is None:
        raise StyxValidationError("`source-volume` must not be None")
    if not isinstance(params["source-volume"], str):
        raise StyxValidationError(f'`source-volume` has the wrong type: Received `{type(params.get("source-volume", None))}` expected `str`')
    if params.get("target-volume", None) is None:
        raise StyxValidationError("`target-volume` must not be None")
    if not isinstance(params["target-volume"], str):
        raise StyxValidationError(f'`target-volume` has the wrong type: Received `{type(params.get("target-volume", None))}` expected `str`')


def volume_resample_flirt_cargs_(
    params: VolumeResampleFlirtParamsDict_,
    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([
        "-flirt",
        params.get("source-volume", None),
        params.get("target-volume", None)
    ])
    return cargs


def volume_resample_affine_series(
    affine_series: str,
    flirt: VolumeResampleFlirtParamsDict_ | None = None,
) -> VolumeResampleAffineSeriesParamsDictTagged:
    """
    Build parameters.
    
    Args:
        affine_series: text file containing 12 or 16 numbers per line, each\
            being a row-major flattened affine.
        flirt: MUST be used if the affines are flirt affines.
    Returns:
        Parameter dictionary
    """
    params = {
        "@type": "affine-series",
        "affine-series": affine_series,
    }
    if flirt is not None:
        params["flirt"] = flirt
    return params


def volume_resample_affine_series_validate(
    params: typing.Any,
) -> None:
    """
    Validate parameters. Throws an error if `params` is not a valid
    `VolumeResampleAffineSeriesParamsDict` 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("affine-series", None) is None:
        raise StyxValidationError("`affine-series` must not be None")
    if not isinstance(params["affine-series"], str):
        raise StyxValidationError(f'`affine-series` has the wrong type: Received `{type(params.get("affine-series", None))}` expected `str`')
    if params.get("flirt", None) is not None:
        volume_resample_flirt_validate_(params["flirt"])


def volume_resample_affine_series_cargs(
    params: VolumeResampleAffineSeriesParamsDict,
    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([
        "-affine-series",
        params.get("affine-series", None),
        *(volume_resample_flirt_cargs_(params.get("flirt", None), execution) if (params.get("flirt", None) is not None) else [])
    ])
    return cargs


def volume_resample_warp(
    warpfield: str,
    source_volume: str | None = None,
) -> VolumeResampleWarpParamsDictTagged:
    """
    Build parameters.
    
    Args:
        warpfield: the warpfield file.
        source_volume: MUST be used if using a fnirt warpfield\
            \
            the source volume used when generating the warpfield.
    Returns:
        Parameter dictionary
    """
    params = {
        "@type": "warp",
        "warpfield": warpfield,
    }
    if source_volume is not None:
        params["source-volume"] = source_volume
    return params


def volume_resample_warp_validate(
    params: typing.Any,
) -> None:
    """
    Validate parameters. Throws an error if `params` is not a valid
    `VolumeResampleWarpParamsDict` 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("warpfield", None) is None:
        raise StyxValidationError("`warpfield` must not be None")
    if not isinstance(params["warpfield"], str):
        raise StyxValidationError(f'`warpfield` has the wrong type: Received `{type(params.get("warpfield", None))}` expected `str`')
    if params.get("source-volume", None) is not None:
        if not isinstance(params["source-volume"], str):
            raise StyxValidationError(f'`source-volume` has the wrong type: Received `{type(params.get("source-volume", None))}` expected `str | None`')


def volume_resample_warp_cargs(
    params: VolumeResampleWarpParamsDict,
    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([
        "-warp",
        params.get("warpfield", None)
    ])
    if params.get("source-volume", None) is not None:
        cargs.extend([
            "-fnirt",
            params.get("source-volume", None)
        ])
    return cargs


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


def volume_resample_params(
    volume_in: InputPathType,
    volume_space: str,
    method: str,
    volume_out: str,
    affine: list[VolumeResampleAffineParamsDict] | None = None,
    affine_series: list[VolumeResampleAffineSeriesParamsDict] | None = None,
    warp: list[VolumeResampleWarpParamsDict] | None = None,
    value: float | None = None,
) -> VolumeResampleParamsDictTagged:
    """
    Build parameters.
    
    Args:
        volume_in: volume to resample.
        volume_space: a volume file in the volume space you want for the output.
        method: the resampling method.
        volume_out: the output volume.
        affine: add an affine transform.
        affine_series: add an independent affine per-frame.
        warp: add a nonlinear warpfield transform.
        value: use a specified value for locations outside the FoV of the input\
            image or warpfield(s)\
            \
            the value to use (default 0).
    Returns:
        Parameter dictionary
    """
    params = {
        "@type": "workbench/volume-resample",
        "volume-in": volume_in,
        "volume-space": volume_space,
        "method": method,
        "volume-out": volume_out,
    }
    if affine is not None:
        params["affine"] = affine
    if affine_series is not None:
        params["affine-series"] = affine_series
    if warp is not None:
        params["warp"] = warp
    if value is not None:
        params["value"] = value
    return params


def volume_resample_validate(
    params: typing.Any,
) -> None:
    """
    Validate parameters. Throws an error if `params` is not a valid
    `VolumeResampleParamsDict` 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-space", None) is None:
        raise StyxValidationError("`volume-space` must not be None")
    if not isinstance(params["volume-space"], str):
        raise StyxValidationError(f'`volume-space` has the wrong type: Received `{type(params.get("volume-space", None))}` expected `str`')
    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("affine", None) is not None:
        if not isinstance(params["affine"], list):
            raise StyxValidationError(f'`affine` has the wrong type: Received `{type(params.get("affine", None))}` expected `list[VolumeResampleAffineParamsDict] | None`')
        for e in params["affine"]:
            volume_resample_affine_validate(e)
    if params.get("affine-series", None) is not None:
        if not isinstance(params["affine-series"], list):
            raise StyxValidationError(f'`affine-series` has the wrong type: Received `{type(params.get("affine-series", None))}` expected `list[VolumeResampleAffineSeriesParamsDict] | None`')
        for e in params["affine-series"]:
            volume_resample_affine_series_validate(e)
    if params.get("warp", None) is not None:
        if not isinstance(params["warp"], list):
            raise StyxValidationError(f'`warp` has the wrong type: Received `{type(params.get("warp", None))}` expected `list[VolumeResampleWarpParamsDict] | None`')
        for e in params["warp"]:
            volume_resample_warp_validate(e)
    if params.get("value", None) is not None:
        if not isinstance(params["value"], (float, int)):
            raise StyxValidationError(f'`value` has the wrong type: Received `{type(params.get("value", None))}` expected `float | None`')


def volume_resample_cargs(
    params: VolumeResampleParamsDict,
    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-resample"
    ])
    cargs.append(execution.input_file(params.get("volume-in", None)))
    cargs.append(params.get("volume-space", None))
    cargs.append(params.get("method", None))
    cargs.append(params.get("volume-out", None))
    if params.get("affine", None) is not None or params.get("affine-series", None) is not None or params.get("warp", None) is not None:
        cargs.extend([
            *([a for c in [volume_resample_affine_cargs(s, execution) for s in params.get("affine", None)] for a in c] if (params.get("affine", None) is not None) else []),
            *([a for c in [volume_resample_affine_series_cargs(s, execution) for s in params.get("affine-series", None)] for a in c] if (params.get("affine-series", None) is not None) else []),
            *([a for c in [volume_resample_warp_cargs(s, execution) for s in params.get("warp", None)] for a in c] if (params.get("warp", None) is not None) else [])
        ])
    if params.get("value", None) is not None:
        cargs.extend([
            "-background",
            str(params.get("value", None))
        ])
    return cargs


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


def volume_resample_execute(
    params: VolumeResampleParamsDict,
    runner: Runner | None = None,
) -> VolumeResampleOutputs:
    """
    TRANSFORM AND RESAMPLE A VOLUME FILE.
    
    Resample a volume file with an arbitrary list of transformations. You may
    specify -affine, -warp, and -affine-series multiple times each, and they
    will be used in the order specified. For instance, for rigid motion
    correction followed by nonlinear atlas registration, specify -affine-series
    first, then -warp. The recommended methods are CUBIC (cubic spline) for most
    data, and ENCLOSING_VOXEL for label data. The parameter <method> must be one
    of:
    
    CUBIC
    ENCLOSING_VOXEL
    TRILINEAR.
    
    Args:
        params: The parameters.
        runner: Command runner.
    Returns:
        NamedTuple of outputs (described in `VolumeResampleOutputs`).
    """
    volume_resample_validate(params)
    runner = runner or get_global_runner()
    execution = runner.start_execution(VOLUME_RESAMPLE_METADATA)
    params = execution.params(params)
    cargs = volume_resample_cargs(params, execution)
    ret = volume_resample_outputs(params, execution)
    execution.run(cargs)
    return ret


def volume_resample(
    volume_in: InputPathType,
    volume_space: str,
    method: str,
    volume_out: str,
    affine: list[VolumeResampleAffineParamsDict] | None = None,
    affine_series: list[VolumeResampleAffineSeriesParamsDict] | None = None,
    warp: list[VolumeResampleWarpParamsDict] | None = None,
    value: float | None = None,
    runner: Runner | None = None,
) -> VolumeResampleOutputs:
    """
    TRANSFORM AND RESAMPLE A VOLUME FILE.
    
    Resample a volume file with an arbitrary list of transformations. You may
    specify -affine, -warp, and -affine-series multiple times each, and they
    will be used in the order specified. For instance, for rigid motion
    correction followed by nonlinear atlas registration, specify -affine-series
    first, then -warp. The recommended methods are CUBIC (cubic spline) for most
    data, and ENCLOSING_VOXEL for label data. The parameter <method> must be one
    of:
    
    CUBIC
    ENCLOSING_VOXEL
    TRILINEAR.
    
    Args:
        volume_in: volume to resample.
        volume_space: a volume file in the volume space you want for the output.
        method: the resampling method.
        volume_out: the output volume.
        affine: add an affine transform.
        affine_series: add an independent affine per-frame.
        warp: add a nonlinear warpfield transform.
        value: use a specified value for locations outside the FoV of the input\
            image or warpfield(s)\
            \
            the value to use (default 0).
        runner: Command runner.
    Returns:
        NamedTuple of outputs (described in `VolumeResampleOutputs`).
    """
    params = volume_resample_params(
        volume_in=volume_in,
        volume_space=volume_space,
        method=method,
        volume_out=volume_out,
        affine=affine,
        affine_series=affine_series,
        warp=warp,
        value=value,
    )
    return volume_resample_execute(params, runner)


__all__ = [
    "VOLUME_RESAMPLE_METADATA",
    "VolumeResampleAffineParamsDict",
    "VolumeResampleAffineParamsDictTagged",
    "VolumeResampleAffineSeriesParamsDict",
    "VolumeResampleAffineSeriesParamsDictTagged",
    "VolumeResampleFlirtParamsDict",
    "VolumeResampleFlirtParamsDictTagged",
    "VolumeResampleFlirtParamsDictTagged_",
    "VolumeResampleFlirtParamsDict_",
    "VolumeResampleOutputs",
    "VolumeResampleParamsDict",
    "VolumeResampleParamsDictTagged",
    "VolumeResampleWarpParamsDict",
    "VolumeResampleWarpParamsDictTagged",
    "volume_resample",
    "volume_resample_affine",
    "volume_resample_affine_series",
    "volume_resample_execute",
    "volume_resample_flirt",
    "volume_resample_flirt_",
    "volume_resample_params",
    "volume_resample_warp",
]
