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

import typing
import pathlib
from styxdefs import *

VOLUME_WARPFIELD_AFFINE_REGRESSION_METADATA = Metadata(
    id="89e83249d5059a7e652b2c0a10e95f7e3d72df57.workbench",
    name="volume-warpfield-affine-regression",
    package="workbench",
    container_image_tag="nx10x/workbench:2.1.0",
)


_VolumeWarpfieldAffineRegressionFlirtOutParamsDictNoTag = typing.TypedDict('_VolumeWarpfieldAffineRegressionFlirtOutParamsDictNoTag', {
    "source-volume": str,
    "target-volume": str,
})
VolumeWarpfieldAffineRegressionFlirtOutParamsDictTagged = typing.TypedDict('VolumeWarpfieldAffineRegressionFlirtOutParamsDictTagged', {
    "@type": typing.Literal["flirt-out"],
    "source-volume": str,
    "target-volume": str,
})
VolumeWarpfieldAffineRegressionFlirtOutParamsDict = _VolumeWarpfieldAffineRegressionFlirtOutParamsDictNoTag | VolumeWarpfieldAffineRegressionFlirtOutParamsDictTagged


_VolumeWarpfieldAffineRegressionParamsDictNoTag = typing.TypedDict('_VolumeWarpfieldAffineRegressionParamsDictNoTag', {
    "warpfield": str,
    "affine-out": str,
    "flirt-out": typing.NotRequired[VolumeWarpfieldAffineRegressionFlirtOutParamsDict | None],
    "source-volume": typing.NotRequired[str | None],
    "roi-vol": typing.NotRequired[InputPathType | None],
})
VolumeWarpfieldAffineRegressionParamsDictTagged = typing.TypedDict('VolumeWarpfieldAffineRegressionParamsDictTagged', {
    "@type": typing.Literal["workbench/volume-warpfield-affine-regression"],
    "warpfield": str,
    "affine-out": str,
    "flirt-out": typing.NotRequired[VolumeWarpfieldAffineRegressionFlirtOutParamsDict | None],
    "source-volume": typing.NotRequired[str | None],
    "roi-vol": typing.NotRequired[InputPathType | None],
})
VolumeWarpfieldAffineRegressionParamsDict = _VolumeWarpfieldAffineRegressionParamsDictNoTag | VolumeWarpfieldAffineRegressionParamsDictTagged


def volume_warpfield_affine_regression_flirt_out(
    source_volume: str,
    target_volume: str,
) -> VolumeWarpfieldAffineRegressionFlirtOutParamsDictTagged:
    """
    Build parameters.
    
    Args:
        source_volume: the volume you want to apply the transform to.
        target_volume: the target space you want the transformed volume to\
            match.
    Returns:
        Parameter dictionary
    """
    params = {
        "@type": "flirt-out",
        "source-volume": source_volume,
        "target-volume": target_volume,
    }
    return params


def volume_warpfield_affine_regression_flirt_out_validate(
    params: typing.Any,
) -> None:
    """
    Validate parameters. Throws an error if `params` is not a valid
    `VolumeWarpfieldAffineRegressionFlirtOutParamsDict` 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_warpfield_affine_regression_flirt_out_cargs(
    params: VolumeWarpfieldAffineRegressionFlirtOutParamsDict,
    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-out",
        params.get("source-volume", None),
        params.get("target-volume", None)
    ])
    return cargs


class VolumeWarpfieldAffineRegressionOutputs(typing.NamedTuple):
    """
    Output object returned when calling `VolumeWarpfieldAffineRegressionParamsDict(...)`.
    """
    root: OutputPathType
    """Output root folder. This is the root folder for all outputs."""


def volume_warpfield_affine_regression_params(
    warpfield: str,
    affine_out: str,
    flirt_out: VolumeWarpfieldAffineRegressionFlirtOutParamsDict | None = None,
    source_volume: str | None = None,
    roi_vol: InputPathType | None = None,
) -> VolumeWarpfieldAffineRegressionParamsDictTagged:
    """
    Build parameters.
    
    Args:
        warpfield: the input warpfield.
        affine_out: output - the output affine file.
        flirt_out: write output as a flirt matrix rather than a world\
            coordinate transform.
        source_volume: input is a fnirt warpfield\
            \
            the source volume used when generating the fnirt warpfield.
        roi_vol: only consider voxels within a mask (e.g., a brain mask)\
            \
            the mask volume.
    Returns:
        Parameter dictionary
    """
    params = {
        "@type": "workbench/volume-warpfield-affine-regression",
        "warpfield": warpfield,
        "affine-out": affine_out,
    }
    if flirt_out is not None:
        params["flirt-out"] = flirt_out
    if source_volume is not None:
        params["source-volume"] = source_volume
    if roi_vol is not None:
        params["roi-vol"] = roi_vol
    return params


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


def volume_warpfield_affine_regression_cargs(
    params: VolumeWarpfieldAffineRegressionParamsDict,
    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-warpfield-affine-regression"
    ])
    cargs.append(params.get("warpfield", None))
    cargs.append(params.get("affine-out", None))
    if params.get("flirt-out", None) is not None:
        cargs.extend(volume_warpfield_affine_regression_flirt_out_cargs(params.get("flirt-out", None), execution))
    if params.get("source-volume", None) is not None:
        cargs.extend([
            "-fnirt",
            params.get("source-volume", None)
        ])
    if params.get("roi-vol", None) is not None:
        cargs.extend([
            "-roi",
            execution.input_file(params.get("roi-vol", None))
        ])
    return cargs


def volume_warpfield_affine_regression_outputs(
    params: VolumeWarpfieldAffineRegressionParamsDict,
    execution: Execution,
) -> VolumeWarpfieldAffineRegressionOutputs:
    """
    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 = VolumeWarpfieldAffineRegressionOutputs(
        root=execution.output_file("."),
    )
    return ret


def volume_warpfield_affine_regression_execute(
    params: VolumeWarpfieldAffineRegressionParamsDict,
    runner: Runner | None = None,
) -> VolumeWarpfieldAffineRegressionOutputs:
    """
    REGRESS AFFINE FROM WARPFIELD.
    
    For all voxels in the warpfield, do a regression that predicts the post-warp
    coordinate from the source coordinate. When -roi is specified, only consider
    voxels with a value greater than 0 in <roi-vol>.
    
    The default is to expect the warpfield to be in relative world coordinates
    (mm space), and to write the output as a world affine (mm space to mm
    space). If you are using FSL-created files and utilities, specify -fnirt and
    -flirt-out as needed, as their coordinate conventions are different.
    
    Args:
        params: The parameters.
        runner: Command runner.
    Returns:
        NamedTuple of outputs (described in `VolumeWarpfieldAffineRegressionOutputs`).
    """
    volume_warpfield_affine_regression_validate(params)
    runner = runner or get_global_runner()
    execution = runner.start_execution(VOLUME_WARPFIELD_AFFINE_REGRESSION_METADATA)
    params = execution.params(params)
    cargs = volume_warpfield_affine_regression_cargs(params, execution)
    ret = volume_warpfield_affine_regression_outputs(params, execution)
    execution.run(cargs)
    return ret


def volume_warpfield_affine_regression(
    warpfield: str,
    affine_out: str,
    flirt_out: VolumeWarpfieldAffineRegressionFlirtOutParamsDict | None = None,
    source_volume: str | None = None,
    roi_vol: InputPathType | None = None,
    runner: Runner | None = None,
) -> VolumeWarpfieldAffineRegressionOutputs:
    """
    REGRESS AFFINE FROM WARPFIELD.
    
    For all voxels in the warpfield, do a regression that predicts the post-warp
    coordinate from the source coordinate. When -roi is specified, only consider
    voxels with a value greater than 0 in <roi-vol>.
    
    The default is to expect the warpfield to be in relative world coordinates
    (mm space), and to write the output as a world affine (mm space to mm
    space). If you are using FSL-created files and utilities, specify -fnirt and
    -flirt-out as needed, as their coordinate conventions are different.
    
    Args:
        warpfield: the input warpfield.
        affine_out: output - the output affine file.
        flirt_out: write output as a flirt matrix rather than a world\
            coordinate transform.
        source_volume: input is a fnirt warpfield\
            \
            the source volume used when generating the fnirt warpfield.
        roi_vol: only consider voxels within a mask (e.g., a brain mask)\
            \
            the mask volume.
        runner: Command runner.
    Returns:
        NamedTuple of outputs (described in `VolumeWarpfieldAffineRegressionOutputs`).
    """
    params = volume_warpfield_affine_regression_params(
        warpfield=warpfield,
        affine_out=affine_out,
        flirt_out=flirt_out,
        source_volume=source_volume,
        roi_vol=roi_vol,
    )
    return volume_warpfield_affine_regression_execute(params, runner)


__all__ = [
    "VOLUME_WARPFIELD_AFFINE_REGRESSION_METADATA",
    "VolumeWarpfieldAffineRegressionFlirtOutParamsDict",
    "VolumeWarpfieldAffineRegressionFlirtOutParamsDictTagged",
    "VolumeWarpfieldAffineRegressionOutputs",
    "VolumeWarpfieldAffineRegressionParamsDict",
    "VolumeWarpfieldAffineRegressionParamsDictTagged",
    "volume_warpfield_affine_regression",
    "volume_warpfield_affine_regression_execute",
    "volume_warpfield_affine_regression_flirt_out",
    "volume_warpfield_affine_regression_params",
]
