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

import typing
import pathlib
from styxdefs import *

SURFACE_AVERAGE_METADATA = Metadata(
    id="3cbdda68e7c781752cdffcc794c5ac24ffea464a.workbench",
    name="surface-average",
    package="workbench",
    container_image_tag="nx10x/workbench:2.1.0",
)


_SurfaceAverageStddevParamsDictNoTag = typing.TypedDict('_SurfaceAverageStddevParamsDictNoTag', {
    "stddev-metric-out": str,
})
SurfaceAverageStddevParamsDictTagged = typing.TypedDict('SurfaceAverageStddevParamsDictTagged', {
    "@type": typing.Literal["stddev"],
    "stddev-metric-out": str,
})
SurfaceAverageStddevParamsDict = _SurfaceAverageStddevParamsDictNoTag | SurfaceAverageStddevParamsDictTagged


_SurfaceAverageUncertaintyParamsDictNoTag = typing.TypedDict('_SurfaceAverageUncertaintyParamsDictNoTag', {
    "uncert-metric-out": str,
})
SurfaceAverageUncertaintyParamsDictTagged = typing.TypedDict('SurfaceAverageUncertaintyParamsDictTagged', {
    "@type": typing.Literal["uncertainty"],
    "uncert-metric-out": str,
})
SurfaceAverageUncertaintyParamsDict = _SurfaceAverageUncertaintyParamsDictNoTag | SurfaceAverageUncertaintyParamsDictTagged


_SurfaceAverageSurfParamsDictNoTag = typing.TypedDict('_SurfaceAverageSurfParamsDictNoTag', {
    "surface": InputPathType,
    "weight": typing.NotRequired[float | None],
})
SurfaceAverageSurfParamsDictTagged = typing.TypedDict('SurfaceAverageSurfParamsDictTagged', {
    "@type": typing.Literal["surf"],
    "surface": InputPathType,
    "weight": typing.NotRequired[float | None],
})
SurfaceAverageSurfParamsDict = _SurfaceAverageSurfParamsDictNoTag | SurfaceAverageSurfParamsDictTagged


_SurfaceAverageParamsDictNoTag = typing.TypedDict('_SurfaceAverageParamsDictNoTag', {
    "surface-out": str,
    "stddev": typing.NotRequired[SurfaceAverageStddevParamsDict | None],
    "uncertainty": typing.NotRequired[SurfaceAverageUncertaintyParamsDict | None],
    "surf": typing.NotRequired[list[SurfaceAverageSurfParamsDict] | None],
})
SurfaceAverageParamsDictTagged = typing.TypedDict('SurfaceAverageParamsDictTagged', {
    "@type": typing.Literal["workbench/surface-average"],
    "surface-out": str,
    "stddev": typing.NotRequired[SurfaceAverageStddevParamsDict | None],
    "uncertainty": typing.NotRequired[SurfaceAverageUncertaintyParamsDict | None],
    "surf": typing.NotRequired[list[SurfaceAverageSurfParamsDict] | None],
})
SurfaceAverageParamsDict = _SurfaceAverageParamsDictNoTag | SurfaceAverageParamsDictTagged


class SurfaceAverageStddevOutputs(typing.NamedTuple):
    """
    Output object returned when calling `SurfaceAverageStddevParamsDict | None(...)`.
    """
    root: OutputPathType
    """Output root folder. This is the root folder for all outputs."""
    stddev_metric_out: OutputPathType
    """the output metric for 3D sample standard deviation"""


def surface_average_stddev(
    stddev_metric_out: str,
) -> SurfaceAverageStddevParamsDictTagged:
    """
    Build parameters.
    
    Args:
        stddev_metric_out: the output metric for 3D sample standard deviation.
    Returns:
        Parameter dictionary
    """
    params = {
        "@type": "stddev",
        "stddev-metric-out": stddev_metric_out,
    }
    return params


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


def surface_average_stddev_cargs(
    params: SurfaceAverageStddevParamsDict,
    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([
        "-stddev",
        params.get("stddev-metric-out", None)
    ])
    return cargs


def surface_average_stddev_outputs(
    params: SurfaceAverageStddevParamsDict,
    execution: Execution,
) -> SurfaceAverageStddevOutputs:
    """
    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 = SurfaceAverageStddevOutputs(
        root=execution.output_file("."),
        stddev_metric_out=execution.output_file(params.get("stddev-metric-out", None)),
    )
    return ret


class SurfaceAverageUncertaintyOutputs(typing.NamedTuple):
    """
    Output object returned when calling `SurfaceAverageUncertaintyParamsDict | None(...)`.
    """
    root: OutputPathType
    """Output root folder. This is the root folder for all outputs."""
    uncert_metric_out: OutputPathType
    """the output metric for uncertainty"""


def surface_average_uncertainty(
    uncert_metric_out: str,
) -> SurfaceAverageUncertaintyParamsDictTagged:
    """
    Build parameters.
    
    Args:
        uncert_metric_out: the output metric for uncertainty.
    Returns:
        Parameter dictionary
    """
    params = {
        "@type": "uncertainty",
        "uncert-metric-out": uncert_metric_out,
    }
    return params


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


def surface_average_uncertainty_cargs(
    params: SurfaceAverageUncertaintyParamsDict,
    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([
        "-uncertainty",
        params.get("uncert-metric-out", None)
    ])
    return cargs


def surface_average_uncertainty_outputs(
    params: SurfaceAverageUncertaintyParamsDict,
    execution: Execution,
) -> SurfaceAverageUncertaintyOutputs:
    """
    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 = SurfaceAverageUncertaintyOutputs(
        root=execution.output_file("."),
        uncert_metric_out=execution.output_file(params.get("uncert-metric-out", None)),
    )
    return ret


def surface_average_surf(
    surface: InputPathType,
    weight: float | None = None,
) -> SurfaceAverageSurfParamsDictTagged:
    """
    Build parameters.
    
    Args:
        surface: a surface file to average.
        weight: specify a weighted average\
            \
            the weight to use (default 1).
    Returns:
        Parameter dictionary
    """
    params = {
        "@type": "surf",
        "surface": surface,
    }
    if weight is not None:
        params["weight"] = weight
    return params


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


def surface_average_surf_cargs(
    params: SurfaceAverageSurfParamsDict,
    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([
        "-surf",
        execution.input_file(params.get("surface", None))
    ])
    if params.get("weight", None) is not None:
        cargs.extend([
            "-weight",
            str(params.get("weight", None))
        ])
    return cargs


class SurfaceAverageOutputs(typing.NamedTuple):
    """
    Output object returned when calling `SurfaceAverageParamsDict(...)`.
    """
    root: OutputPathType
    """Output root folder. This is the root folder for all outputs."""
    surface_out: OutputPathType
    """the output averaged surface"""
    stddev: SurfaceAverageStddevOutputs | None
    """Outputs from `surface_average_stddev_outputs`."""
    uncertainty: SurfaceAverageUncertaintyOutputs | None
    """Outputs from `surface_average_uncertainty_outputs`."""


def surface_average_params(
    surface_out: str,
    stddev: SurfaceAverageStddevParamsDict | None = None,
    uncertainty: SurfaceAverageUncertaintyParamsDict | None = None,
    surf: list[SurfaceAverageSurfParamsDict] | None = None,
) -> SurfaceAverageParamsDictTagged:
    """
    Build parameters.
    
    Args:
        surface_out: the output averaged surface.
        stddev: compute 3D sample standard deviation.
        uncertainty: compute caret5 'uncertainty'.
        surf: specify a surface to include in the average.
    Returns:
        Parameter dictionary
    """
    params = {
        "@type": "workbench/surface-average",
        "surface-out": surface_out,
    }
    if stddev is not None:
        params["stddev"] = stddev
    if uncertainty is not None:
        params["uncertainty"] = uncertainty
    if surf is not None:
        params["surf"] = surf
    return params


def surface_average_validate(
    params: typing.Any,
) -> None:
    """
    Validate parameters. Throws an error if `params` is not a valid
    `SurfaceAverageParamsDict` 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("surface-out", None) is None:
        raise StyxValidationError("`surface-out` must not be None")
    if not isinstance(params["surface-out"], str):
        raise StyxValidationError(f'`surface-out` has the wrong type: Received `{type(params.get("surface-out", None))}` expected `str`')
    if params.get("stddev", None) is not None:
        surface_average_stddev_validate(params["stddev"])
    if params.get("uncertainty", None) is not None:
        surface_average_uncertainty_validate(params["uncertainty"])
    if params.get("surf", None) is not None:
        if not isinstance(params["surf"], list):
            raise StyxValidationError(f'`surf` has the wrong type: Received `{type(params.get("surf", None))}` expected `list[SurfaceAverageSurfParamsDict] | None`')
        for e in params["surf"]:
            surface_average_surf_validate(e)


def surface_average_cargs(
    params: SurfaceAverageParamsDict,
    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",
        "-surface-average"
    ])
    cargs.append(params.get("surface-out", None))
    if params.get("stddev", None) is not None or params.get("uncertainty", None) is not None or params.get("surf", None) is not None:
        cargs.extend([
            *(surface_average_stddev_cargs(params.get("stddev", None), execution) if (params.get("stddev", None) is not None) else []),
            *(surface_average_uncertainty_cargs(params.get("uncertainty", None), execution) if (params.get("uncertainty", None) is not None) else []),
            *([a for c in [surface_average_surf_cargs(s, execution) for s in params.get("surf", None)] for a in c] if (params.get("surf", None) is not None) else [])
        ])
    return cargs


def surface_average_outputs(
    params: SurfaceAverageParamsDict,
    execution: Execution,
) -> SurfaceAverageOutputs:
    """
    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 = SurfaceAverageOutputs(
        root=execution.output_file("."),
        surface_out=execution.output_file(params.get("surface-out", None)),
        stddev=surface_average_stddev_outputs(params.get("stddev"), execution) if params.get("stddev") else None,
        uncertainty=surface_average_uncertainty_outputs(params.get("uncertainty"), execution) if params.get("uncertainty") else None,
    )
    return ret


def surface_average_execute(
    params: SurfaceAverageParamsDict,
    runner: Runner | None = None,
) -> SurfaceAverageOutputs:
    """
    AVERAGE SURFACE FILES TOGETHER.
    
    The 3D sample standard deviation is computed as 'sqrt(sum(squaredlength(xyz
    - mean(xyz)))/(n - 1))'.
    
    Uncertainty is a legacy measure used in caret5, and is computed as
    'sum(length(xyz - mean(xyz)))/n'.
    
    When weights are used, the 3D sample standard deviation treats them as
    reliability weights.
    
    Args:
        params: The parameters.
        runner: Command runner.
    Returns:
        NamedTuple of outputs (described in `SurfaceAverageOutputs`).
    """
    surface_average_validate(params)
    runner = runner or get_global_runner()
    execution = runner.start_execution(SURFACE_AVERAGE_METADATA)
    params = execution.params(params)
    cargs = surface_average_cargs(params, execution)
    ret = surface_average_outputs(params, execution)
    execution.run(cargs)
    return ret


def surface_average(
    surface_out: str,
    stddev: SurfaceAverageStddevParamsDict | None = None,
    uncertainty: SurfaceAverageUncertaintyParamsDict | None = None,
    surf: list[SurfaceAverageSurfParamsDict] | None = None,
    runner: Runner | None = None,
) -> SurfaceAverageOutputs:
    """
    AVERAGE SURFACE FILES TOGETHER.
    
    The 3D sample standard deviation is computed as 'sqrt(sum(squaredlength(xyz
    - mean(xyz)))/(n - 1))'.
    
    Uncertainty is a legacy measure used in caret5, and is computed as
    'sum(length(xyz - mean(xyz)))/n'.
    
    When weights are used, the 3D sample standard deviation treats them as
    reliability weights.
    
    Args:
        surface_out: the output averaged surface.
        stddev: compute 3D sample standard deviation.
        uncertainty: compute caret5 'uncertainty'.
        surf: specify a surface to include in the average.
        runner: Command runner.
    Returns:
        NamedTuple of outputs (described in `SurfaceAverageOutputs`).
    """
    params = surface_average_params(
        surface_out=surface_out,
        stddev=stddev,
        uncertainty=uncertainty,
        surf=surf,
    )
    return surface_average_execute(params, runner)


__all__ = [
    "SURFACE_AVERAGE_METADATA",
    "SurfaceAverageOutputs",
    "SurfaceAverageParamsDict",
    "SurfaceAverageParamsDictTagged",
    "SurfaceAverageStddevOutputs",
    "SurfaceAverageStddevParamsDict",
    "SurfaceAverageStddevParamsDictTagged",
    "SurfaceAverageSurfParamsDict",
    "SurfaceAverageSurfParamsDictTagged",
    "SurfaceAverageUncertaintyOutputs",
    "SurfaceAverageUncertaintyParamsDict",
    "SurfaceAverageUncertaintyParamsDictTagged",
    "surface_average",
    "surface_average_execute",
    "surface_average_params",
    "surface_average_stddev",
    "surface_average_surf",
    "surface_average_uncertainty",
]
