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

import typing
import pathlib
from styxdefs import *

ATROPOS_METADATA = Metadata(
    id="6436edca90da7aa4163ae647bc1238ae647dd4fd.boutiques",
    name="Atropos",
    package="ants",
    container_image_tag="antsx/ants:v2.5.3",
)


_AtroposParamsDictNoTag = typing.TypedDict('_AtroposParamsDictNoTag', {
    "image_dimensionality": typing.NotRequired[typing.Literal[2, 3, 4] | None],
    "intensity_image": str,
    "bspline": typing.NotRequired[str | None],
    "initialization": str,
    "partial_volume_label_set": typing.NotRequired[str | None],
    "use_partial_volume_likelihoods": typing.NotRequired[bool | None],
    "posterior_formulation": typing.NotRequired[str | None],
    "mask_image": InputPathType,
    "convergence": str,
    "likelihood_model": str,
    "mrf": typing.NotRequired[str | None],
    "icm": typing.NotRequired[str | None],
    "use_random_seed": typing.NotRequired[bool | None],
    "output": str,
    "minimize_memory_usage": typing.NotRequired[bool | None],
    "winsorize_outliers": typing.NotRequired[str | None],
    "use_euclidean_distance": typing.NotRequired[bool | None],
    "label_propagation": typing.NotRequired[str | None],
    "verbose": typing.NotRequired[bool | None],
})
AtroposParamsDictTagged = typing.TypedDict('AtroposParamsDictTagged', {
    "@type": typing.Literal["ants/Atropos"],
    "image_dimensionality": typing.NotRequired[typing.Literal[2, 3, 4] | None],
    "intensity_image": str,
    "bspline": typing.NotRequired[str | None],
    "initialization": str,
    "partial_volume_label_set": typing.NotRequired[str | None],
    "use_partial_volume_likelihoods": typing.NotRequired[bool | None],
    "posterior_formulation": typing.NotRequired[str | None],
    "mask_image": InputPathType,
    "convergence": str,
    "likelihood_model": str,
    "mrf": typing.NotRequired[str | None],
    "icm": typing.NotRequired[str | None],
    "use_random_seed": typing.NotRequired[bool | None],
    "output": str,
    "minimize_memory_usage": typing.NotRequired[bool | None],
    "winsorize_outliers": typing.NotRequired[str | None],
    "use_euclidean_distance": typing.NotRequired[bool | None],
    "label_propagation": typing.NotRequired[str | None],
    "verbose": typing.NotRequired[bool | None],
})
AtroposParamsDict = _AtroposParamsDictNoTag | AtroposParamsDictTagged


class AtroposOutputs(typing.NamedTuple):
    """
    Output object returned when calling `AtroposParamsDict(...)`.
    """
    root: OutputPathType
    """Output root folder. This is the root folder for all outputs."""
    classified_image: OutputPathType
    """The output labeled image with assigned labels for each voxel in the
    masked region."""
    posterior_probability_images: OutputPathType
    """Output posterior probability images in specified format."""


def atropos_params(
    intensity_image: str,
    initialization: str,
    mask_image: InputPathType,
    convergence: str,
    likelihood_model: str,
    output: str,
    image_dimensionality: typing.Literal[2, 3, 4] | None = None,
    bspline: str | None = None,
    partial_volume_label_set: str | None = None,
    use_partial_volume_likelihoods: bool | None = None,
    posterior_formulation: str | None = None,
    mrf: str | None = None,
    icm: str | None = None,
    use_random_seed: bool | None = None,
    minimize_memory_usage: bool | None = None,
    winsorize_outliers: str | None = None,
    use_euclidean_distance: bool | None = None,
    label_propagation: str | None = None,
    verbose: bool | None = None,
) -> AtroposParamsDictTagged:
    """
    Build parameters.
    
    Args:
        intensity_image: One or more scalar images is specified for\
            segmentation. For scenarios with no prior information, the first scalar\
            image is used to order labelings by intensity. The optional adaptive\
            smoothing weight is applicable with prior images, specified between\
            [0,1].
        initialization: Initialize the FMM parameters. options include Random,\
            Otsu, KMeans, PriorProbabilityImages, and PriorLabelImage.
        mask_image: The required image mask defines the region to be labeled by\
            Atropos.
        convergence: Determine convergence based on mean maximum posterior\
            probability over region of interest.
        likelihood_model: Specify parametric or non-parametric likelihood\
            model. Options include Gaussian, HistogramParzenWindows,\
            ManifoldParzenWindows, among others.
        output: Output labeled image and optionally posterior probability\
            images.
        image_dimensionality: This option forces the image to be treated as a\
            specified-dimensional image. If not specified, Atropos tries to infer\
            the dimensionality from the first input image.
        bspline: Parameters for B-Spline. Adaptive smoothing is applied to\
            intensity images if smoothing weights > 0.
        partial_volume_label_set: Model mixtures of classes within single\
            voxels. Specify labels for each partial volume class.
        use_partial_volume_likelihoods: Whether to use partial volume\
            likelihoods. A value of 1 considers the partial volume class separate\
            from tissue classes.
        posterior_formulation: Specify posterior probability formulation.\
            Options are Socrates, Plato, Aristotle, or Sigmoid.
        mrf: Markov Random Field parameters to enforce spatial constraints on\
            segmentation.
        icm: ICM (Iterated Conditional Modes) parameters for asynchronous\
            updating.
        use_random_seed: Initialize with a random seed or a constant seed\
            number.
        minimize_memory_usage: Minimize memory usage by calculating images on\
            the fly and storing only non-negligible pixel values.
        winsorize_outliers: Options to remove effects of outliers in\
            calculations using methods like BoxPlot or GrubbsRosner.
        use_euclidean_distance: Propagate labels throughout the mask using a\
            distance transform.
        label_propagation: Control propagation of each prior label by specified\
            lambda and boundary probability.
        verbose: Verbose output.
    Returns:
        Parameter dictionary
    """
    params = {
        "@type": "ants/Atropos",
        "intensity_image": intensity_image,
        "initialization": initialization,
        "mask_image": mask_image,
        "convergence": convergence,
        "likelihood_model": likelihood_model,
        "output": output,
    }
    if image_dimensionality is not None:
        params["image_dimensionality"] = image_dimensionality
    if bspline is not None:
        params["bspline"] = bspline
    if partial_volume_label_set is not None:
        params["partial_volume_label_set"] = partial_volume_label_set
    if use_partial_volume_likelihoods is not None:
        params["use_partial_volume_likelihoods"] = use_partial_volume_likelihoods
    if posterior_formulation is not None:
        params["posterior_formulation"] = posterior_formulation
    if mrf is not None:
        params["mrf"] = mrf
    if icm is not None:
        params["icm"] = icm
    if use_random_seed is not None:
        params["use_random_seed"] = use_random_seed
    if minimize_memory_usage is not None:
        params["minimize_memory_usage"] = minimize_memory_usage
    if winsorize_outliers is not None:
        params["winsorize_outliers"] = winsorize_outliers
    if use_euclidean_distance is not None:
        params["use_euclidean_distance"] = use_euclidean_distance
    if label_propagation is not None:
        params["label_propagation"] = label_propagation
    if verbose is not None:
        params["verbose"] = verbose
    return params


def atropos_validate(
    params: typing.Any,
) -> None:
    """
    Validate parameters. Throws an error if `params` is not a valid
    `AtroposParamsDict` 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_dimensionality", None) is not None:
        if not isinstance(params["image_dimensionality"], int):
            raise StyxValidationError(f'`image_dimensionality` has the wrong type: Received `{type(params.get("image_dimensionality", None))}` expected `typing.Literal[2, 3, 4] | None`')
        if params["image_dimensionality"] not in [2, 3, 4]:
            raise StyxValidationError("Parameter `image_dimensionality` must be one of [2, 3, 4]")
    if params.get("intensity_image", None) is None:
        raise StyxValidationError("`intensity_image` must not be None")
    if not isinstance(params["intensity_image"], str):
        raise StyxValidationError(f'`intensity_image` has the wrong type: Received `{type(params.get("intensity_image", None))}` expected `str`')
    if params.get("bspline", None) is not None:
        if not isinstance(params["bspline"], str):
            raise StyxValidationError(f'`bspline` has the wrong type: Received `{type(params.get("bspline", None))}` expected `str | None`')
    if params.get("initialization", None) is None:
        raise StyxValidationError("`initialization` must not be None")
    if not isinstance(params["initialization"], str):
        raise StyxValidationError(f'`initialization` has the wrong type: Received `{type(params.get("initialization", None))}` expected `str`')
    if params.get("partial_volume_label_set", None) is not None:
        if not isinstance(params["partial_volume_label_set"], str):
            raise StyxValidationError(f'`partial_volume_label_set` has the wrong type: Received `{type(params.get("partial_volume_label_set", None))}` expected `str | None`')
    if params.get("use_partial_volume_likelihoods", None) is not None:
        if not isinstance(params["use_partial_volume_likelihoods"], bool):
            raise StyxValidationError(f'`use_partial_volume_likelihoods` has the wrong type: Received `{type(params.get("use_partial_volume_likelihoods", None))}` expected `bool | None`')
    if params.get("posterior_formulation", None) is not None:
        if not isinstance(params["posterior_formulation"], str):
            raise StyxValidationError(f'`posterior_formulation` has the wrong type: Received `{type(params.get("posterior_formulation", None))}` expected `str | None`')
    if params.get("mask_image", None) is None:
        raise StyxValidationError("`mask_image` must not be None")
    if not isinstance(params["mask_image"], (pathlib.Path, str)):
        raise StyxValidationError(f'`mask_image` has the wrong type: Received `{type(params.get("mask_image", None))}` expected `InputPathType`')
    if params.get("convergence", None) is None:
        raise StyxValidationError("`convergence` must not be None")
    if not isinstance(params["convergence"], str):
        raise StyxValidationError(f'`convergence` has the wrong type: Received `{type(params.get("convergence", None))}` expected `str`')
    if params.get("likelihood_model", None) is None:
        raise StyxValidationError("`likelihood_model` must not be None")
    if not isinstance(params["likelihood_model"], str):
        raise StyxValidationError(f'`likelihood_model` has the wrong type: Received `{type(params.get("likelihood_model", None))}` expected `str`')
    if params.get("mrf", None) is not None:
        if not isinstance(params["mrf"], str):
            raise StyxValidationError(f'`mrf` has the wrong type: Received `{type(params.get("mrf", None))}` expected `str | None`')
    if params.get("icm", None) is not None:
        if not isinstance(params["icm"], str):
            raise StyxValidationError(f'`icm` has the wrong type: Received `{type(params.get("icm", None))}` expected `str | None`')
    if params.get("use_random_seed", None) is not None:
        if not isinstance(params["use_random_seed"], bool):
            raise StyxValidationError(f'`use_random_seed` has the wrong type: Received `{type(params.get("use_random_seed", None))}` expected `bool | None`')
    if params.get("output", None) is None:
        raise StyxValidationError("`output` must not be None")
    if not isinstance(params["output"], str):
        raise StyxValidationError(f'`output` has the wrong type: Received `{type(params.get("output", None))}` expected `str`')
    if params.get("minimize_memory_usage", None) is not None:
        if not isinstance(params["minimize_memory_usage"], bool):
            raise StyxValidationError(f'`minimize_memory_usage` has the wrong type: Received `{type(params.get("minimize_memory_usage", None))}` expected `bool | None`')
    if params.get("winsorize_outliers", None) is not None:
        if not isinstance(params["winsorize_outliers"], str):
            raise StyxValidationError(f'`winsorize_outliers` has the wrong type: Received `{type(params.get("winsorize_outliers", None))}` expected `str | None`')
    if params.get("use_euclidean_distance", None) is not None:
        if not isinstance(params["use_euclidean_distance"], bool):
            raise StyxValidationError(f'`use_euclidean_distance` has the wrong type: Received `{type(params.get("use_euclidean_distance", None))}` expected `bool | None`')
    if params.get("label_propagation", None) is not None:
        if not isinstance(params["label_propagation"], str):
            raise StyxValidationError(f'`label_propagation` has the wrong type: Received `{type(params.get("label_propagation", None))}` expected `str | None`')
    if params.get("verbose", None) is not None:
        if not isinstance(params["verbose"], bool):
            raise StyxValidationError(f'`verbose` has the wrong type: Received `{type(params.get("verbose", None))}` expected `bool | None`')


def atropos_cargs(
    params: AtroposParamsDict,
    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("Atropos")
    if params.get("image_dimensionality", None) is not None:
        cargs.extend([
            "--image-dimensionality",
            str(params.get("image_dimensionality", None))
        ])
    cargs.extend([
        "-a",
        params.get("intensity_image", None)
    ])
    if params.get("bspline", None) is not None:
        cargs.extend([
            "-b",
            params.get("bspline", None)
        ])
    cargs.extend([
        "-i",
        params.get("initialization", None)
    ])
    if params.get("partial_volume_label_set", None) is not None:
        cargs.extend([
            "-s",
            params.get("partial_volume_label_set", None)
        ])
    if params.get("use_partial_volume_likelihoods", None) is not None:
        cargs.extend([
            "--use-partial-volume-likelihoods",
            ("1" if params.get("use_partial_volume_likelihoods", None) else "0")
        ])
    if params.get("posterior_formulation", None) is not None:
        cargs.extend([
            "-p",
            params.get("posterior_formulation", None)
        ])
    cargs.extend([
        "-x",
        execution.input_file(params.get("mask_image", None))
    ])
    cargs.extend([
        "-c",
        params.get("convergence", None)
    ])
    cargs.extend([
        "-k",
        params.get("likelihood_model", None)
    ])
    if params.get("mrf", None) is not None:
        cargs.extend([
            "-m",
            params.get("mrf", None)
        ])
    if params.get("icm", None) is not None:
        cargs.extend([
            "-g",
            params.get("icm", None)
        ])
    if params.get("use_random_seed", None) is not None:
        cargs.extend([
            "-r",
            ("1" if params.get("use_random_seed", None) else "0")
        ])
    cargs.extend([
        "-o",
        params.get("output", None)
    ])
    if params.get("minimize_memory_usage", None) is not None:
        cargs.extend([
            "-u",
            ("1" if params.get("minimize_memory_usage", None) else "0")
        ])
    if params.get("winsorize_outliers", None) is not None:
        cargs.extend([
            "-w",
            params.get("winsorize_outliers", None)
        ])
    if params.get("use_euclidean_distance", None) is not None:
        cargs.extend([
            "-e",
            ("1" if params.get("use_euclidean_distance", None) else "0")
        ])
    if params.get("label_propagation", None) is not None:
        cargs.extend([
            "-l",
            params.get("label_propagation", None)
        ])
    if params.get("verbose", None) is not None:
        cargs.extend([
            "-v",
            ("1" if params.get("verbose", None) else "0")
        ])
    return cargs


def atropos_outputs(
    params: AtroposParamsDict,
    execution: Execution,
) -> AtroposOutputs:
    """
    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 = AtroposOutputs(
        root=execution.output_file("."),
        classified_image=execution.output_file(params.get("output", None) + "_classified.nii.gz"),
        posterior_probability_images=execution.output_file("[POSTERIOR_PROBABILITY_IMAGE_FILE_NAME_FORMAT]"),
    )
    return ret


def atropos_execute(
    params: AtroposParamsDict,
    runner: Runner | None = None,
) -> AtroposOutputs:
    """
    Atropos
    
    Atropos is a finite mixture modeling (FMM) segmentation approach that allows
    for prior constraints including a prior label image, prior probability
    images, and/or an MRF prior to enforce spatial smoothing of the labels.
    
    Author: ANTs Developers
    
    URL: https://github.com/ANTsX/ANTs
    
    Args:
        params: The parameters.
        runner: Command runner.
    Returns:
        NamedTuple of outputs (described in `AtroposOutputs`).
    """
    atropos_validate(params)
    runner = runner or get_global_runner()
    execution = runner.start_execution(ATROPOS_METADATA)
    params = execution.params(params)
    cargs = atropos_cargs(params, execution)
    ret = atropos_outputs(params, execution)
    execution.run(cargs)
    return ret


def atropos(
    intensity_image: str,
    initialization: str,
    mask_image: InputPathType,
    convergence: str,
    likelihood_model: str,
    output: str,
    image_dimensionality: typing.Literal[2, 3, 4] | None = None,
    bspline: str | None = None,
    partial_volume_label_set: str | None = None,
    use_partial_volume_likelihoods: bool | None = None,
    posterior_formulation: str | None = None,
    mrf: str | None = None,
    icm: str | None = None,
    use_random_seed: bool | None = None,
    minimize_memory_usage: bool | None = None,
    winsorize_outliers: str | None = None,
    use_euclidean_distance: bool | None = None,
    label_propagation: str | None = None,
    verbose: bool | None = None,
    runner: Runner | None = None,
) -> AtroposOutputs:
    """
    Atropos
    
    Atropos is a finite mixture modeling (FMM) segmentation approach that allows
    for prior constraints including a prior label image, prior probability
    images, and/or an MRF prior to enforce spatial smoothing of the labels.
    
    Author: ANTs Developers
    
    URL: https://github.com/ANTsX/ANTs
    
    Args:
        intensity_image: One or more scalar images is specified for\
            segmentation. For scenarios with no prior information, the first scalar\
            image is used to order labelings by intensity. The optional adaptive\
            smoothing weight is applicable with prior images, specified between\
            [0,1].
        initialization: Initialize the FMM parameters. options include Random,\
            Otsu, KMeans, PriorProbabilityImages, and PriorLabelImage.
        mask_image: The required image mask defines the region to be labeled by\
            Atropos.
        convergence: Determine convergence based on mean maximum posterior\
            probability over region of interest.
        likelihood_model: Specify parametric or non-parametric likelihood\
            model. Options include Gaussian, HistogramParzenWindows,\
            ManifoldParzenWindows, among others.
        output: Output labeled image and optionally posterior probability\
            images.
        image_dimensionality: This option forces the image to be treated as a\
            specified-dimensional image. If not specified, Atropos tries to infer\
            the dimensionality from the first input image.
        bspline: Parameters for B-Spline. Adaptive smoothing is applied to\
            intensity images if smoothing weights > 0.
        partial_volume_label_set: Model mixtures of classes within single\
            voxels. Specify labels for each partial volume class.
        use_partial_volume_likelihoods: Whether to use partial volume\
            likelihoods. A value of 1 considers the partial volume class separate\
            from tissue classes.
        posterior_formulation: Specify posterior probability formulation.\
            Options are Socrates, Plato, Aristotle, or Sigmoid.
        mrf: Markov Random Field parameters to enforce spatial constraints on\
            segmentation.
        icm: ICM (Iterated Conditional Modes) parameters for asynchronous\
            updating.
        use_random_seed: Initialize with a random seed or a constant seed\
            number.
        minimize_memory_usage: Minimize memory usage by calculating images on\
            the fly and storing only non-negligible pixel values.
        winsorize_outliers: Options to remove effects of outliers in\
            calculations using methods like BoxPlot or GrubbsRosner.
        use_euclidean_distance: Propagate labels throughout the mask using a\
            distance transform.
        label_propagation: Control propagation of each prior label by specified\
            lambda and boundary probability.
        verbose: Verbose output.
        runner: Command runner.
    Returns:
        NamedTuple of outputs (described in `AtroposOutputs`).
    """
    params = atropos_params(
        image_dimensionality=image_dimensionality,
        intensity_image=intensity_image,
        bspline=bspline,
        initialization=initialization,
        partial_volume_label_set=partial_volume_label_set,
        use_partial_volume_likelihoods=use_partial_volume_likelihoods,
        posterior_formulation=posterior_formulation,
        mask_image=mask_image,
        convergence=convergence,
        likelihood_model=likelihood_model,
        mrf=mrf,
        icm=icm,
        use_random_seed=use_random_seed,
        output=output,
        minimize_memory_usage=minimize_memory_usage,
        winsorize_outliers=winsorize_outliers,
        use_euclidean_distance=use_euclidean_distance,
        label_propagation=label_propagation,
        verbose=verbose,
    )
    return atropos_execute(params, runner)


__all__ = [
    "ATROPOS_METADATA",
    "AtroposOutputs",
    "AtroposParamsDict",
    "AtroposParamsDictTagged",
    "atropos",
    "atropos_execute",
    "atropos_params",
]
