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

import typing
import pathlib
from styxdefs import *

N3_BIAS_FIELD_CORRECTION_METADATA = Metadata(
    id="9d12f968603c88299a9568f0389d257d580c4fb5.boutiques",
    name="N3BiasFieldCorrection",
    package="ants",
    container_image_tag="antsx/ants:v2.5.3",
)


_N3BiasFieldCorrectionParamsDictNoTag = typing.TypedDict('_N3BiasFieldCorrectionParamsDictNoTag', {
    "image_dimensionality": typing.NotRequired[typing.Literal[2, 3, 4] | None],
    "input_image": InputPathType,
    "mask_image": typing.NotRequired[InputPathType | None],
    "rescale_intensities": typing.NotRequired[bool | None],
    "weight_image": typing.NotRequired[InputPathType | None],
    "shrink_factor": typing.NotRequired[int | None],
    "convergence": typing.NotRequired[str | None],
    "bspline_fitting": typing.NotRequired[str | None],
    "histogram_sharpening": typing.NotRequired[str | None],
    "output": str,
    "verbose": typing.NotRequired[bool | None],
})
N3BiasFieldCorrectionParamsDictTagged = typing.TypedDict('N3BiasFieldCorrectionParamsDictTagged', {
    "@type": typing.Literal["ants/N3BiasFieldCorrection"],
    "image_dimensionality": typing.NotRequired[typing.Literal[2, 3, 4] | None],
    "input_image": InputPathType,
    "mask_image": typing.NotRequired[InputPathType | None],
    "rescale_intensities": typing.NotRequired[bool | None],
    "weight_image": typing.NotRequired[InputPathType | None],
    "shrink_factor": typing.NotRequired[int | None],
    "convergence": typing.NotRequired[str | None],
    "bspline_fitting": typing.NotRequired[str | None],
    "histogram_sharpening": typing.NotRequired[str | None],
    "output": str,
    "verbose": typing.NotRequired[bool | None],
})
N3BiasFieldCorrectionParamsDict = _N3BiasFieldCorrectionParamsDictNoTag | N3BiasFieldCorrectionParamsDictTagged


class N3BiasFieldCorrectionOutputs(typing.NamedTuple):
    """
    Output object returned when calling `N3BiasFieldCorrectionParamsDict(...)`.
    """
    root: OutputPathType
    """Output root folder. This is the root folder for all outputs."""
    corrected_image: OutputPathType
    """The bias-corrected version of the input image."""
    bias_field: OutputPathType
    """The estimated bias field, if specified in the output."""


def n3_bias_field_correction_params(
    input_image: InputPathType,
    output: str,
    image_dimensionality: typing.Literal[2, 3, 4] | None = None,
    mask_image: InputPathType | None = None,
    rescale_intensities: bool | None = None,
    weight_image: InputPathType | None = None,
    shrink_factor: int | None = None,
    convergence: str | None = None,
    bspline_fitting: str | None = None,
    histogram_sharpening: str | None = None,
    verbose: bool | None = None,
) -> N3BiasFieldCorrectionParamsDictTagged:
    """
    Build parameters.
    
    Args:
        input_image: A scalar image is expected as input for bias correction.\
            Since N3 log transforms the intensities, negative values or values\
            close to zero should be processed prior to correction.
        output: The bias-corrected version of the input image and optionally\
            the estimated bias field.
        image_dimensionality: This option forces the image to be treated as a\
            specified-dimensional image. If not specified, N3 tries to infer the\
            dimensionality from the input image.
        mask_image: If a mask image is specified, the final bias correction is\
            only performed in the mask region. If a mask image is not specified,\
            the entire image region will be used as the mask region. Note: this\
            differs from the original N3 implementation.
        rescale_intensities: This option rescales the intensity range within\
            the user-specified mask to the original [min, max] range.
        weight_image: The weight image allows the user to perform a relative\
            weighting of specific voxels during the B-spline fitting.
        shrink_factor: Shrink factor to resample the input image. Commonly used\
            values are <= 4.
        convergence: Describes the convergence criteria with default value as\
            [50,0.0].
        bspline_fitting: Describes the parameters for B-Spline fitting.\
            Defaults are [splineDistance,4,3].
        histogram_sharpening: Describes histogram sharpening parameters;\
            defaults are [0.15,0.01,200].
        verbose: Verbose output.
    Returns:
        Parameter dictionary
    """
    params = {
        "@type": "ants/N3BiasFieldCorrection",
        "input_image": input_image,
        "output": output,
    }
    if image_dimensionality is not None:
        params["image_dimensionality"] = image_dimensionality
    if mask_image is not None:
        params["mask_image"] = mask_image
    if rescale_intensities is not None:
        params["rescale_intensities"] = rescale_intensities
    if weight_image is not None:
        params["weight_image"] = weight_image
    if shrink_factor is not None:
        params["shrink_factor"] = shrink_factor
    if convergence is not None:
        params["convergence"] = convergence
    if bspline_fitting is not None:
        params["bspline_fitting"] = bspline_fitting
    if histogram_sharpening is not None:
        params["histogram_sharpening"] = histogram_sharpening
    if verbose is not None:
        params["verbose"] = verbose
    return params


def n3_bias_field_correction_validate(
    params: typing.Any,
) -> None:
    """
    Validate parameters. Throws an error if `params` is not a valid
    `N3BiasFieldCorrectionParamsDict` 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("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("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("rescale_intensities", None) is not None:
        if not isinstance(params["rescale_intensities"], bool):
            raise StyxValidationError(f'`rescale_intensities` has the wrong type: Received `{type(params.get("rescale_intensities", None))}` expected `bool | None`')
    if params.get("weight_image", None) is not None:
        if not isinstance(params["weight_image"], (pathlib.Path, str)):
            raise StyxValidationError(f'`weight_image` has the wrong type: Received `{type(params.get("weight_image", None))}` expected `InputPathType | None`')
    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("convergence", None) is not None:
        if not isinstance(params["convergence"], str):
            raise StyxValidationError(f'`convergence` has the wrong type: Received `{type(params.get("convergence", None))}` expected `str | None`')
    if params.get("bspline_fitting", None) is not None:
        if not isinstance(params["bspline_fitting"], str):
            raise StyxValidationError(f'`bspline_fitting` has the wrong type: Received `{type(params.get("bspline_fitting", None))}` expected `str | None`')
    if params.get("histogram_sharpening", None) is not None:
        if not isinstance(params["histogram_sharpening"], str):
            raise StyxValidationError(f'`histogram_sharpening` has the wrong type: Received `{type(params.get("histogram_sharpening", None))}` expected `str | 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("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 n3_bias_field_correction_cargs(
    params: N3BiasFieldCorrectionParamsDict,
    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("N3BiasFieldCorrection")
    if params.get("image_dimensionality", None) is not None:
        cargs.extend([
            "--image-dimensionality",
            str(params.get("image_dimensionality", None))
        ])
    cargs.extend([
        "--input-image",
        execution.input_file(params.get("input_image", 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("rescale_intensities", None) is not None:
        cargs.extend([
            "--rescale-intensities",
            ("1" if params.get("rescale_intensities", None) else "0")
        ])
    if params.get("weight_image", None) is not None:
        cargs.extend([
            "--weight-image",
            execution.input_file(params.get("weight_image", None))
        ])
    if params.get("shrink_factor", None) is not None:
        cargs.extend([
            "--shrink-factor",
            str(params.get("shrink_factor", None))
        ])
    if params.get("convergence", None) is not None:
        cargs.extend([
            "--convergence",
            params.get("convergence", None)
        ])
    if params.get("bspline_fitting", None) is not None:
        cargs.extend([
            "--bspline-fitting",
            params.get("bspline_fitting", None)
        ])
    if params.get("histogram_sharpening", None) is not None:
        cargs.extend([
            "--histogram-sharpening",
            params.get("histogram_sharpening", None)
        ])
    cargs.extend([
        "--output",
        params.get("output", None)
    ])
    if params.get("verbose", None) is not None:
        cargs.extend([
            "--verbose",
            ("1" if params.get("verbose", None) else "0")
        ])
    return cargs


def n3_bias_field_correction_outputs(
    params: N3BiasFieldCorrectionParamsDict,
    execution: Execution,
) -> N3BiasFieldCorrectionOutputs:
    """
    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 = N3BiasFieldCorrectionOutputs(
        root=execution.output_file("."),
        corrected_image=execution.output_file(params.get("output", None)),
        bias_field=execution.output_file("[BIS_FIELD]"),
    )
    return ret


def n3_bias_field_correction_execute(
    params: N3BiasFieldCorrectionParamsDict,
    runner: Runner | None = None,
) -> N3BiasFieldCorrectionOutputs:
    """
    N3BiasFieldCorrection
    
    This N3 is a variant of the popular N3 (nonparametric nonuniform
    normalization) retrospective bias correction algorithm. Based on the
    assumption that the corruption of the low frequency bias field can be
    modeled as a convolution of the intensity histogram by a Gaussian, the basic
    algorithmic protocol is to iterate between deconvolving the intensity
    histogram by a Gaussian, remapping the intensities, and then spatially
    smoothing this result by a B-spline modeling of the bias field itself.
    
    Author: ANTs Developers
    
    URL: https://github.com/ANTsX/ANTs
    
    Args:
        params: The parameters.
        runner: Command runner.
    Returns:
        NamedTuple of outputs (described in `N3BiasFieldCorrectionOutputs`).
    """
    n3_bias_field_correction_validate(params)
    runner = runner or get_global_runner()
    execution = runner.start_execution(N3_BIAS_FIELD_CORRECTION_METADATA)
    params = execution.params(params)
    cargs = n3_bias_field_correction_cargs(params, execution)
    ret = n3_bias_field_correction_outputs(params, execution)
    execution.run(cargs)
    return ret


def n3_bias_field_correction(
    input_image: InputPathType,
    output: str,
    image_dimensionality: typing.Literal[2, 3, 4] | None = None,
    mask_image: InputPathType | None = None,
    rescale_intensities: bool | None = None,
    weight_image: InputPathType | None = None,
    shrink_factor: int | None = None,
    convergence: str | None = None,
    bspline_fitting: str | None = None,
    histogram_sharpening: str | None = None,
    verbose: bool | None = None,
    runner: Runner | None = None,
) -> N3BiasFieldCorrectionOutputs:
    """
    N3BiasFieldCorrection
    
    This N3 is a variant of the popular N3 (nonparametric nonuniform
    normalization) retrospective bias correction algorithm. Based on the
    assumption that the corruption of the low frequency bias field can be
    modeled as a convolution of the intensity histogram by a Gaussian, the basic
    algorithmic protocol is to iterate between deconvolving the intensity
    histogram by a Gaussian, remapping the intensities, and then spatially
    smoothing this result by a B-spline modeling of the bias field itself.
    
    Author: ANTs Developers
    
    URL: https://github.com/ANTsX/ANTs
    
    Args:
        input_image: A scalar image is expected as input for bias correction.\
            Since N3 log transforms the intensities, negative values or values\
            close to zero should be processed prior to correction.
        output: The bias-corrected version of the input image and optionally\
            the estimated bias field.
        image_dimensionality: This option forces the image to be treated as a\
            specified-dimensional image. If not specified, N3 tries to infer the\
            dimensionality from the input image.
        mask_image: If a mask image is specified, the final bias correction is\
            only performed in the mask region. If a mask image is not specified,\
            the entire image region will be used as the mask region. Note: this\
            differs from the original N3 implementation.
        rescale_intensities: This option rescales the intensity range within\
            the user-specified mask to the original [min, max] range.
        weight_image: The weight image allows the user to perform a relative\
            weighting of specific voxels during the B-spline fitting.
        shrink_factor: Shrink factor to resample the input image. Commonly used\
            values are <= 4.
        convergence: Describes the convergence criteria with default value as\
            [50,0.0].
        bspline_fitting: Describes the parameters for B-Spline fitting.\
            Defaults are [splineDistance,4,3].
        histogram_sharpening: Describes histogram sharpening parameters;\
            defaults are [0.15,0.01,200].
        verbose: Verbose output.
        runner: Command runner.
    Returns:
        NamedTuple of outputs (described in `N3BiasFieldCorrectionOutputs`).
    """
    params = n3_bias_field_correction_params(
        image_dimensionality=image_dimensionality,
        input_image=input_image,
        mask_image=mask_image,
        rescale_intensities=rescale_intensities,
        weight_image=weight_image,
        shrink_factor=shrink_factor,
        convergence=convergence,
        bspline_fitting=bspline_fitting,
        histogram_sharpening=histogram_sharpening,
        output=output,
        verbose=verbose,
    )
    return n3_bias_field_correction_execute(params, runner)


__all__ = [
    "N3BiasFieldCorrectionOutputs",
    "N3BiasFieldCorrectionParamsDict",
    "N3BiasFieldCorrectionParamsDictTagged",
    "N3_BIAS_FIELD_CORRECTION_METADATA",
    "n3_bias_field_correction",
    "n3_bias_field_correction_execute",
    "n3_bias_field_correction_params",
]
