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

import typing
import pathlib
from styxdefs import *

N4_BIAS_FIELD_CORRECTION_METADATA = Metadata(
    id="3f10828e86e53eef2772983bf2e0a920246c4729.boutiques",
    name="N4BiasFieldCorrection",
    package="ants",
    container_image_tag="antsx/ants:v2.5.3",
)


_N4BiasFieldCorrectionConvergenceParamsDictNoTag = typing.TypedDict('_N4BiasFieldCorrectionConvergenceParamsDictNoTag', {
    "convergence": list[int],
    "convergence_threshold": typing.NotRequired[float | None],
})
N4BiasFieldCorrectionConvergenceParamsDictTagged = typing.TypedDict('N4BiasFieldCorrectionConvergenceParamsDictTagged', {
    "@type": typing.Literal["convergence"],
    "convergence": list[int],
    "convergence_threshold": typing.NotRequired[float | None],
})
N4BiasFieldCorrectionConvergenceParamsDict = _N4BiasFieldCorrectionConvergenceParamsDictNoTag | N4BiasFieldCorrectionConvergenceParamsDictTagged


_N4BiasFieldCorrectionBsplineFittingParamsDictNoTag = typing.TypedDict('_N4BiasFieldCorrectionBsplineFittingParamsDictNoTag', {
    "spline_distance": list[float],
    "spline_order": typing.NotRequired[int | None],
})
N4BiasFieldCorrectionBsplineFittingParamsDictTagged = typing.TypedDict('N4BiasFieldCorrectionBsplineFittingParamsDictTagged', {
    "@type": typing.Literal["bspline_fitting"],
    "spline_distance": list[float],
    "spline_order": typing.NotRequired[int | None],
})
N4BiasFieldCorrectionBsplineFittingParamsDict = _N4BiasFieldCorrectionBsplineFittingParamsDictNoTag | N4BiasFieldCorrectionBsplineFittingParamsDictTagged


_N4BiasFieldCorrectionHistogramSharpeningParamsDictNoTag = typing.TypedDict('_N4BiasFieldCorrectionHistogramSharpeningParamsDictNoTag', {
    "fwhm": typing.NotRequired[float | None],
    "wiener_noise": typing.NotRequired[float | None],
    "number_of_histogram_bins": typing.NotRequired[int | None],
})
N4BiasFieldCorrectionHistogramSharpeningParamsDictTagged = typing.TypedDict('N4BiasFieldCorrectionHistogramSharpeningParamsDictTagged', {
    "@type": typing.Literal["histogram_sharpening"],
    "fwhm": typing.NotRequired[float | None],
    "wiener_noise": typing.NotRequired[float | None],
    "number_of_histogram_bins": typing.NotRequired[int | None],
})
N4BiasFieldCorrectionHistogramSharpeningParamsDict = _N4BiasFieldCorrectionHistogramSharpeningParamsDictNoTag | N4BiasFieldCorrectionHistogramSharpeningParamsDictTagged


_N4BiasFieldCorrectionCorrectedOutputParamsDictNoTag = typing.TypedDict('_N4BiasFieldCorrectionCorrectedOutputParamsDictNoTag', {
    "correctedOutputFileName": str,
})
N4BiasFieldCorrectionCorrectedOutputParamsDictTagged = typing.TypedDict('N4BiasFieldCorrectionCorrectedOutputParamsDictTagged', {
    "@type": typing.Literal["correctedOutput"],
    "correctedOutputFileName": str,
})
N4BiasFieldCorrectionCorrectedOutputParamsDict = _N4BiasFieldCorrectionCorrectedOutputParamsDictNoTag | N4BiasFieldCorrectionCorrectedOutputParamsDictTagged


_N4BiasFieldCorrectionCorrectedOutputNoiseParamsDictNoTag = typing.TypedDict('_N4BiasFieldCorrectionCorrectedOutputNoiseParamsDictNoTag', {
    "correctedOutputFileName": str,
    "biasFile": typing.NotRequired[str | None],
})
N4BiasFieldCorrectionCorrectedOutputNoiseParamsDictTagged = typing.TypedDict('N4BiasFieldCorrectionCorrectedOutputNoiseParamsDictTagged', {
    "@type": typing.Literal["correctedOutputNoise"],
    "correctedOutputFileName": str,
    "biasFile": typing.NotRequired[str | None],
})
N4BiasFieldCorrectionCorrectedOutputNoiseParamsDict = _N4BiasFieldCorrectionCorrectedOutputNoiseParamsDictNoTag | N4BiasFieldCorrectionCorrectedOutputNoiseParamsDictTagged


_N4BiasFieldCorrectionParamsDictNoTag = typing.TypedDict('_N4BiasFieldCorrectionParamsDictNoTag', {
    "image_dimensionality": typing.NotRequired[typing.Literal[2, 3, 4] | None],
    "shrink_factor": typing.NotRequired[int | None],
    "mask_image": typing.NotRequired[InputPathType | None],
    "rescale_intensities": typing.NotRequired[bool | None],
    "weight_image": typing.NotRequired[InputPathType | None],
    "convergence": typing.NotRequired[N4BiasFieldCorrectionConvergenceParamsDict | None],
    "bspline_fitting": typing.NotRequired[N4BiasFieldCorrectionBsplineFittingParamsDict | None],
    "histogram_sharpening": typing.NotRequired[N4BiasFieldCorrectionHistogramSharpeningParamsDict | None],
    "verbose": typing.NotRequired[bool | None],
    "input_image": InputPathType,
    "output": typing.Union[N4BiasFieldCorrectionCorrectedOutputParamsDictTagged, N4BiasFieldCorrectionCorrectedOutputNoiseParamsDictTagged],
})
N4BiasFieldCorrectionParamsDictTagged = typing.TypedDict('N4BiasFieldCorrectionParamsDictTagged', {
    "@type": typing.Literal["ants/N4BiasFieldCorrection"],
    "image_dimensionality": typing.NotRequired[typing.Literal[2, 3, 4] | None],
    "shrink_factor": typing.NotRequired[int | None],
    "mask_image": typing.NotRequired[InputPathType | None],
    "rescale_intensities": typing.NotRequired[bool | None],
    "weight_image": typing.NotRequired[InputPathType | None],
    "convergence": typing.NotRequired[N4BiasFieldCorrectionConvergenceParamsDict | None],
    "bspline_fitting": typing.NotRequired[N4BiasFieldCorrectionBsplineFittingParamsDict | None],
    "histogram_sharpening": typing.NotRequired[N4BiasFieldCorrectionHistogramSharpeningParamsDict | None],
    "verbose": typing.NotRequired[bool | None],
    "input_image": InputPathType,
    "output": typing.Union[N4BiasFieldCorrectionCorrectedOutputParamsDictTagged, N4BiasFieldCorrectionCorrectedOutputNoiseParamsDictTagged],
})
N4BiasFieldCorrectionParamsDict = _N4BiasFieldCorrectionParamsDictNoTag | N4BiasFieldCorrectionParamsDictTagged


def n4_bias_field_correction_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": n4_bias_field_correction_corrected_output_cargs,
        "correctedOutputNoise": n4_bias_field_correction_corrected_output_noise_cargs,
    }.get(t)


def n4_bias_field_correction_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": n4_bias_field_correction_corrected_output_outputs,
        "correctedOutputNoise": n4_bias_field_correction_corrected_output_noise_outputs,
    }.get(t)


def n4_bias_field_correction_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": n4_bias_field_correction_corrected_output_validate,
        "correctedOutputNoise": n4_bias_field_correction_corrected_output_noise_validate,
    }.get(t)


def n4_bias_field_correction_convergence(
    convergence: list[int],
    convergence_threshold: float | None = None,
) -> N4BiasFieldCorrectionConvergenceParamsDictTagged:
    """
    Build parameters.
    
    Args:
        convergence:.
        convergence_threshold:.
    Returns:
        Parameter dictionary
    """
    params = {
        "@type": "convergence",
        "convergence": convergence,
    }
    if convergence_threshold is not None:
        params["convergence_threshold"] = convergence_threshold
    return params


def n4_bias_field_correction_convergence_validate(
    params: typing.Any,
) -> None:
    """
    Validate parameters. Throws an error if `params` is not a valid
    `N4BiasFieldCorrectionConvergenceParamsDict` 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("convergence", None) is None:
        raise StyxValidationError("`convergence` must not be None")
    if not isinstance(params["convergence"], list):
        raise StyxValidationError(f'`convergence` has the wrong type: Received `{type(params.get("convergence", None))}` expected `list[int]`')
    for e in params["convergence"]:
        if not isinstance(e, int):
            raise StyxValidationError(f'`convergence` has the wrong type: Received `{type(params.get("convergence", None))}` expected `list[int]`')
    if params.get("convergence_threshold", None) is not None:
        if not isinstance(params["convergence_threshold"], (float, int)):
            raise StyxValidationError(f'`convergence_threshold` has the wrong type: Received `{type(params.get("convergence_threshold", None))}` expected `float | None`')


def n4_bias_field_correction_convergence_cargs(
    params: N4BiasFieldCorrectionConvergenceParamsDict,
    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("[" + "x".join(map(str, params.get("convergence", None))) + "," + (str(params.get("convergence_threshold", None)) if (params.get("convergence_threshold", None) is not None) else "") + "]")
    return cargs


def n4_bias_field_correction_bspline_fitting(
    spline_distance: list[float],
    spline_order: int | None = None,
) -> N4BiasFieldCorrectionBsplineFittingParamsDictTagged:
    """
    Build parameters.
    
    Args:
        spline_distance:.
        spline_order:.
    Returns:
        Parameter dictionary
    """
    params = {
        "@type": "bspline_fitting",
        "spline_distance": spline_distance,
    }
    if spline_order is not None:
        params["spline_order"] = spline_order
    return params


def n4_bias_field_correction_bspline_fitting_validate(
    params: typing.Any,
) -> None:
    """
    Validate parameters. Throws an error if `params` is not a valid
    `N4BiasFieldCorrectionBsplineFittingParamsDict` 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("spline_distance", None) is None:
        raise StyxValidationError("`spline_distance` must not be None")
    if not isinstance(params["spline_distance"], list):
        raise StyxValidationError(f'`spline_distance` has the wrong type: Received `{type(params.get("spline_distance", None))}` expected `list[float]`')
    for e in params["spline_distance"]:
        if not isinstance(e, (float, int)):
            raise StyxValidationError(f'`spline_distance` has the wrong type: Received `{type(params.get("spline_distance", None))}` expected `list[float]`')
    if params.get("spline_order", None) is not None:
        if not isinstance(params["spline_order"], int):
            raise StyxValidationError(f'`spline_order` has the wrong type: Received `{type(params.get("spline_order", None))}` expected `int | None`')


def n4_bias_field_correction_bspline_fitting_cargs(
    params: N4BiasFieldCorrectionBsplineFittingParamsDict,
    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("[" + "x".join(map(str, params.get("spline_distance", None))) + "," + (str(params.get("spline_order", None)) if (params.get("spline_order", None) is not None) else "") + "]")
    return cargs


def n4_bias_field_correction_histogram_sharpening(
    fwhm: float | None = None,
    wiener_noise: float | None = None,
    number_of_histogram_bins: int | None = None,
) -> N4BiasFieldCorrectionHistogramSharpeningParamsDictTagged:
    """
    Build parameters.
    
    Args:
        fwhm:.
        wiener_noise:.
        number_of_histogram_bins:.
    Returns:
        Parameter dictionary
    """
    params = {
        "@type": "histogram_sharpening",
    }
    if fwhm is not None:
        params["fwhm"] = fwhm
    if wiener_noise is not None:
        params["wiener_noise"] = wiener_noise
    if number_of_histogram_bins is not None:
        params["number_of_histogram_bins"] = number_of_histogram_bins
    return params


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


def n4_bias_field_correction_histogram_sharpening_cargs(
    params: N4BiasFieldCorrectionHistogramSharpeningParamsDict,
    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("fwhm", None) is not None or params.get("wiener_noise", None) is not None or params.get("number_of_histogram_bins", None) is not None:
        cargs.append("[" + (str(params.get("fwhm", None)) if (params.get("fwhm", None) is not None) else "") + "," + (str(params.get("wiener_noise", None)) if (params.get("wiener_noise", None) is not None) else "") + "," + (str(params.get("number_of_histogram_bins", None)) if (params.get("number_of_histogram_bins", None) is not None) else "") + "]")
    return cargs


class N4BiasFieldCorrectionCorrectedOutputOutputs(typing.NamedTuple):
    """
    Output object returned when calling `N4BiasFieldCorrectionCorrectedOutputParamsDict(...)`.
    """
    root: OutputPathType
    """Output root folder. This is the root folder for all outputs."""
    output_image_outfile: OutputPathType
    """Bias corrected image."""


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


def n4_bias_field_correction_corrected_output_validate(
    params: typing.Any,
) -> None:
    """
    Validate parameters. Throws an error if `params` is not a valid
    `N4BiasFieldCorrectionCorrectedOutputParamsDict` 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 n4_bias_field_correction_corrected_output_cargs(
    params: N4BiasFieldCorrectionCorrectedOutputParamsDict,
    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 n4_bias_field_correction_corrected_output_outputs(
    params: N4BiasFieldCorrectionCorrectedOutputParamsDict,
    execution: Execution,
) -> N4BiasFieldCorrectionCorrectedOutputOutputs:
    """
    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 = N4BiasFieldCorrectionCorrectedOutputOutputs(
        root=execution.output_file("."),
        output_image_outfile=execution.output_file(params.get("correctedOutputFileName", None)),
    )
    return ret


class N4BiasFieldCorrectionCorrectedOutputNoiseOutputs(typing.NamedTuple):
    """
    Output object returned when calling `N4BiasFieldCorrectionCorrectedOutputNoiseParamsDict(...)`.
    """
    root: OutputPathType
    """Output root folder. This is the root folder for all outputs."""
    output_image_outfile: OutputPathType
    """Bias corrected image."""
    output_bias_image: OutputPathType | None
    """Bias field image."""


def n4_bias_field_correction_corrected_output_noise(
    corrected_output_file_name: str,
    bias_file: str | None = None,
) -> N4BiasFieldCorrectionCorrectedOutputNoiseParamsDictTagged:
    """
    Build parameters.
    
    Args:
        corrected_output_file_name: Output file name.
        bias_file: Output bias field image.
    Returns:
        Parameter dictionary
    """
    params = {
        "@type": "correctedOutputNoise",
        "correctedOutputFileName": corrected_output_file_name,
    }
    if bias_file is not None:
        params["biasFile"] = bias_file
    return params


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


def n4_bias_field_correction_corrected_output_noise_cargs(
    params: N4BiasFieldCorrectionCorrectedOutputNoiseParamsDict,
    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("biasFile", None) if (params.get("biasFile", None) is not None) else "") + "]")
    return cargs


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


class N4BiasFieldCorrectionOutputs(typing.NamedTuple):
    """
    Output object returned when calling `N4BiasFieldCorrectionParamsDict(...)`.
    """
    root: OutputPathType
    """Output root folder. This is the root folder for all outputs."""
    output: typing.Union[N4BiasFieldCorrectionCorrectedOutputOutputs, N4BiasFieldCorrectionCorrectedOutputNoiseOutputs]
    """Outputs from `N4BiasFieldCorrectionCorrectedOutputParamsDict` or
    `N4BiasFieldCorrectionCorrectedOutputNoiseParamsDict`."""


def n4_bias_field_correction_params(
    input_image: InputPathType,
    output: typing.Union[N4BiasFieldCorrectionCorrectedOutputParamsDictTagged, N4BiasFieldCorrectionCorrectedOutputNoiseParamsDictTagged],
    image_dimensionality: typing.Literal[2, 3, 4] | None = None,
    shrink_factor: int | None = None,
    mask_image: InputPathType | None = None,
    rescale_intensities: bool | None = None,
    weight_image: InputPathType | None = None,
    convergence: N4BiasFieldCorrectionConvergenceParamsDict | None = None,
    bspline_fitting: N4BiasFieldCorrectionBsplineFittingParamsDict | None = None,
    histogram_sharpening: N4BiasFieldCorrectionHistogramSharpeningParamsDict | None = None,
    verbose: bool | None = None,
) -> N4BiasFieldCorrectionParamsDictTagged:
    """
    Build parameters.
    
    Args:
        input_image: -i, --input-image inputImageFilename. A scalar image is\
            expected as input for bias correction. Since N4 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, with optional\
            noise 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, N4 tries to infer the dimensionality from the input image.
        shrink_factor: -s, --shrink-factor 1/2/3/(4)/... Running N4 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 factors <= 4 are commonly\
            used. Note that the shrink factor is only applied to the first two or\
            three dimensions which we assume are spatial.
        mask_image: -x, --mask-image maskImageFilename. If a mask image is\
            specified, the final bias correction is only performed in the mask\
            region. If a weight image is not specified, only intensity values\
            inside the masked region are used during the execution of the\
            algorithm. If a weight image is specified, only the non-zero weights\
            are used in the execution of the algorithm although the mask region\
            defines where bias correction is performed in the final output.\
            Otherwise bias correction occurs over the entire image domain. See also\
            the option description for the weight image. If a mask image is *not*\
            specified then the entire image region will be used as the mask region.\
            Note that this is different than the N3 implementation which uses the\
            results of Otsu thresholding to define a mask. However, this leads to\
            unknown anatomical regions being included and excluded during the bias\
            correction.
        rescale_intensities: -r, --rescale-intensities 0/(1). At each\
            iteration, a new intensity mapping is calculated and applied but there\
            is nothing which constrains the new intensity range to be within\
            certain values. The result is that the range can "drift" from the\
            original at each iteration. This option rescales to the [min,max] range\
            of the original image intensities within the user-specified mask. A\
            mask is required to perform rescaling.
        weight_image: -w, --weight-image weightImageFilename. The weight image\
            allows the user to perform a relative weighting of specific voxels\
            during the B-spline fitting. For example, some studies have shown that\
            N3 performed on white matter segmentations improves performance. If one\
            has a spatial probability map of the white matter, one can use this map\
            to weight the b-spline fitting towards those voxels which are more\
            probabilistically classified as white matter. See also the option\
            description for the mask image.
        convergence: -c, --convergence\
            [<numberOfIterations=50x50x50x50>,<convergenceThreshold=0.0>].\
            Convergence is determined by calculating the coefficient of variation\
            between subsequent iterations. When this value is less than the\
            specified threshold from the previous iteration or the maximum number\
            of iterations is exceeded the program terminates. Multiple resolutions\
            can be specified by using 'x' between the number of iterations at each\
            resolution, e.g. 100x50x50.
        bspline_fitting: -b, --bspline-fitting\
            [splineDistance,<splineOrder=3>]. These options describe the b-spline\
            fitting parameters. The initial b-spline mesh at the coarsest\
            resolution is specified either as the number of elements in each\
            dimension, e.g. 2x2x3 for 3-D images, or it can be specified as a\
            single scalar parameter which describes the isotropic sizing of the\
            mesh elements. The latter option is typically preferred. For each\
            subsequent level, the spline distance decreases in half, or\
            equivalently, the number of mesh elements doubles Cubic splines (order\
            = 3) are typically used. The default setting is to employ a single mesh\
            element over the entire domain, i.e., -b [1x1x1,3].
        histogram_sharpening: -t, --histogram-sharpening\
            [<FWHM=0.15>,<wienerNoise=0.01>,<numberOfHistogramBins=200>]. These\
            options describe the histogram sharpening parameters, i.e. the\
            deconvolution step parameters described in the original N3 algorithm.\
            The default values have been shown to work fairly well.
        verbose: Verbose output.
    Returns:
        Parameter dictionary
    """
    params = {
        "@type": "ants/N4BiasFieldCorrection",
        "input_image": input_image,
        "output": output,
    }
    if image_dimensionality is not None:
        params["image_dimensionality"] = image_dimensionality
    if shrink_factor is not None:
        params["shrink_factor"] = shrink_factor
    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 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 n4_bias_field_correction_validate(
    params: typing.Any,
) -> None:
    """
    Validate parameters. Throws an error if `params` is not a valid
    `N4BiasFieldCorrectionParamsDict` 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("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("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("convergence", None) is not None:
        n4_bias_field_correction_convergence_validate(params["convergence"])
    if params.get("bspline_fitting", None) is not None:
        n4_bias_field_correction_bspline_fitting_validate(params["bspline_fitting"])
    if params.get("histogram_sharpening", None) is not None:
        n4_bias_field_correction_histogram_sharpening_validate(params["histogram_sharpening"])
    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\"]")
    n4_bias_field_correction_output_validate_dyn_fn(params["output"]["@type"])(params["output"])


def n4_bias_field_correction_cargs(
    params: N4BiasFieldCorrectionParamsDict,
    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("N4BiasFieldCorrection")
    if params.get("image_dimensionality", None) is not None:
        cargs.extend([
            "--image-dimensionality",
            str(params.get("image_dimensionality", 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("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("convergence", None) is not None:
        cargs.extend([
            "--convergence",
            *n4_bias_field_correction_convergence_cargs(params.get("convergence", None), execution)
        ])
    if params.get("bspline_fitting", None) is not None:
        cargs.extend([
            "--bspline-fitting",
            *n4_bias_field_correction_bspline_fitting_cargs(params.get("bspline_fitting", None), execution)
        ])
    if params.get("histogram_sharpening", None) is not None:
        cargs.extend([
            "--histogram-sharpening",
            *n4_bias_field_correction_histogram_sharpening_cargs(params.get("histogram_sharpening", None), execution)
        ])
    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",
        *n4_bias_field_correction_output_cargs_dyn_fn(params.get("output", None)["@type"])(params.get("output", None), execution)
    ])
    return cargs


def n4_bias_field_correction_outputs(
    params: N4BiasFieldCorrectionParamsDict,
    execution: Execution,
) -> N4BiasFieldCorrectionOutputs:
    """
    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 = N4BiasFieldCorrectionOutputs(
        root=execution.output_file("."),
        output=n4_bias_field_correction_output_outputs_dyn_fn(params.get("output")["@type"])(params.get("output"), execution),
    )
    return ret


def n4_bias_field_correction_execute(
    params: N4BiasFieldCorrectionParamsDict,
    runner: Runner | None = None,
) -> N4BiasFieldCorrectionOutputs:
    """
    N4BiasFieldCorrection
    
    N4 is a variant of the popular N3 (nonparameteric 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 `N4BiasFieldCorrectionOutputs`).
    """
    n4_bias_field_correction_validate(params)
    runner = runner or get_global_runner()
    execution = runner.start_execution(N4_BIAS_FIELD_CORRECTION_METADATA)
    params = execution.params(params)
    cargs = n4_bias_field_correction_cargs(params, execution)
    ret = n4_bias_field_correction_outputs(params, execution)
    execution.run(cargs)
    return ret


def n4_bias_field_correction(
    input_image: InputPathType,
    output: typing.Union[N4BiasFieldCorrectionCorrectedOutputParamsDictTagged, N4BiasFieldCorrectionCorrectedOutputNoiseParamsDictTagged],
    image_dimensionality: typing.Literal[2, 3, 4] | None = None,
    shrink_factor: int | None = None,
    mask_image: InputPathType | None = None,
    rescale_intensities: bool | None = None,
    weight_image: InputPathType | None = None,
    convergence: N4BiasFieldCorrectionConvergenceParamsDict | None = None,
    bspline_fitting: N4BiasFieldCorrectionBsplineFittingParamsDict | None = None,
    histogram_sharpening: N4BiasFieldCorrectionHistogramSharpeningParamsDict | None = None,
    verbose: bool | None = None,
    runner: Runner | None = None,
) -> N4BiasFieldCorrectionOutputs:
    """
    N4BiasFieldCorrection
    
    N4 is a variant of the popular N3 (nonparameteric 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: -i, --input-image inputImageFilename. A scalar image is\
            expected as input for bias correction. Since N4 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, with optional\
            noise 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, N4 tries to infer the dimensionality from the input image.
        shrink_factor: -s, --shrink-factor 1/2/3/(4)/... Running N4 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 factors <= 4 are commonly\
            used. Note that the shrink factor is only applied to the first two or\
            three dimensions which we assume are spatial.
        mask_image: -x, --mask-image maskImageFilename. If a mask image is\
            specified, the final bias correction is only performed in the mask\
            region. If a weight image is not specified, only intensity values\
            inside the masked region are used during the execution of the\
            algorithm. If a weight image is specified, only the non-zero weights\
            are used in the execution of the algorithm although the mask region\
            defines where bias correction is performed in the final output.\
            Otherwise bias correction occurs over the entire image domain. See also\
            the option description for the weight image. If a mask image is *not*\
            specified then the entire image region will be used as the mask region.\
            Note that this is different than the N3 implementation which uses the\
            results of Otsu thresholding to define a mask. However, this leads to\
            unknown anatomical regions being included and excluded during the bias\
            correction.
        rescale_intensities: -r, --rescale-intensities 0/(1). At each\
            iteration, a new intensity mapping is calculated and applied but there\
            is nothing which constrains the new intensity range to be within\
            certain values. The result is that the range can "drift" from the\
            original at each iteration. This option rescales to the [min,max] range\
            of the original image intensities within the user-specified mask. A\
            mask is required to perform rescaling.
        weight_image: -w, --weight-image weightImageFilename. The weight image\
            allows the user to perform a relative weighting of specific voxels\
            during the B-spline fitting. For example, some studies have shown that\
            N3 performed on white matter segmentations improves performance. If one\
            has a spatial probability map of the white matter, one can use this map\
            to weight the b-spline fitting towards those voxels which are more\
            probabilistically classified as white matter. See also the option\
            description for the mask image.
        convergence: -c, --convergence\
            [<numberOfIterations=50x50x50x50>,<convergenceThreshold=0.0>].\
            Convergence is determined by calculating the coefficient of variation\
            between subsequent iterations. When this value is less than the\
            specified threshold from the previous iteration or the maximum number\
            of iterations is exceeded the program terminates. Multiple resolutions\
            can be specified by using 'x' between the number of iterations at each\
            resolution, e.g. 100x50x50.
        bspline_fitting: -b, --bspline-fitting\
            [splineDistance,<splineOrder=3>]. These options describe the b-spline\
            fitting parameters. The initial b-spline mesh at the coarsest\
            resolution is specified either as the number of elements in each\
            dimension, e.g. 2x2x3 for 3-D images, or it can be specified as a\
            single scalar parameter which describes the isotropic sizing of the\
            mesh elements. The latter option is typically preferred. For each\
            subsequent level, the spline distance decreases in half, or\
            equivalently, the number of mesh elements doubles Cubic splines (order\
            = 3) are typically used. The default setting is to employ a single mesh\
            element over the entire domain, i.e., -b [1x1x1,3].
        histogram_sharpening: -t, --histogram-sharpening\
            [<FWHM=0.15>,<wienerNoise=0.01>,<numberOfHistogramBins=200>]. These\
            options describe the histogram sharpening parameters, i.e. the\
            deconvolution step parameters described in the original N3 algorithm.\
            The default values have been shown to work fairly well.
        verbose: Verbose output.
        runner: Command runner.
    Returns:
        NamedTuple of outputs (described in `N4BiasFieldCorrectionOutputs`).
    """
    params = n4_bias_field_correction_params(
        image_dimensionality=image_dimensionality,
        shrink_factor=shrink_factor,
        mask_image=mask_image,
        rescale_intensities=rescale_intensities,
        weight_image=weight_image,
        convergence=convergence,
        bspline_fitting=bspline_fitting,
        histogram_sharpening=histogram_sharpening,
        verbose=verbose,
        input_image=input_image,
        output=output,
    )
    return n4_bias_field_correction_execute(params, runner)


__all__ = [
    "N4BiasFieldCorrectionBsplineFittingParamsDict",
    "N4BiasFieldCorrectionBsplineFittingParamsDictTagged",
    "N4BiasFieldCorrectionConvergenceParamsDict",
    "N4BiasFieldCorrectionConvergenceParamsDictTagged",
    "N4BiasFieldCorrectionCorrectedOutputNoiseOutputs",
    "N4BiasFieldCorrectionCorrectedOutputNoiseParamsDict",
    "N4BiasFieldCorrectionCorrectedOutputNoiseParamsDictTagged",
    "N4BiasFieldCorrectionCorrectedOutputOutputs",
    "N4BiasFieldCorrectionCorrectedOutputParamsDict",
    "N4BiasFieldCorrectionCorrectedOutputParamsDictTagged",
    "N4BiasFieldCorrectionHistogramSharpeningParamsDict",
    "N4BiasFieldCorrectionHistogramSharpeningParamsDictTagged",
    "N4BiasFieldCorrectionOutputs",
    "N4BiasFieldCorrectionParamsDict",
    "N4BiasFieldCorrectionParamsDictTagged",
    "N4_BIAS_FIELD_CORRECTION_METADATA",
    "n4_bias_field_correction",
    "n4_bias_field_correction_bspline_fitting",
    "n4_bias_field_correction_convergence",
    "n4_bias_field_correction_corrected_output",
    "n4_bias_field_correction_corrected_output_noise",
    "n4_bias_field_correction_execute",
    "n4_bias_field_correction_histogram_sharpening",
    "n4_bias_field_correction_params",
]
