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

import typing
import pathlib
from styxdefs import *

VOLUME_REDUCE_METADATA = Metadata(
    id="640fab587d02e7f004bb3968f135463a35a2774a.workbench",
    name="volume-reduce",
    package="workbench",
    container_image_tag="nx10x/workbench:2.1.0",
)


_VolumeReduceExcludeOutliersParamsDictNoTag = typing.TypedDict('_VolumeReduceExcludeOutliersParamsDictNoTag', {
    "sigma-below": float,
    "sigma-above": float,
})
VolumeReduceExcludeOutliersParamsDictTagged = typing.TypedDict('VolumeReduceExcludeOutliersParamsDictTagged', {
    "@type": typing.Literal["exclude-outliers"],
    "sigma-below": float,
    "sigma-above": float,
})
VolumeReduceExcludeOutliersParamsDict = _VolumeReduceExcludeOutliersParamsDictNoTag | VolumeReduceExcludeOutliersParamsDictTagged


_VolumeReduceParamsDictNoTag = typing.TypedDict('_VolumeReduceParamsDictNoTag', {
    "volume-in": InputPathType,
    "operation": str,
    "volume-out": str,
    "exclude-outliers": typing.NotRequired[VolumeReduceExcludeOutliersParamsDict | None],
    "only-numeric": bool,
})
VolumeReduceParamsDictTagged = typing.TypedDict('VolumeReduceParamsDictTagged', {
    "@type": typing.Literal["workbench/volume-reduce"],
    "volume-in": InputPathType,
    "operation": str,
    "volume-out": str,
    "exclude-outliers": typing.NotRequired[VolumeReduceExcludeOutliersParamsDict | None],
    "only-numeric": bool,
})
VolumeReduceParamsDict = _VolumeReduceParamsDictNoTag | VolumeReduceParamsDictTagged


def volume_reduce_exclude_outliers(
    sigma_below: float,
    sigma_above: float,
) -> VolumeReduceExcludeOutliersParamsDictTagged:
    """
    Build parameters.
    
    Args:
        sigma_below: number of standard deviations below the mean to include.
        sigma_above: number of standard deviations above the mean to include.
    Returns:
        Parameter dictionary
    """
    params = {
        "@type": "exclude-outliers",
        "sigma-below": sigma_below,
        "sigma-above": sigma_above,
    }
    return params


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


def volume_reduce_exclude_outliers_cargs(
    params: VolumeReduceExcludeOutliersParamsDict,
    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.extend([
        "-exclude-outliers",
        str(params.get("sigma-below", None)),
        str(params.get("sigma-above", None))
    ])
    return cargs


class VolumeReduceOutputs(typing.NamedTuple):
    """
    Output object returned when calling `VolumeReduceParamsDict(...)`.
    """
    root: OutputPathType
    """Output root folder. This is the root folder for all outputs."""
    volume_out: OutputPathType
    """the output volume"""


def volume_reduce_params(
    volume_in: InputPathType,
    operation: str,
    volume_out: str,
    exclude_outliers: VolumeReduceExcludeOutliersParamsDict | None = None,
    only_numeric: bool = False,
) -> VolumeReduceParamsDictTagged:
    """
    Build parameters.
    
    Args:
        volume_in: the volume file to reduce.
        operation: the reduction operator to use.
        volume_out: the output volume.
        exclude_outliers: exclude non-numeric values and outliers by standard\
            deviation.
        only_numeric: exclude non-numeric values.
    Returns:
        Parameter dictionary
    """
    params = {
        "@type": "workbench/volume-reduce",
        "volume-in": volume_in,
        "operation": operation,
        "volume-out": volume_out,
        "only-numeric": only_numeric,
    }
    if exclude_outliers is not None:
        params["exclude-outliers"] = exclude_outliers
    return params


def volume_reduce_validate(
    params: typing.Any,
) -> None:
    """
    Validate parameters. Throws an error if `params` is not a valid
    `VolumeReduceParamsDict` 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("volume-in", None) is None:
        raise StyxValidationError("`volume-in` must not be None")
    if not isinstance(params["volume-in"], (pathlib.Path, str)):
        raise StyxValidationError(f'`volume-in` has the wrong type: Received `{type(params.get("volume-in", None))}` expected `InputPathType`')
    if params.get("operation", None) is None:
        raise StyxValidationError("`operation` must not be None")
    if not isinstance(params["operation"], str):
        raise StyxValidationError(f'`operation` has the wrong type: Received `{type(params.get("operation", None))}` expected `str`')
    if params.get("volume-out", None) is None:
        raise StyxValidationError("`volume-out` must not be None")
    if not isinstance(params["volume-out"], str):
        raise StyxValidationError(f'`volume-out` has the wrong type: Received `{type(params.get("volume-out", None))}` expected `str`')
    if params.get("exclude-outliers", None) is not None:
        volume_reduce_exclude_outliers_validate(params["exclude-outliers"])
    if params.get("only-numeric", False) is None:
        raise StyxValidationError("`only-numeric` must not be None")
    if not isinstance(params["only-numeric"], bool):
        raise StyxValidationError(f'`only-numeric` has the wrong type: Received `{type(params.get("only-numeric", False))}` expected `bool`')


def volume_reduce_cargs(
    params: VolumeReduceParamsDict,
    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.extend([
        "wb_command",
        "-volume-reduce"
    ])
    cargs.append(execution.input_file(params.get("volume-in", None)))
    cargs.append(params.get("operation", None))
    cargs.append(params.get("volume-out", None))
    if params.get("exclude-outliers", None) is not None:
        cargs.extend(volume_reduce_exclude_outliers_cargs(params.get("exclude-outliers", None), execution))
    if params.get("only-numeric", False):
        cargs.append("-only-numeric")
    return cargs


def volume_reduce_outputs(
    params: VolumeReduceParamsDict,
    execution: Execution,
) -> VolumeReduceOutputs:
    """
    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 = VolumeReduceOutputs(
        root=execution.output_file("."),
        volume_out=execution.output_file(params.get("volume-out", None)),
    )
    return ret


def volume_reduce_execute(
    params: VolumeReduceParamsDict,
    runner: Runner | None = None,
) -> VolumeReduceOutputs:
    """
    PERFORM REDUCTION OPERATION ACROSS SUBVOLUMES.
    
    For each voxel, takes the data across subvolumes as a vector, and performs
    the specified reduction on it, putting the result into the single output
    volume at that voxel. The reduction operators are as follows:
    
    MAX: the maximum value
    MIN: the minimum value
    INDEXMAX: the 1-based index of the maximum value
    INDEXMIN: the 1-based index of the minimum value
    SUM: add all values
    PRODUCT: multiply all values
    MEAN: the mean of the data
    STDEV: the standard deviation (N denominator)
    SAMPSTDEV: the sample standard deviation (N-1 denominator)
    VARIANCE: the variance of the data
    TSNR: mean divided by sample standard deviation (N-1 denominator)
    COV: sample standard deviation (N-1 denominator) divided by mean
    L2NORM: square root of sum of squares
    MEDIAN: the median of the data
    MODE: the mode of the data
    COUNT_NONZERO: the number of nonzero elements in the data
    .
    
    Args:
        params: The parameters.
        runner: Command runner.
    Returns:
        NamedTuple of outputs (described in `VolumeReduceOutputs`).
    """
    volume_reduce_validate(params)
    runner = runner or get_global_runner()
    execution = runner.start_execution(VOLUME_REDUCE_METADATA)
    params = execution.params(params)
    cargs = volume_reduce_cargs(params, execution)
    ret = volume_reduce_outputs(params, execution)
    execution.run(cargs)
    return ret


def volume_reduce(
    volume_in: InputPathType,
    operation: str,
    volume_out: str,
    exclude_outliers: VolumeReduceExcludeOutliersParamsDict | None = None,
    only_numeric: bool = False,
    runner: Runner | None = None,
) -> VolumeReduceOutputs:
    """
    PERFORM REDUCTION OPERATION ACROSS SUBVOLUMES.
    
    For each voxel, takes the data across subvolumes as a vector, and performs
    the specified reduction on it, putting the result into the single output
    volume at that voxel. The reduction operators are as follows:
    
    MAX: the maximum value
    MIN: the minimum value
    INDEXMAX: the 1-based index of the maximum value
    INDEXMIN: the 1-based index of the minimum value
    SUM: add all values
    PRODUCT: multiply all values
    MEAN: the mean of the data
    STDEV: the standard deviation (N denominator)
    SAMPSTDEV: the sample standard deviation (N-1 denominator)
    VARIANCE: the variance of the data
    TSNR: mean divided by sample standard deviation (N-1 denominator)
    COV: sample standard deviation (N-1 denominator) divided by mean
    L2NORM: square root of sum of squares
    MEDIAN: the median of the data
    MODE: the mode of the data
    COUNT_NONZERO: the number of nonzero elements in the data
    .
    
    Args:
        volume_in: the volume file to reduce.
        operation: the reduction operator to use.
        volume_out: the output volume.
        exclude_outliers: exclude non-numeric values and outliers by standard\
            deviation.
        only_numeric: exclude non-numeric values.
        runner: Command runner.
    Returns:
        NamedTuple of outputs (described in `VolumeReduceOutputs`).
    """
    params = volume_reduce_params(
        volume_in=volume_in,
        operation=operation,
        volume_out=volume_out,
        exclude_outliers=exclude_outliers,
        only_numeric=only_numeric,
    )
    return volume_reduce_execute(params, runner)


__all__ = [
    "VOLUME_REDUCE_METADATA",
    "VolumeReduceExcludeOutliersParamsDict",
    "VolumeReduceExcludeOutliersParamsDictTagged",
    "VolumeReduceOutputs",
    "VolumeReduceParamsDict",
    "VolumeReduceParamsDictTagged",
    "volume_reduce",
    "volume_reduce_exclude_outliers",
    "volume_reduce_execute",
    "volume_reduce_params",
]
