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

import typing
import pathlib
from styxdefs import *

CIFTI_WEIGHTED_STATS_METADATA = Metadata(
    id="014a1bf95b4718c304bf3aa95e26fa00e131122c.workbench",
    name="cifti-weighted-stats",
    package="workbench",
    container_image_tag="nx10x/workbench:2.1.0",
)


_CiftiWeightedStatsSpatialWeightsParamsDictNoTag = typing.TypedDict('_CiftiWeightedStatsSpatialWeightsParamsDictNoTag', {
    "cerebellum-metric": typing.NotRequired[InputPathType | None],
    "right-metric": typing.NotRequired[InputPathType | None],
    "left-metric": typing.NotRequired[InputPathType | None],
    "cerebellum-surf": typing.NotRequired[InputPathType | None],
    "right-surf": typing.NotRequired[InputPathType | None],
    "left-surf": typing.NotRequired[InputPathType | None],
})
CiftiWeightedStatsSpatialWeightsParamsDictTagged = typing.TypedDict('CiftiWeightedStatsSpatialWeightsParamsDictTagged', {
    "@type": typing.Literal["spatial-weights"],
    "cerebellum-metric": typing.NotRequired[InputPathType | None],
    "right-metric": typing.NotRequired[InputPathType | None],
    "left-metric": typing.NotRequired[InputPathType | None],
    "cerebellum-surf": typing.NotRequired[InputPathType | None],
    "right-surf": typing.NotRequired[InputPathType | None],
    "left-surf": typing.NotRequired[InputPathType | None],
})
CiftiWeightedStatsSpatialWeightsParamsDict = _CiftiWeightedStatsSpatialWeightsParamsDictNoTag | CiftiWeightedStatsSpatialWeightsParamsDictTagged


_CiftiWeightedStatsRoiParamsDictNoTag = typing.TypedDict('_CiftiWeightedStatsRoiParamsDictNoTag', {
    "roi-cifti": InputPathType,
    "match-maps": bool,
})
CiftiWeightedStatsRoiParamsDictTagged = typing.TypedDict('CiftiWeightedStatsRoiParamsDictTagged', {
    "@type": typing.Literal["roi"],
    "roi-cifti": InputPathType,
    "match-maps": bool,
})
CiftiWeightedStatsRoiParamsDict = _CiftiWeightedStatsRoiParamsDictNoTag | CiftiWeightedStatsRoiParamsDictTagged


_CiftiWeightedStatsParamsDictNoTag = typing.TypedDict('_CiftiWeightedStatsParamsDictNoTag', {
    "cifti-in": InputPathType,
    "spatial-weights": typing.NotRequired[CiftiWeightedStatsSpatialWeightsParamsDict | None],
    "roi": typing.NotRequired[CiftiWeightedStatsRoiParamsDict | None],
    "percent": typing.NotRequired[float | None],
    "sample": typing.NotRequired[bool | None],
    "column": typing.NotRequired[int | None],
    "weight-cifti": typing.NotRequired[InputPathType | None],
    "show-map-name": bool,
    "sum": bool,
    "mean": bool,
})
CiftiWeightedStatsParamsDictTagged = typing.TypedDict('CiftiWeightedStatsParamsDictTagged', {
    "@type": typing.Literal["workbench/cifti-weighted-stats"],
    "cifti-in": InputPathType,
    "spatial-weights": typing.NotRequired[CiftiWeightedStatsSpatialWeightsParamsDict | None],
    "roi": typing.NotRequired[CiftiWeightedStatsRoiParamsDict | None],
    "percent": typing.NotRequired[float | None],
    "sample": typing.NotRequired[bool | None],
    "column": typing.NotRequired[int | None],
    "weight-cifti": typing.NotRequired[InputPathType | None],
    "show-map-name": bool,
    "sum": bool,
    "mean": bool,
})
CiftiWeightedStatsParamsDict = _CiftiWeightedStatsParamsDictNoTag | CiftiWeightedStatsParamsDictTagged


def cifti_weighted_stats_spatial_weights(
    cerebellum_metric: InputPathType | None = None,
    right_metric: InputPathType | None = None,
    left_metric: InputPathType | None = None,
    cerebellum_surf: InputPathType | None = None,
    right_surf: InputPathType | None = None,
    left_surf: InputPathType | None = None,
) -> CiftiWeightedStatsSpatialWeightsParamsDictTagged:
    """
    Build parameters.
    
    Args:
        cerebellum_metric: use a metric file for cerebellum vertex areas\
            \
            metric file containing cerebellum vertex areas.
        right_metric: use a metric file for right vertex areas\
            \
            metric file containing right vertex areas.
        left_metric: use a metric file for left vertex areas\
            \
            metric file containing left vertex areas.
        cerebellum_surf: use a surface for cerebellum vertex areas\
            \
            the cerebellum surface to use, areas are in mm^2.
        right_surf: use a surface for right vertex areas\
            \
            the right surface to use, areas are in mm^2.
        left_surf: use a surface for left vertex areas\
            \
            the left surface to use, areas are in mm^2.
    Returns:
        Parameter dictionary
    """
    params = {
        "@type": "spatial-weights",
    }
    if cerebellum_metric is not None:
        params["cerebellum-metric"] = cerebellum_metric
    if right_metric is not None:
        params["right-metric"] = right_metric
    if left_metric is not None:
        params["left-metric"] = left_metric
    if cerebellum_surf is not None:
        params["cerebellum-surf"] = cerebellum_surf
    if right_surf is not None:
        params["right-surf"] = right_surf
    if left_surf is not None:
        params["left-surf"] = left_surf
    return params


def cifti_weighted_stats_spatial_weights_validate(
    params: typing.Any,
) -> None:
    """
    Validate parameters. Throws an error if `params` is not a valid
    `CiftiWeightedStatsSpatialWeightsParamsDict` 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("cerebellum-metric", None) is not None:
        if not isinstance(params["cerebellum-metric"], (pathlib.Path, str)):
            raise StyxValidationError(f'`cerebellum-metric` has the wrong type: Received `{type(params.get("cerebellum-metric", None))}` expected `InputPathType | None`')
    if params.get("right-metric", None) is not None:
        if not isinstance(params["right-metric"], (pathlib.Path, str)):
            raise StyxValidationError(f'`right-metric` has the wrong type: Received `{type(params.get("right-metric", None))}` expected `InputPathType | None`')
    if params.get("left-metric", None) is not None:
        if not isinstance(params["left-metric"], (pathlib.Path, str)):
            raise StyxValidationError(f'`left-metric` has the wrong type: Received `{type(params.get("left-metric", None))}` expected `InputPathType | None`')
    if params.get("cerebellum-surf", None) is not None:
        if not isinstance(params["cerebellum-surf"], (pathlib.Path, str)):
            raise StyxValidationError(f'`cerebellum-surf` has the wrong type: Received `{type(params.get("cerebellum-surf", None))}` expected `InputPathType | None`')
    if params.get("right-surf", None) is not None:
        if not isinstance(params["right-surf"], (pathlib.Path, str)):
            raise StyxValidationError(f'`right-surf` has the wrong type: Received `{type(params.get("right-surf", None))}` expected `InputPathType | None`')
    if params.get("left-surf", None) is not None:
        if not isinstance(params["left-surf"], (pathlib.Path, str)):
            raise StyxValidationError(f'`left-surf` has the wrong type: Received `{type(params.get("left-surf", None))}` expected `InputPathType | None`')


def cifti_weighted_stats_spatial_weights_cargs(
    params: CiftiWeightedStatsSpatialWeightsParamsDict,
    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("-spatial-weights")
    if params.get("cerebellum-metric", None) is not None:
        cargs.extend([
            "-cerebellum-area-metric",
            execution.input_file(params.get("cerebellum-metric", None))
        ])
    if params.get("right-metric", None) is not None:
        cargs.extend([
            "-right-area-metric",
            execution.input_file(params.get("right-metric", None))
        ])
    if params.get("left-metric", None) is not None:
        cargs.extend([
            "-left-area-metric",
            execution.input_file(params.get("left-metric", None))
        ])
    if params.get("cerebellum-surf", None) is not None:
        cargs.extend([
            "-cerebellum-area-surf",
            execution.input_file(params.get("cerebellum-surf", None))
        ])
    if params.get("right-surf", None) is not None:
        cargs.extend([
            "-right-area-surf",
            execution.input_file(params.get("right-surf", None))
        ])
    if params.get("left-surf", None) is not None:
        cargs.extend([
            "-left-area-surf",
            execution.input_file(params.get("left-surf", None))
        ])
    return cargs


def cifti_weighted_stats_roi(
    roi_cifti: InputPathType,
    match_maps: bool = False,
) -> CiftiWeightedStatsRoiParamsDictTagged:
    """
    Build parameters.
    
    Args:
        roi_cifti: the roi, as a cifti file.
        match_maps: each column of input uses the corresponding column from the\
            roi file.
    Returns:
        Parameter dictionary
    """
    params = {
        "@type": "roi",
        "roi-cifti": roi_cifti,
        "match-maps": match_maps,
    }
    return params


def cifti_weighted_stats_roi_validate(
    params: typing.Any,
) -> None:
    """
    Validate parameters. Throws an error if `params` is not a valid
    `CiftiWeightedStatsRoiParamsDict` 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("roi-cifti", None) is None:
        raise StyxValidationError("`roi-cifti` must not be None")
    if not isinstance(params["roi-cifti"], (pathlib.Path, str)):
        raise StyxValidationError(f'`roi-cifti` has the wrong type: Received `{type(params.get("roi-cifti", None))}` expected `InputPathType`')
    if params.get("match-maps", False) is None:
        raise StyxValidationError("`match-maps` must not be None")
    if not isinstance(params["match-maps"], bool):
        raise StyxValidationError(f'`match-maps` has the wrong type: Received `{type(params.get("match-maps", False))}` expected `bool`')


def cifti_weighted_stats_roi_cargs(
    params: CiftiWeightedStatsRoiParamsDict,
    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([
        "-roi",
        execution.input_file(params.get("roi-cifti", None))
    ])
    if params.get("match-maps", False):
        cargs.append("-match-maps")
    return cargs


class CiftiWeightedStatsOutputs(typing.NamedTuple):
    """
    Output object returned when calling `CiftiWeightedStatsParamsDict(...)`.
    """
    root: OutputPathType
    """Output root folder. This is the root folder for all outputs."""


def cifti_weighted_stats_params(
    cifti_in: InputPathType,
    spatial_weights: CiftiWeightedStatsSpatialWeightsParamsDict | None = None,
    roi: CiftiWeightedStatsRoiParamsDict | None = None,
    percent: float | None = None,
    sample: bool | None = None,
    column: int | None = None,
    weight_cifti: InputPathType | None = None,
    show_map_name: bool = False,
    sum_: bool = False,
    mean: bool = False,
) -> CiftiWeightedStatsParamsDictTagged:
    """
    Build parameters.
    
    Args:
        cifti_in: the input cifti.
        spatial_weights: use vertex area and voxel volume as weights.
        roi: only consider data inside an roi.
        percent: compute weighted percentile\
            \
            the percentile to find, must be between 0 and 100.
        sample: compute weighted standard deviation\
            \
            estimate population stdev from the sample.
        column: only display output for one column\
            \
            the column to use (1-based).
        weight_cifti: use a cifti file containing weights\
            \
            the weights to use, as a cifti file.
        show_map_name: print map index and name before each output.
        sum_: compute weighted sum.
        mean: compute weighted mean.
    Returns:
        Parameter dictionary
    """
    params = {
        "@type": "workbench/cifti-weighted-stats",
        "cifti-in": cifti_in,
        "show-map-name": show_map_name,
        "sum": sum_,
        "mean": mean,
    }
    if spatial_weights is not None:
        params["spatial-weights"] = spatial_weights
    if roi is not None:
        params["roi"] = roi
    if percent is not None:
        params["percent"] = percent
    if sample is not None:
        params["sample"] = sample
    if column is not None:
        params["column"] = column
    if weight_cifti is not None:
        params["weight-cifti"] = weight_cifti
    return params


def cifti_weighted_stats_validate(
    params: typing.Any,
) -> None:
    """
    Validate parameters. Throws an error if `params` is not a valid
    `CiftiWeightedStatsParamsDict` 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("cifti-in", None) is None:
        raise StyxValidationError("`cifti-in` must not be None")
    if not isinstance(params["cifti-in"], (pathlib.Path, str)):
        raise StyxValidationError(f'`cifti-in` has the wrong type: Received `{type(params.get("cifti-in", None))}` expected `InputPathType`')
    if params.get("spatial-weights", None) is not None:
        cifti_weighted_stats_spatial_weights_validate(params["spatial-weights"])
    if params.get("roi", None) is not None:
        cifti_weighted_stats_roi_validate(params["roi"])
    if params.get("percent", None) is not None:
        if not isinstance(params["percent"], (float, int)):
            raise StyxValidationError(f'`percent` has the wrong type: Received `{type(params.get("percent", None))}` expected `float | None`')
    if params.get("sample", None) is not None:
        if not isinstance(params["sample"], bool):
            raise StyxValidationError(f'`sample` has the wrong type: Received `{type(params.get("sample", None))}` expected `bool | None`')
    if params.get("column", None) is not None:
        if not isinstance(params["column"], int):
            raise StyxValidationError(f'`column` has the wrong type: Received `{type(params.get("column", None))}` expected `int | None`')
    if params.get("weight-cifti", None) is not None:
        if not isinstance(params["weight-cifti"], (pathlib.Path, str)):
            raise StyxValidationError(f'`weight-cifti` has the wrong type: Received `{type(params.get("weight-cifti", None))}` expected `InputPathType | None`')
    if params.get("show-map-name", False) is None:
        raise StyxValidationError("`show-map-name` must not be None")
    if not isinstance(params["show-map-name"], bool):
        raise StyxValidationError(f'`show-map-name` has the wrong type: Received `{type(params.get("show-map-name", False))}` expected `bool`')
    if params.get("sum", False) is None:
        raise StyxValidationError("`sum` must not be None")
    if not isinstance(params["sum"], bool):
        raise StyxValidationError(f'`sum` has the wrong type: Received `{type(params.get("sum", False))}` expected `bool`')
    if params.get("mean", False) is None:
        raise StyxValidationError("`mean` must not be None")
    if not isinstance(params["mean"], bool):
        raise StyxValidationError(f'`mean` has the wrong type: Received `{type(params.get("mean", False))}` expected `bool`')


def cifti_weighted_stats_cargs(
    params: CiftiWeightedStatsParamsDict,
    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",
        "-cifti-weighted-stats"
    ])
    cargs.append(execution.input_file(params.get("cifti-in", None)))
    if params.get("spatial-weights", None) is not None or params.get("roi", None) is not None:
        cargs.extend([
            *(cifti_weighted_stats_spatial_weights_cargs(params.get("spatial-weights", None), execution) if (params.get("spatial-weights", None) is not None) else []),
            *(cifti_weighted_stats_roi_cargs(params.get("roi", None), execution) if (params.get("roi", None) is not None) else [])
        ])
    if params.get("percent", None) is not None:
        cargs.extend([
            "-percentile",
            str(params.get("percent", None))
        ])
    if params.get("sample", None) is not None:
        cargs.extend([
            "-stdev",
            "-sample"
        ])
    if params.get("column", None) is not None:
        cargs.extend([
            "-column",
            str(params.get("column", None))
        ])
    if params.get("weight-cifti", None) is not None:
        cargs.extend([
            "-cifti-weights",
            execution.input_file(params.get("weight-cifti", None))
        ])
    if params.get("show-map-name", False):
        cargs.append("-show-map-name")
    if params.get("sum", False):
        cargs.append("-sum")
    if params.get("mean", False):
        cargs.append("-mean")
    return cargs


def cifti_weighted_stats_outputs(
    params: CiftiWeightedStatsParamsDict,
    execution: Execution,
) -> CiftiWeightedStatsOutputs:
    """
    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 = CiftiWeightedStatsOutputs(
        root=execution.output_file("."),
    )
    return ret


def cifti_weighted_stats_execute(
    params: CiftiWeightedStatsParamsDict,
    runner: Runner | None = None,
) -> CiftiWeightedStatsOutputs:
    """
    WEIGHTED STATISTICS ALONG CIFTI COLUMNS.
    
    If the mapping along column is brain models, for each column of the input,
    the specified operation is done on each surface and across all voxels, and
    the results are printed on separate lines. For other mapping types, the
    operation is done on each column, and one line per map is printed. Exactly
    one of -spatial-weights or -cifti-weights must be specified. Use -column to
    only give output for a single column. If the -roi option is used without
    -match-maps, then each line will contain as many numbers as there are maps
    in the ROI file, separated by tab characters. Exactly one of -mean, -stdev,
    -percentile or -sum must be specified.
    
    Using -sum with -spatial-weights (or with -cifti-weights and a cifti
    containing weights of similar meaning) is equivalent to integrating with
    respect to area and volume. When the input is binary ROIs, this will
    therefore output the area or volume of each ROI.
    
    Args:
        params: The parameters.
        runner: Command runner.
    Returns:
        NamedTuple of outputs (described in `CiftiWeightedStatsOutputs`).
    """
    cifti_weighted_stats_validate(params)
    runner = runner or get_global_runner()
    execution = runner.start_execution(CIFTI_WEIGHTED_STATS_METADATA)
    params = execution.params(params)
    cargs = cifti_weighted_stats_cargs(params, execution)
    ret = cifti_weighted_stats_outputs(params, execution)
    execution.run(cargs)
    return ret


def cifti_weighted_stats(
    cifti_in: InputPathType,
    spatial_weights: CiftiWeightedStatsSpatialWeightsParamsDict | None = None,
    roi: CiftiWeightedStatsRoiParamsDict | None = None,
    percent: float | None = None,
    sample: bool | None = None,
    column: int | None = None,
    weight_cifti: InputPathType | None = None,
    show_map_name: bool = False,
    sum_: bool = False,
    mean: bool = False,
    runner: Runner | None = None,
) -> CiftiWeightedStatsOutputs:
    """
    WEIGHTED STATISTICS ALONG CIFTI COLUMNS.
    
    If the mapping along column is brain models, for each column of the input,
    the specified operation is done on each surface and across all voxels, and
    the results are printed on separate lines. For other mapping types, the
    operation is done on each column, and one line per map is printed. Exactly
    one of -spatial-weights or -cifti-weights must be specified. Use -column to
    only give output for a single column. If the -roi option is used without
    -match-maps, then each line will contain as many numbers as there are maps
    in the ROI file, separated by tab characters. Exactly one of -mean, -stdev,
    -percentile or -sum must be specified.
    
    Using -sum with -spatial-weights (or with -cifti-weights and a cifti
    containing weights of similar meaning) is equivalent to integrating with
    respect to area and volume. When the input is binary ROIs, this will
    therefore output the area or volume of each ROI.
    
    Args:
        cifti_in: the input cifti.
        spatial_weights: use vertex area and voxel volume as weights.
        roi: only consider data inside an roi.
        percent: compute weighted percentile\
            \
            the percentile to find, must be between 0 and 100.
        sample: compute weighted standard deviation\
            \
            estimate population stdev from the sample.
        column: only display output for one column\
            \
            the column to use (1-based).
        weight_cifti: use a cifti file containing weights\
            \
            the weights to use, as a cifti file.
        show_map_name: print map index and name before each output.
        sum_: compute weighted sum.
        mean: compute weighted mean.
        runner: Command runner.
    Returns:
        NamedTuple of outputs (described in `CiftiWeightedStatsOutputs`).
    """
    params = cifti_weighted_stats_params(
        cifti_in=cifti_in,
        spatial_weights=spatial_weights,
        roi=roi,
        percent=percent,
        sample=sample,
        column=column,
        weight_cifti=weight_cifti,
        show_map_name=show_map_name,
        sum_=sum_,
        mean=mean,
    )
    return cifti_weighted_stats_execute(params, runner)


__all__ = [
    "CIFTI_WEIGHTED_STATS_METADATA",
    "CiftiWeightedStatsOutputs",
    "CiftiWeightedStatsParamsDict",
    "CiftiWeightedStatsParamsDictTagged",
    "CiftiWeightedStatsRoiParamsDict",
    "CiftiWeightedStatsRoiParamsDictTagged",
    "CiftiWeightedStatsSpatialWeightsParamsDict",
    "CiftiWeightedStatsSpatialWeightsParamsDictTagged",
    "cifti_weighted_stats",
    "cifti_weighted_stats_execute",
    "cifti_weighted_stats_params",
    "cifti_weighted_stats_roi",
    "cifti_weighted_stats_spatial_weights",
]
