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

import typing
import pathlib
from styxdefs import *

CREATE_SIGNED_DISTANCE_VOLUME_METADATA = Metadata(
    id="4d61fcbc40072b03f96c88c490ff99bbafba1379.workbench",
    name="create-signed-distance-volume",
    package="workbench",
    container_image_tag="nx10x/workbench:2.1.0",
)


_CreateSignedDistanceVolumeRoiOutParamsDictNoTag = typing.TypedDict('_CreateSignedDistanceVolumeRoiOutParamsDictNoTag', {
    "roi-vol": str,
})
CreateSignedDistanceVolumeRoiOutParamsDictTagged = typing.TypedDict('CreateSignedDistanceVolumeRoiOutParamsDictTagged', {
    "@type": typing.Literal["roi-out"],
    "roi-vol": str,
})
CreateSignedDistanceVolumeRoiOutParamsDict = _CreateSignedDistanceVolumeRoiOutParamsDictNoTag | CreateSignedDistanceVolumeRoiOutParamsDictTagged


_CreateSignedDistanceVolumeParamsDictNoTag = typing.TypedDict('_CreateSignedDistanceVolumeParamsDictNoTag', {
    "surface": InputPathType,
    "refspace": str,
    "outvol": str,
    "roi-out": typing.NotRequired[CreateSignedDistanceVolumeRoiOutParamsDict | None],
    "method": typing.NotRequired[str | None],
    "num": typing.NotRequired[int | None],
    "dist": typing.NotRequired[float | None],
    "dist": typing.NotRequired[float | None],
    "value": typing.NotRequired[float | None],
})
CreateSignedDistanceVolumeParamsDictTagged = typing.TypedDict('CreateSignedDistanceVolumeParamsDictTagged', {
    "@type": typing.Literal["workbench/create-signed-distance-volume"],
    "surface": InputPathType,
    "refspace": str,
    "outvol": str,
    "roi-out": typing.NotRequired[CreateSignedDistanceVolumeRoiOutParamsDict | None],
    "method": typing.NotRequired[str | None],
    "num": typing.NotRequired[int | None],
    "dist": typing.NotRequired[float | None],
    "dist": typing.NotRequired[float | None],
    "value": typing.NotRequired[float | None],
})
CreateSignedDistanceVolumeParamsDict = _CreateSignedDistanceVolumeParamsDictNoTag | CreateSignedDistanceVolumeParamsDictTagged


class CreateSignedDistanceVolumeRoiOutOutputs(typing.NamedTuple):
    """
    Output object returned when calling `CreateSignedDistanceVolumeRoiOutParamsDict | None(...)`.
    """
    root: OutputPathType
    """Output root folder. This is the root folder for all outputs."""
    roi_vol: OutputPathType
    """the output roi volume"""


def create_signed_distance_volume_roi_out(
    roi_vol: str,
) -> CreateSignedDistanceVolumeRoiOutParamsDictTagged:
    """
    Build parameters.
    
    Args:
        roi_vol: the output roi volume.
    Returns:
        Parameter dictionary
    """
    params = {
        "@type": "roi-out",
        "roi-vol": roi_vol,
    }
    return params


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


def create_signed_distance_volume_roi_out_cargs(
    params: CreateSignedDistanceVolumeRoiOutParamsDict,
    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([
        "-roi-out",
        params.get("roi-vol", None)
    ])
    return cargs


def create_signed_distance_volume_roi_out_outputs(
    params: CreateSignedDistanceVolumeRoiOutParamsDict,
    execution: Execution,
) -> CreateSignedDistanceVolumeRoiOutOutputs:
    """
    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 = CreateSignedDistanceVolumeRoiOutOutputs(
        root=execution.output_file("."),
        roi_vol=execution.output_file(params.get("roi-vol", None)),
    )
    return ret


class CreateSignedDistanceVolumeOutputs(typing.NamedTuple):
    """
    Output object returned when calling `CreateSignedDistanceVolumeParamsDict(...)`.
    """
    root: OutputPathType
    """Output root folder. This is the root folder for all outputs."""
    outvol: OutputPathType
    """the output volume"""
    roi_out: CreateSignedDistanceVolumeRoiOutOutputs | None
    """Outputs from `create_signed_distance_volume_roi_out_outputs`."""


def create_signed_distance_volume_params(
    surface: InputPathType,
    refspace: str,
    outvol: str,
    roi_out: CreateSignedDistanceVolumeRoiOutParamsDict | None = None,
    method: str | None = None,
    num: int | None = None,
    dist: float | None = None,
    dist_: float | None = None,
    value: float | None = None,
) -> CreateSignedDistanceVolumeParamsDictTagged:
    """
    Build parameters.
    
    Args:
        surface: the input surface.
        refspace: a volume in the desired output space (dims, spacing, origin).
        outvol: the output volume.
        roi_out: output an roi volume of where the output has a computed value.
        method: winding method for point inside surface test\
            \
            name of the method (default EVEN_ODD).
        num: voxel neighborhood for approximate calculation\
            \
            size of neighborhood cube measured from center to face, in voxels\
            (default 2 = 5x5x5).
        dist: specify distance for approximate output\
            \
            distance in mm (default 20).
        dist_: specify distance for exact output\
            \
            distance in mm (default 5).
        value: specify a value to put in all voxels that don't get assigned a\
            distance\
            \
            value to fill with (default 0).
    Returns:
        Parameter dictionary
    """
    params = {
        "@type": "workbench/create-signed-distance-volume",
        "surface": surface,
        "refspace": refspace,
        "outvol": outvol,
    }
    if roi_out is not None:
        params["roi-out"] = roi_out
    if method is not None:
        params["method"] = method
    if num is not None:
        params["num"] = num
    if dist is not None:
        params["dist"] = dist
    if dist_ is not None:
        params["dist"] = dist_
    if value is not None:
        params["value"] = value
    return params


def create_signed_distance_volume_validate(
    params: typing.Any,
) -> None:
    """
    Validate parameters. Throws an error if `params` is not a valid
    `CreateSignedDistanceVolumeParamsDict` 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("surface", None) is None:
        raise StyxValidationError("`surface` must not be None")
    if not isinstance(params["surface"], (pathlib.Path, str)):
        raise StyxValidationError(f'`surface` has the wrong type: Received `{type(params.get("surface", None))}` expected `InputPathType`')
    if params.get("refspace", None) is None:
        raise StyxValidationError("`refspace` must not be None")
    if not isinstance(params["refspace"], str):
        raise StyxValidationError(f'`refspace` has the wrong type: Received `{type(params.get("refspace", None))}` expected `str`')
    if params.get("outvol", None) is None:
        raise StyxValidationError("`outvol` must not be None")
    if not isinstance(params["outvol"], str):
        raise StyxValidationError(f'`outvol` has the wrong type: Received `{type(params.get("outvol", None))}` expected `str`')
    if params.get("roi-out", None) is not None:
        create_signed_distance_volume_roi_out_validate(params["roi-out"])
    if params.get("method", None) is not None:
        if not isinstance(params["method"], str):
            raise StyxValidationError(f'`method` has the wrong type: Received `{type(params.get("method", None))}` expected `str | None`')
    if params.get("num", None) is not None:
        if not isinstance(params["num"], int):
            raise StyxValidationError(f'`num` has the wrong type: Received `{type(params.get("num", None))}` expected `int | None`')
    if params.get("dist", None) is not None:
        if not isinstance(params["dist"], (float, int)):
            raise StyxValidationError(f'`dist` has the wrong type: Received `{type(params.get("dist", None))}` expected `float | None`')
    if params.get("dist", None) is not None:
        if not isinstance(params["dist"], (float, int)):
            raise StyxValidationError(f'`dist` has the wrong type: Received `{type(params.get("dist", None))}` expected `float | None`')
    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 create_signed_distance_volume_cargs(
    params: CreateSignedDistanceVolumeParamsDict,
    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",
        "-create-signed-distance-volume"
    ])
    cargs.append(execution.input_file(params.get("surface", None)))
    cargs.append(params.get("refspace", None))
    cargs.append(params.get("outvol", None))
    if params.get("roi-out", None) is not None:
        cargs.extend(create_signed_distance_volume_roi_out_cargs(params.get("roi-out", None), execution))
    if params.get("method", None) is not None:
        cargs.extend([
            "-winding",
            params.get("method", None)
        ])
    if params.get("num", None) is not None:
        cargs.extend([
            "-approx-neighborhood",
            str(params.get("num", None))
        ])
    if params.get("dist", None) is not None:
        cargs.extend([
            "-approx-limit",
            str(params.get("dist", None))
        ])
    if params.get("dist", None) is not None:
        cargs.extend([
            "-exact-limit",
            str(params.get("dist", None))
        ])
    if params.get("value", None) is not None:
        cargs.extend([
            "-fill-value",
            str(params.get("value", None))
        ])
    return cargs


def create_signed_distance_volume_outputs(
    params: CreateSignedDistanceVolumeParamsDict,
    execution: Execution,
) -> CreateSignedDistanceVolumeOutputs:
    """
    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 = CreateSignedDistanceVolumeOutputs(
        root=execution.output_file("."),
        outvol=execution.output_file(params.get("outvol", None)),
        roi_out=create_signed_distance_volume_roi_out_outputs(params.get("roi-out"), execution) if params.get("roi-out") else None,
    )
    return ret


def create_signed_distance_volume_execute(
    params: CreateSignedDistanceVolumeParamsDict,
    runner: Runner | None = None,
) -> CreateSignedDistanceVolumeOutputs:
    """
    CREATE SIGNED DISTANCE VOLUME FROM SURFACE.
    
    Computes the signed distance function of the surface. Exact distance is
    calculated by finding the closest point on any surface triangle to the
    center of the voxel. Approximate distance is calculated starting with these
    distances, using dijkstra's method with a neighborhood of voxels. Specifying
    too small of an exact distance may produce unexpected results. Valid
    specifiers for winding methods are as follows:
    
    EVEN_ODD (default)
    NEGATIVE
    NONZERO
    NORMALS
    
    The NORMALS method uses the normals of triangles and edges, or the closest
    triangle hit by a ray from the point. This method may be slightly faster,
    but is only reliable for a closed surface that does not cross through
    itself. All other methods count entry (positive) and exit (negative)
    crossings of a vertical ray from the point, then counts as inside if the
    total is odd, negative, or nonzero, respectively.
    
    Args:
        params: The parameters.
        runner: Command runner.
    Returns:
        NamedTuple of outputs (described in `CreateSignedDistanceVolumeOutputs`).
    """
    create_signed_distance_volume_validate(params)
    runner = runner or get_global_runner()
    execution = runner.start_execution(CREATE_SIGNED_DISTANCE_VOLUME_METADATA)
    params = execution.params(params)
    cargs = create_signed_distance_volume_cargs(params, execution)
    ret = create_signed_distance_volume_outputs(params, execution)
    execution.run(cargs)
    return ret


def create_signed_distance_volume(
    surface: InputPathType,
    refspace: str,
    outvol: str,
    roi_out: CreateSignedDistanceVolumeRoiOutParamsDict | None = None,
    method: str | None = None,
    num: int | None = None,
    dist: float | None = None,
    dist_: float | None = None,
    value: float | None = None,
    runner: Runner | None = None,
) -> CreateSignedDistanceVolumeOutputs:
    """
    CREATE SIGNED DISTANCE VOLUME FROM SURFACE.
    
    Computes the signed distance function of the surface. Exact distance is
    calculated by finding the closest point on any surface triangle to the
    center of the voxel. Approximate distance is calculated starting with these
    distances, using dijkstra's method with a neighborhood of voxels. Specifying
    too small of an exact distance may produce unexpected results. Valid
    specifiers for winding methods are as follows:
    
    EVEN_ODD (default)
    NEGATIVE
    NONZERO
    NORMALS
    
    The NORMALS method uses the normals of triangles and edges, or the closest
    triangle hit by a ray from the point. This method may be slightly faster,
    but is only reliable for a closed surface that does not cross through
    itself. All other methods count entry (positive) and exit (negative)
    crossings of a vertical ray from the point, then counts as inside if the
    total is odd, negative, or nonzero, respectively.
    
    Args:
        surface: the input surface.
        refspace: a volume in the desired output space (dims, spacing, origin).
        outvol: the output volume.
        roi_out: output an roi volume of where the output has a computed value.
        method: winding method for point inside surface test\
            \
            name of the method (default EVEN_ODD).
        num: voxel neighborhood for approximate calculation\
            \
            size of neighborhood cube measured from center to face, in voxels\
            (default 2 = 5x5x5).
        dist: specify distance for approximate output\
            \
            distance in mm (default 20).
        dist_: specify distance for exact output\
            \
            distance in mm (default 5).
        value: specify a value to put in all voxels that don't get assigned a\
            distance\
            \
            value to fill with (default 0).
        runner: Command runner.
    Returns:
        NamedTuple of outputs (described in `CreateSignedDistanceVolumeOutputs`).
    """
    params = create_signed_distance_volume_params(
        surface=surface,
        refspace=refspace,
        outvol=outvol,
        roi_out=roi_out,
        method=method,
        num=num,
        dist=dist,
        dist_=dist_,
        value=value,
    )
    return create_signed_distance_volume_execute(params, runner)


__all__ = [
    "CREATE_SIGNED_DISTANCE_VOLUME_METADATA",
    "CreateSignedDistanceVolumeOutputs",
    "CreateSignedDistanceVolumeParamsDict",
    "CreateSignedDistanceVolumeParamsDictTagged",
    "CreateSignedDistanceVolumeRoiOutOutputs",
    "CreateSignedDistanceVolumeRoiOutParamsDict",
    "CreateSignedDistanceVolumeRoiOutParamsDictTagged",
    "create_signed_distance_volume",
    "create_signed_distance_volume_execute",
    "create_signed_distance_volume_params",
    "create_signed_distance_volume_roi_out",
]
