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

import typing
import pathlib
from styxdefs import *

DENOISE_IMAGE_METADATA = Metadata(
    id="dd9cbbb4389367b37aac087edf973dfbcbdeb4d3.boutiques",
    name="DenoiseImage",
    package="ants",
    container_image_tag="antsx/ants:v2.5.3",
)


_DenoiseImageCorrectedOutputParamsDictNoTag = typing.TypedDict('_DenoiseImageCorrectedOutputParamsDictNoTag', {
    "correctedOutputFileName": str,
})
DenoiseImageCorrectedOutputParamsDictTagged = typing.TypedDict('DenoiseImageCorrectedOutputParamsDictTagged', {
    "@type": typing.Literal["correctedOutput"],
    "correctedOutputFileName": str,
})
DenoiseImageCorrectedOutputParamsDict = _DenoiseImageCorrectedOutputParamsDictNoTag | DenoiseImageCorrectedOutputParamsDictTagged


_DenoiseImageCorrectedOutputNoiseParamsDictNoTag = typing.TypedDict('_DenoiseImageCorrectedOutputNoiseParamsDictNoTag', {
    "correctedOutputFileName": str,
    "noiseFile": typing.NotRequired[str | None],
})
DenoiseImageCorrectedOutputNoiseParamsDictTagged = typing.TypedDict('DenoiseImageCorrectedOutputNoiseParamsDictTagged', {
    "@type": typing.Literal["correctedOutputNoise"],
    "correctedOutputFileName": str,
    "noiseFile": typing.NotRequired[str | None],
})
DenoiseImageCorrectedOutputNoiseParamsDict = _DenoiseImageCorrectedOutputNoiseParamsDictNoTag | DenoiseImageCorrectedOutputNoiseParamsDictTagged


_DenoiseImageParamsDictNoTag = typing.TypedDict('_DenoiseImageParamsDictNoTag', {
    "image_dimensionality": typing.NotRequired[typing.Literal[2, 3, 4] | None],
    "noise_model": typing.NotRequired[typing.Literal["Gaussian", "Rician"] | None],
    "shrink_factor": typing.NotRequired[int | None],
    "mask_image": typing.NotRequired[InputPathType | None],
    "patch_radius": typing.NotRequired[str | None],
    "search_radius": typing.NotRequired[str | None],
    "verbose": typing.NotRequired[bool | None],
    "input_image": InputPathType,
    "output": typing.Union[DenoiseImageCorrectedOutputParamsDictTagged, DenoiseImageCorrectedOutputNoiseParamsDictTagged],
})
DenoiseImageParamsDictTagged = typing.TypedDict('DenoiseImageParamsDictTagged', {
    "@type": typing.Literal["ants/DenoiseImage"],
    "image_dimensionality": typing.NotRequired[typing.Literal[2, 3, 4] | None],
    "noise_model": typing.NotRequired[typing.Literal["Gaussian", "Rician"] | None],
    "shrink_factor": typing.NotRequired[int | None],
    "mask_image": typing.NotRequired[InputPathType | None],
    "patch_radius": typing.NotRequired[str | None],
    "search_radius": typing.NotRequired[str | None],
    "verbose": typing.NotRequired[bool | None],
    "input_image": InputPathType,
    "output": typing.Union[DenoiseImageCorrectedOutputParamsDictTagged, DenoiseImageCorrectedOutputNoiseParamsDictTagged],
})
DenoiseImageParamsDict = _DenoiseImageParamsDictNoTag | DenoiseImageParamsDictTagged


def denoise_image_output_cargs_dyn_fn(
    t: str,
) -> typing.Any:
    """
    Get build cargs function by command type.
    
    Args:
        t: Command type.
    Returns:
        Build cargs function.
    """
    return {
        "correctedOutput": denoise_image_corrected_output_cargs,
        "correctedOutputNoise": denoise_image_corrected_output_noise_cargs,
    }.get(t)


def denoise_image_output_outputs_dyn_fn(
    t: str,
) -> typing.Any:
    """
    Get build outputs function by command type.
    
    Args:
        t: Command type.
    Returns:
        Build outputs function.
    """
    return {
        "correctedOutput": denoise_image_corrected_output_outputs,
        "correctedOutputNoise": denoise_image_corrected_output_noise_outputs,
    }.get(t)


def denoise_image_output_validate_dyn_fn(
    t: str,
) -> typing.Any:
    """
    Get validate params function by command type.
    
    Args:
        t: Command type.
    Returns:
        Validate params function.
    """
    return {
        "correctedOutput": denoise_image_corrected_output_validate,
        "correctedOutputNoise": denoise_image_corrected_output_noise_validate,
    }.get(t)


class DenoiseImageCorrectedOutputOutputs(typing.NamedTuple):
    """
    Output object returned when calling `DenoiseImageCorrectedOutputParamsDict(...)`.
    """
    root: OutputPathType
    """Output root folder. This is the root folder for all outputs."""
    output_image_outfile: OutputPathType
    """Denoised image."""


def denoise_image_corrected_output(
    corrected_output_file_name: str,
) -> DenoiseImageCorrectedOutputParamsDictTagged:
    """
    Build parameters.
    
    Args:
        corrected_output_file_name: Output file name.
    Returns:
        Parameter dictionary
    """
    params = {
        "@type": "correctedOutput",
        "correctedOutputFileName": corrected_output_file_name,
    }
    return params


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


def denoise_image_corrected_output_cargs(
    params: DenoiseImageCorrectedOutputParamsDict,
    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(params.get("correctedOutputFileName", None))
    return cargs


def denoise_image_corrected_output_outputs(
    params: DenoiseImageCorrectedOutputParamsDict,
    execution: Execution,
) -> DenoiseImageCorrectedOutputOutputs:
    """
    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 = DenoiseImageCorrectedOutputOutputs(
        root=execution.output_file("."),
        output_image_outfile=execution.output_file(params.get("correctedOutputFileName", None)),
    )
    return ret


class DenoiseImageCorrectedOutputNoiseOutputs(typing.NamedTuple):
    """
    Output object returned when calling `DenoiseImageCorrectedOutputNoiseParamsDict(...)`.
    """
    root: OutputPathType
    """Output root folder. This is the root folder for all outputs."""
    output_image_outfile: OutputPathType
    """Denoised output image."""
    output_bias_image: OutputPathType | None
    """Noise map image."""


def denoise_image_corrected_output_noise(
    corrected_output_file_name: str,
    noise_file: str | None = None,
) -> DenoiseImageCorrectedOutputNoiseParamsDictTagged:
    """
    Build parameters.
    
    Args:
        corrected_output_file_name: Output file name.
        noise_file: Output noise map image.
    Returns:
        Parameter dictionary
    """
    params = {
        "@type": "correctedOutputNoise",
        "correctedOutputFileName": corrected_output_file_name,
    }
    if noise_file is not None:
        params["noiseFile"] = noise_file
    return params


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


def denoise_image_corrected_output_noise_cargs(
    params: DenoiseImageCorrectedOutputNoiseParamsDict,
    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("[" + params.get("correctedOutputFileName", None) + "," + (params.get("noiseFile", None) if (params.get("noiseFile", None) is not None) else "") + "]")
    return cargs


def denoise_image_corrected_output_noise_outputs(
    params: DenoiseImageCorrectedOutputNoiseParamsDict,
    execution: Execution,
) -> DenoiseImageCorrectedOutputNoiseOutputs:
    """
    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 = DenoiseImageCorrectedOutputNoiseOutputs(
        root=execution.output_file("."),
        output_image_outfile=execution.output_file(params.get("correctedOutputFileName", None)),
        output_bias_image=execution.output_file(params.get("noiseFile", None)) if (params.get("noiseFile") is not None) else None,
    )
    return ret


class DenoiseImageOutputs(typing.NamedTuple):
    """
    Output object returned when calling `DenoiseImageParamsDict(...)`.
    """
    root: OutputPathType
    """Output root folder. This is the root folder for all outputs."""
    output: typing.Union[DenoiseImageCorrectedOutputOutputs, DenoiseImageCorrectedOutputNoiseOutputs]
    """Outputs from `DenoiseImageCorrectedOutputParamsDict` or
    `DenoiseImageCorrectedOutputNoiseParamsDict`."""


def denoise_image_params(
    input_image: InputPathType,
    output: typing.Union[DenoiseImageCorrectedOutputParamsDictTagged, DenoiseImageCorrectedOutputNoiseParamsDictTagged],
    image_dimensionality: typing.Literal[2, 3, 4] | None = None,
    noise_model: typing.Literal["Gaussian", "Rician"] | None = None,
    shrink_factor: int | None = None,
    mask_image: InputPathType | None = None,
    patch_radius: str | None = None,
    search_radius: str | None = None,
    verbose: bool | None = None,
) -> DenoiseImageParamsDictTagged:
    """
    Build parameters.
    
    Args:
        input_image: -i, --input-image inputImageFilename. A scalar image is\
            expected as input for noise correction.
        output: The denoised version of the input image, with optional noise\
            map image.
        image_dimensionality: -d, --image-dimensionality 2/3/4. This option\
            forces the image to be treated as a specified-dimensional image. If not\
            specified, the program tries to infer the dimensionality from the input\
            image.
        noise_model: -n, --noise-model Rician/(Gaussian). Employ a Rician or\
            Gaussian noise model.
        shrink_factor: -s, --shrink-factor (1)/2/3/... Running noise correction\
            on large images can be time consuming. To lessen computation time, the\
            input image can be resampled. The shrink factor, specified as a single\
            integer, describes this resampling. Shrink factor = 1 is the default.
        mask_image: -x, --mask-image maskImageFilename. If a mask image is\
            specified, denoising is only performed in the mask region.
        patch_radius: -p, --patch-radius 1x1x1. Patch radius. Default is 1x1x1.
        search_radius: -r, --search-radius 2x2x2. Search radius. Default is\
            2x2x2.
        verbose: Verbose output.
    Returns:
        Parameter dictionary
    """
    params = {
        "@type": "ants/DenoiseImage",
        "input_image": input_image,
        "output": output,
    }
    if image_dimensionality is not None:
        params["image_dimensionality"] = image_dimensionality
    if noise_model is not None:
        params["noise_model"] = noise_model
    if shrink_factor is not None:
        params["shrink_factor"] = shrink_factor
    if mask_image is not None:
        params["mask_image"] = mask_image
    if patch_radius is not None:
        params["patch_radius"] = patch_radius
    if search_radius is not None:
        params["search_radius"] = search_radius
    if verbose is not None:
        params["verbose"] = verbose
    return params


def denoise_image_validate(
    params: typing.Any,
) -> None:
    """
    Validate parameters. Throws an error if `params` is not a valid
    `DenoiseImageParamsDict` 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("noise_model", None) is not None:
        if not isinstance(params["noise_model"], str):
            raise StyxValidationError(f'`noise_model` has the wrong type: Received `{type(params.get("noise_model", None))}` expected `typing.Literal["Gaussian", "Rician"] | None`')
        if params["noise_model"] not in ["Gaussian", "Rician"]:
            raise StyxValidationError("Parameter `noise_model` must be one of [\"Gaussian\", \"Rician\"]")
    if params.get("shrink_factor", None) is not None:
        if not isinstance(params["shrink_factor"], int):
            raise StyxValidationError(f'`shrink_factor` has the wrong type: Received `{type(params.get("shrink_factor", None))}` expected `int | None`')
    if params.get("mask_image", None) is not 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 | None`')
    if params.get("patch_radius", None) is not None:
        if not isinstance(params["patch_radius"], str):
            raise StyxValidationError(f'`patch_radius` has the wrong type: Received `{type(params.get("patch_radius", None))}` expected `str | None`')
    if params.get("search_radius", None) is not None:
        if not isinstance(params["search_radius"], str):
            raise StyxValidationError(f'`search_radius` has the wrong type: Received `{type(params.get("search_radius", 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`')
    if params.get("input_image", None) is None:
        raise StyxValidationError("`input_image` must not be None")
    if not isinstance(params["input_image"], (pathlib.Path, str)):
        raise StyxValidationError(f'`input_image` has the wrong type: Received `{type(params.get("input_image", None))}` expected `InputPathType`')
    if params.get("output", None) is None:
        raise StyxValidationError("`output` must not be None")
    if not isinstance(params["output"], dict):
        raise StyxValidationError(f'Params object has the wrong type \'{type(params["output"])}\'')
    if "@type" not in params["output"]:
        raise StyxValidationError("Params object is missing `@type`")
    if params["output"]["@type"] not in ["correctedOutput", "correctedOutputNoise"]:
        raise StyxValidationError("Parameter `output`s `@type` must be one of [\"correctedOutput\", \"correctedOutputNoise\"]")
    denoise_image_output_validate_dyn_fn(params["output"]["@type"])(params["output"])


def denoise_image_cargs(
    params: DenoiseImageParamsDict,
    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("DenoiseImage")
    if params.get("image_dimensionality", None) is not None:
        cargs.extend([
            "--image-dimensionality",
            str(params.get("image_dimensionality", None))
        ])
    if params.get("noise_model", None) is not None:
        cargs.extend([
            "--noise-model",
            params.get("noise_model", None)
        ])
    if params.get("shrink_factor", None) is not None:
        cargs.extend([
            "--shrink-factor",
            str(params.get("shrink_factor", None))
        ])
    if params.get("mask_image", None) is not None:
        cargs.extend([
            "--mask-image",
            execution.input_file(params.get("mask_image", None))
        ])
    if params.get("patch_radius", None) is not None:
        cargs.extend([
            "--patch-radius",
            params.get("patch_radius", None)
        ])
    if params.get("search_radius", None) is not None:
        cargs.extend([
            "--search-radius",
            params.get("search_radius", None)
        ])
    if params.get("verbose", None) is not None:
        cargs.extend([
            "--verbose",
            ("1" if params.get("verbose", None) else "0")
        ])
    cargs.extend([
        "--input-image",
        execution.input_file(params.get("input_image", None))
    ])
    cargs.extend([
        "--output",
        *denoise_image_output_cargs_dyn_fn(params.get("output", None)["@type"])(params.get("output", None), execution)
    ])
    return cargs


def denoise_image_outputs(
    params: DenoiseImageParamsDict,
    execution: Execution,
) -> DenoiseImageOutputs:
    """
    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 = DenoiseImageOutputs(
        root=execution.output_file("."),
        output=denoise_image_output_outputs_dyn_fn(params.get("output")["@type"])(params.get("output"), execution),
    )
    return ret


def denoise_image_execute(
    params: DenoiseImageParamsDict,
    runner: Runner | None = None,
) -> DenoiseImageOutputs:
    """
    DenoiseImage
    
    Denoise an image using a spatially adaptive filter originally described in
    J. V. Manjon, P. Coupe, Luis Marti-Bonmati, D. L. Collins, and M. Robles.
    Adaptive Non-Local Means Denoising of MR Images With Spatially Varying Noise
    Levels, Journal of Magnetic Resonance Imaging, 31:192-203, June 2010.
    
    Author: ANTs Developers
    
    URL: https://github.com/ANTsX/ANTs
    
    Args:
        params: The parameters.
        runner: Command runner.
    Returns:
        NamedTuple of outputs (described in `DenoiseImageOutputs`).
    """
    denoise_image_validate(params)
    runner = runner or get_global_runner()
    execution = runner.start_execution(DENOISE_IMAGE_METADATA)
    params = execution.params(params)
    cargs = denoise_image_cargs(params, execution)
    ret = denoise_image_outputs(params, execution)
    execution.run(cargs)
    return ret


def denoise_image(
    input_image: InputPathType,
    output: typing.Union[DenoiseImageCorrectedOutputParamsDictTagged, DenoiseImageCorrectedOutputNoiseParamsDictTagged],
    image_dimensionality: typing.Literal[2, 3, 4] | None = None,
    noise_model: typing.Literal["Gaussian", "Rician"] | None = None,
    shrink_factor: int | None = None,
    mask_image: InputPathType | None = None,
    patch_radius: str | None = None,
    search_radius: str | None = None,
    verbose: bool | None = None,
    runner: Runner | None = None,
) -> DenoiseImageOutputs:
    """
    DenoiseImage
    
    Denoise an image using a spatially adaptive filter originally described in
    J. V. Manjon, P. Coupe, Luis Marti-Bonmati, D. L. Collins, and M. Robles.
    Adaptive Non-Local Means Denoising of MR Images With Spatially Varying Noise
    Levels, Journal of Magnetic Resonance Imaging, 31:192-203, June 2010.
    
    Author: ANTs Developers
    
    URL: https://github.com/ANTsX/ANTs
    
    Args:
        input_image: -i, --input-image inputImageFilename. A scalar image is\
            expected as input for noise correction.
        output: The denoised version of the input image, with optional noise\
            map image.
        image_dimensionality: -d, --image-dimensionality 2/3/4. This option\
            forces the image to be treated as a specified-dimensional image. If not\
            specified, the program tries to infer the dimensionality from the input\
            image.
        noise_model: -n, --noise-model Rician/(Gaussian). Employ a Rician or\
            Gaussian noise model.
        shrink_factor: -s, --shrink-factor (1)/2/3/... Running noise correction\
            on large images can be time consuming. To lessen computation time, the\
            input image can be resampled. The shrink factor, specified as a single\
            integer, describes this resampling. Shrink factor = 1 is the default.
        mask_image: -x, --mask-image maskImageFilename. If a mask image is\
            specified, denoising is only performed in the mask region.
        patch_radius: -p, --patch-radius 1x1x1. Patch radius. Default is 1x1x1.
        search_radius: -r, --search-radius 2x2x2. Search radius. Default is\
            2x2x2.
        verbose: Verbose output.
        runner: Command runner.
    Returns:
        NamedTuple of outputs (described in `DenoiseImageOutputs`).
    """
    params = denoise_image_params(
        image_dimensionality=image_dimensionality,
        noise_model=noise_model,
        shrink_factor=shrink_factor,
        mask_image=mask_image,
        patch_radius=patch_radius,
        search_radius=search_radius,
        verbose=verbose,
        input_image=input_image,
        output=output,
    )
    return denoise_image_execute(params, runner)


__all__ = [
    "DENOISE_IMAGE_METADATA",
    "DenoiseImageCorrectedOutputNoiseOutputs",
    "DenoiseImageCorrectedOutputNoiseParamsDict",
    "DenoiseImageCorrectedOutputNoiseParamsDictTagged",
    "DenoiseImageCorrectedOutputOutputs",
    "DenoiseImageCorrectedOutputParamsDict",
    "DenoiseImageCorrectedOutputParamsDictTagged",
    "DenoiseImageOutputs",
    "DenoiseImageParamsDict",
    "DenoiseImageParamsDictTagged",
    "denoise_image",
    "denoise_image_corrected_output",
    "denoise_image_corrected_output_noise",
    "denoise_image_execute",
    "denoise_image_params",
]
