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

import typing
import pathlib
from styxdefs import *

SIMULATE_DISPLACEMENT_FIELD_METADATA = Metadata(
    id="62eab1210d3ee9c94268b73a3a247d08a7a705f3.boutiques",
    name="SimulateDisplacementField",
    package="ants",
    container_image_tag="antsx/ants:v2.5.3",
)


_SimulateDisplacementFieldBsplineOptionsParamsDictNoTag = typing.TypedDict('_SimulateDisplacementFieldBsplineOptionsParamsDictNoTag', {
    "number_of_fitting_levels": typing.NotRequired[int | None],
    "number_of_control_points": typing.NotRequired[int | None],
})
SimulateDisplacementFieldBsplineOptionsParamsDictTagged = typing.TypedDict('SimulateDisplacementFieldBsplineOptionsParamsDictTagged', {
    "@type": typing.Literal["bspline_options"],
    "number_of_fitting_levels": typing.NotRequired[int | None],
    "number_of_control_points": typing.NotRequired[int | None],
})
SimulateDisplacementFieldBsplineOptionsParamsDict = _SimulateDisplacementFieldBsplineOptionsParamsDictNoTag | SimulateDisplacementFieldBsplineOptionsParamsDictTagged


_SimulateDisplacementFieldExponentialOptionsParamsDictNoTag = typing.TypedDict('_SimulateDisplacementFieldExponentialOptionsParamsDictNoTag', {
    "smoothing_standard_deviation": typing.NotRequired[float | None],
})
SimulateDisplacementFieldExponentialOptionsParamsDictTagged = typing.TypedDict('SimulateDisplacementFieldExponentialOptionsParamsDictTagged', {
    "@type": typing.Literal["exponential_options"],
    "smoothing_standard_deviation": typing.NotRequired[float | None],
})
SimulateDisplacementFieldExponentialOptionsParamsDict = _SimulateDisplacementFieldExponentialOptionsParamsDictNoTag | SimulateDisplacementFieldExponentialOptionsParamsDictTagged


_SimulateDisplacementFieldParamsDictNoTag = typing.TypedDict('_SimulateDisplacementFieldParamsDictNoTag', {
    "image_dimension": int,
    "displacement_field_type": typing.Literal["BSpline", "Exponential"],
    "domain_image": InputPathType,
    "output_field": str,
    "number_of_random_points": typing.NotRequired[int | None],
    "standard_deviation_displacement_field": typing.NotRequired[float | None],
    "enforce_stationary_boundary": typing.NotRequired[int | None],
    "displacement_specific_options": typing.NotRequired[typing.Union[SimulateDisplacementFieldBsplineOptionsParamsDictTagged, SimulateDisplacementFieldExponentialOptionsParamsDictTagged] | None],
})
SimulateDisplacementFieldParamsDictTagged = typing.TypedDict('SimulateDisplacementFieldParamsDictTagged', {
    "@type": typing.Literal["ants/SimulateDisplacementField"],
    "image_dimension": int,
    "displacement_field_type": typing.Literal["BSpline", "Exponential"],
    "domain_image": InputPathType,
    "output_field": str,
    "number_of_random_points": typing.NotRequired[int | None],
    "standard_deviation_displacement_field": typing.NotRequired[float | None],
    "enforce_stationary_boundary": typing.NotRequired[int | None],
    "displacement_specific_options": typing.NotRequired[typing.Union[SimulateDisplacementFieldBsplineOptionsParamsDictTagged, SimulateDisplacementFieldExponentialOptionsParamsDictTagged] | None],
})
SimulateDisplacementFieldParamsDict = _SimulateDisplacementFieldParamsDictNoTag | SimulateDisplacementFieldParamsDictTagged


def simulate_displacement_field_displacement_specific_options_cargs_dyn_fn(
    t: str,
) -> typing.Any:
    """
    Get build cargs function by command type.
    
    Args:
        t: Command type.
    Returns:
        Build cargs function.
    """
    return {
        "bspline_options": simulate_displacement_field_bspline_options_cargs,
        "exponential_options": simulate_displacement_field_exponential_options_cargs,
    }.get(t)


def simulate_displacement_field_displacement_specific_options_validate_dyn_fn(
    t: str,
) -> typing.Any:
    """
    Get validate params function by command type.
    
    Args:
        t: Command type.
    Returns:
        Validate params function.
    """
    return {
        "bspline_options": simulate_displacement_field_bspline_options_validate,
        "exponential_options": simulate_displacement_field_exponential_options_validate,
    }.get(t)


def simulate_displacement_field_bspline_options(
    number_of_fitting_levels: int | None = None,
    number_of_control_points: int | None = None,
) -> SimulateDisplacementFieldBsplineOptionsParamsDictTagged:
    """
    Build parameters.
    
    Args:
        number_of_fitting_levels: Number of fitting levels for BSpline.
        number_of_control_points: Number of control points for BSpline.
    Returns:
        Parameter dictionary
    """
    params = {
        "@type": "bspline_options",
    }
    if number_of_fitting_levels is not None:
        params["number_of_fitting_levels"] = number_of_fitting_levels
    if number_of_control_points is not None:
        params["number_of_control_points"] = number_of_control_points
    return params


def simulate_displacement_field_bspline_options_validate(
    params: typing.Any,
) -> None:
    """
    Validate parameters. Throws an error if `params` is not a valid
    `SimulateDisplacementFieldBsplineOptionsParamsDict` 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("number_of_fitting_levels", None) is not None:
        if not isinstance(params["number_of_fitting_levels"], int):
            raise StyxValidationError(f'`number_of_fitting_levels` has the wrong type: Received `{type(params.get("number_of_fitting_levels", None))}` expected `int | None`')
    if params.get("number_of_control_points", None) is not None:
        if not isinstance(params["number_of_control_points"], int):
            raise StyxValidationError(f'`number_of_control_points` has the wrong type: Received `{type(params.get("number_of_control_points", None))}` expected `int | None`')


def simulate_displacement_field_bspline_options_cargs(
    params: SimulateDisplacementFieldBsplineOptionsParamsDict,
    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("number_of_fitting_levels", None) is not None:
        cargs.append(str(params.get("number_of_fitting_levels", None)))
    if params.get("number_of_control_points", None) is not None:
        cargs.append(str(params.get("number_of_control_points", None)))
    return cargs


def simulate_displacement_field_exponential_options(
    smoothing_standard_deviation: float | None = None,
) -> SimulateDisplacementFieldExponentialOptionsParamsDictTagged:
    """
    Build parameters.
    
    Args:
        smoothing_standard_deviation: Smoothing standard deviation for\
            Exponential.
    Returns:
        Parameter dictionary
    """
    params = {
        "@type": "exponential_options",
    }
    if smoothing_standard_deviation is not None:
        params["smoothing_standard_deviation"] = smoothing_standard_deviation
    return params


def simulate_displacement_field_exponential_options_validate(
    params: typing.Any,
) -> None:
    """
    Validate parameters. Throws an error if `params` is not a valid
    `SimulateDisplacementFieldExponentialOptionsParamsDict` 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("smoothing_standard_deviation", None) is not None:
        if not isinstance(params["smoothing_standard_deviation"], (float, int)):
            raise StyxValidationError(f'`smoothing_standard_deviation` has the wrong type: Received `{type(params.get("smoothing_standard_deviation", None))}` expected `float | None`')


def simulate_displacement_field_exponential_options_cargs(
    params: SimulateDisplacementFieldExponentialOptionsParamsDict,
    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("smoothing_standard_deviation", None) is not None:
        cargs.append(str(params.get("smoothing_standard_deviation", None)))
    return cargs


class SimulateDisplacementFieldOutputs(typing.NamedTuple):
    """
    Output object returned when calling `SimulateDisplacementFieldParamsDict(...)`.
    """
    root: OutputPathType
    """Output root folder. This is the root folder for all outputs."""
    output_displacement_field: OutputPathType
    """The simulated displacement field."""


def simulate_displacement_field_params(
    image_dimension: int,
    displacement_field_type: typing.Literal["BSpline", "Exponential"],
    domain_image: InputPathType,
    output_field: str,
    number_of_random_points: int | None = None,
    standard_deviation_displacement_field: float | None = None,
    enforce_stationary_boundary: int | None = None,
    displacement_specific_options: typing.Union[SimulateDisplacementFieldBsplineOptionsParamsDictTagged, SimulateDisplacementFieldExponentialOptionsParamsDictTagged] | None = None,
) -> SimulateDisplacementFieldParamsDictTagged:
    """
    Build parameters.
    
    Args:
        image_dimension: Dimensionality of the image.
        displacement_field_type: Type of displacement field to simulate.
        domain_image: Image defining the domain for the displacement field.
        output_field: Path to save the output displacement field.
        number_of_random_points: Number of random points to use in the\
            simulation.
        standard_deviation_displacement_field: Standard deviation for the\
            displacement field.
        enforce_stationary_boundary: Boolean flag indicating whether to enforce\
            stationary boundary.
        displacement_specific_options: Options specific to the type of\
            displacement field simulation.
    Returns:
        Parameter dictionary
    """
    params = {
        "@type": "ants/SimulateDisplacementField",
        "image_dimension": image_dimension,
        "displacement_field_type": displacement_field_type,
        "domain_image": domain_image,
        "output_field": output_field,
    }
    if number_of_random_points is not None:
        params["number_of_random_points"] = number_of_random_points
    if standard_deviation_displacement_field is not None:
        params["standard_deviation_displacement_field"] = standard_deviation_displacement_field
    if enforce_stationary_boundary is not None:
        params["enforce_stationary_boundary"] = enforce_stationary_boundary
    if displacement_specific_options is not None:
        params["displacement_specific_options"] = displacement_specific_options
    return params


def simulate_displacement_field_validate(
    params: typing.Any,
) -> None:
    """
    Validate parameters. Throws an error if `params` is not a valid
    `SimulateDisplacementFieldParamsDict` 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("image_dimension", None) is None:
        raise StyxValidationError("`image_dimension` must not be None")
    if not isinstance(params["image_dimension"], int):
        raise StyxValidationError(f'`image_dimension` has the wrong type: Received `{type(params.get("image_dimension", None))}` expected `int`')
    if params.get("displacement_field_type", None) is None:
        raise StyxValidationError("`displacement_field_type` must not be None")
    if not isinstance(params["displacement_field_type"], str):
        raise StyxValidationError(f'`displacement_field_type` has the wrong type: Received `{type(params.get("displacement_field_type", None))}` expected `typing.Literal["BSpline", "Exponential"]`')
    if params["displacement_field_type"] not in ["BSpline", "Exponential"]:
        raise StyxValidationError("Parameter `displacement_field_type` must be one of [\"BSpline\", \"Exponential\"]")
    if params.get("domain_image", None) is None:
        raise StyxValidationError("`domain_image` must not be None")
    if not isinstance(params["domain_image"], (pathlib.Path, str)):
        raise StyxValidationError(f'`domain_image` has the wrong type: Received `{type(params.get("domain_image", None))}` expected `InputPathType`')
    if params.get("output_field", None) is None:
        raise StyxValidationError("`output_field` must not be None")
    if not isinstance(params["output_field"], str):
        raise StyxValidationError(f'`output_field` has the wrong type: Received `{type(params.get("output_field", None))}` expected `str`')
    if params.get("number_of_random_points", None) is not None:
        if not isinstance(params["number_of_random_points"], int):
            raise StyxValidationError(f'`number_of_random_points` has the wrong type: Received `{type(params.get("number_of_random_points", None))}` expected `int | None`')
    if params.get("standard_deviation_displacement_field", None) is not None:
        if not isinstance(params["standard_deviation_displacement_field"], (float, int)):
            raise StyxValidationError(f'`standard_deviation_displacement_field` has the wrong type: Received `{type(params.get("standard_deviation_displacement_field", None))}` expected `float | None`')
    if params.get("enforce_stationary_boundary", None) is not None:
        if not isinstance(params["enforce_stationary_boundary"], int):
            raise StyxValidationError(f'`enforce_stationary_boundary` has the wrong type: Received `{type(params.get("enforce_stationary_boundary", None))}` expected `int | None`')
    if params.get("displacement_specific_options", None) is not None:
        if not isinstance(params["displacement_specific_options"], dict):
            raise StyxValidationError(f'Params object has the wrong type \'{type(params["displacement_specific_options"])}\'')
        if "@type" not in params["displacement_specific_options"]:
            raise StyxValidationError("Params object is missing `@type`")
        if params["displacement_specific_options"]["@type"] not in ["bspline_options", "exponential_options"]:
            raise StyxValidationError("Parameter `displacement_specific_options`s `@type` must be one of [\"bspline_options\", \"exponential_options\"]")
        simulate_displacement_field_displacement_specific_options_validate_dyn_fn(params["displacement_specific_options"]["@type"])(params["displacement_specific_options"])


def simulate_displacement_field_cargs(
    params: SimulateDisplacementFieldParamsDict,
    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.append("SimulateDisplacementField")
    cargs.append(str(params.get("image_dimension", None)))
    cargs.append(params.get("displacement_field_type", None))
    cargs.append(execution.input_file(params.get("domain_image", None)))
    cargs.append(params.get("output_field", None))
    if params.get("number_of_random_points", None) is not None:
        cargs.append(str(params.get("number_of_random_points", None)))
    if params.get("standard_deviation_displacement_field", None) is not None:
        cargs.append(str(params.get("standard_deviation_displacement_field", None)))
    if params.get("enforce_stationary_boundary", None) is not None:
        cargs.append(str(params.get("enforce_stationary_boundary", None)))
    if params.get("displacement_specific_options", None) is not None:
        cargs.extend(simulate_displacement_field_displacement_specific_options_cargs_dyn_fn(params.get("displacement_specific_options", None)["@type"])(params.get("displacement_specific_options", None), execution))
    return cargs


def simulate_displacement_field_outputs(
    params: SimulateDisplacementFieldParamsDict,
    execution: Execution,
) -> SimulateDisplacementFieldOutputs:
    """
    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 = SimulateDisplacementFieldOutputs(
        root=execution.output_file("."),
        output_displacement_field=execution.output_file(params.get("output_field", None)),
    )
    return ret


def simulate_displacement_field_execute(
    params: SimulateDisplacementFieldParamsDict,
    runner: Runner | None = None,
) -> SimulateDisplacementFieldOutputs:
    """
    SimulateDisplacementField
    
    Simulate displacement fields using various methods such as BSpline or
    Exponential.
    
    Author: ANTs Developers
    
    URL: https://github.com/ANTsX/ANTs
    
    Args:
        params: The parameters.
        runner: Command runner.
    Returns:
        NamedTuple of outputs (described in `SimulateDisplacementFieldOutputs`).
    """
    simulate_displacement_field_validate(params)
    runner = runner or get_global_runner()
    execution = runner.start_execution(SIMULATE_DISPLACEMENT_FIELD_METADATA)
    params = execution.params(params)
    cargs = simulate_displacement_field_cargs(params, execution)
    ret = simulate_displacement_field_outputs(params, execution)
    execution.run(cargs)
    return ret


def simulate_displacement_field(
    image_dimension: int,
    displacement_field_type: typing.Literal["BSpline", "Exponential"],
    domain_image: InputPathType,
    output_field: str,
    number_of_random_points: int | None = None,
    standard_deviation_displacement_field: float | None = None,
    enforce_stationary_boundary: int | None = None,
    displacement_specific_options: typing.Union[SimulateDisplacementFieldBsplineOptionsParamsDictTagged, SimulateDisplacementFieldExponentialOptionsParamsDictTagged] | None = None,
    runner: Runner | None = None,
) -> SimulateDisplacementFieldOutputs:
    """
    SimulateDisplacementField
    
    Simulate displacement fields using various methods such as BSpline or
    Exponential.
    
    Author: ANTs Developers
    
    URL: https://github.com/ANTsX/ANTs
    
    Args:
        image_dimension: Dimensionality of the image.
        displacement_field_type: Type of displacement field to simulate.
        domain_image: Image defining the domain for the displacement field.
        output_field: Path to save the output displacement field.
        number_of_random_points: Number of random points to use in the\
            simulation.
        standard_deviation_displacement_field: Standard deviation for the\
            displacement field.
        enforce_stationary_boundary: Boolean flag indicating whether to enforce\
            stationary boundary.
        displacement_specific_options: Options specific to the type of\
            displacement field simulation.
        runner: Command runner.
    Returns:
        NamedTuple of outputs (described in `SimulateDisplacementFieldOutputs`).
    """
    params = simulate_displacement_field_params(
        image_dimension=image_dimension,
        displacement_field_type=displacement_field_type,
        domain_image=domain_image,
        output_field=output_field,
        number_of_random_points=number_of_random_points,
        standard_deviation_displacement_field=standard_deviation_displacement_field,
        enforce_stationary_boundary=enforce_stationary_boundary,
        displacement_specific_options=displacement_specific_options,
    )
    return simulate_displacement_field_execute(params, runner)


__all__ = [
    "SIMULATE_DISPLACEMENT_FIELD_METADATA",
    "SimulateDisplacementFieldBsplineOptionsParamsDict",
    "SimulateDisplacementFieldBsplineOptionsParamsDictTagged",
    "SimulateDisplacementFieldExponentialOptionsParamsDict",
    "SimulateDisplacementFieldExponentialOptionsParamsDictTagged",
    "SimulateDisplacementFieldOutputs",
    "SimulateDisplacementFieldParamsDict",
    "SimulateDisplacementFieldParamsDictTagged",
    "simulate_displacement_field",
    "simulate_displacement_field_bspline_options",
    "simulate_displacement_field_execute",
    "simulate_displacement_field_exponential_options",
    "simulate_displacement_field_params",
]
