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

import typing
import pathlib
from styxdefs import *

CIFTI_EXTREMA_METADATA = Metadata(
    id="96cc4edc754b1196eb76c4a8761c2b9a9cc4593f.workbench",
    name="cifti-extrema",
    package="workbench",
    container_image_tag="nx10x/workbench:2.1.0",
)


_CiftiExtremaThresholdParamsDictNoTag = typing.TypedDict('_CiftiExtremaThresholdParamsDictNoTag', {
    "low": float,
    "high": float,
})
CiftiExtremaThresholdParamsDictTagged = typing.TypedDict('CiftiExtremaThresholdParamsDictTagged', {
    "@type": typing.Literal["threshold"],
    "low": float,
    "high": float,
})
CiftiExtremaThresholdParamsDict = _CiftiExtremaThresholdParamsDictNoTag | CiftiExtremaThresholdParamsDictTagged


_CiftiExtremaParamsDictNoTag = typing.TypedDict('_CiftiExtremaParamsDictNoTag', {
    "cifti": InputPathType,
    "surface-distance": float,
    "volume-distance": float,
    "direction": str,
    "cifti-out": str,
    "threshold": typing.NotRequired[CiftiExtremaThresholdParamsDict | None],
    "volume-kernel": typing.NotRequired[float | None],
    "surface-kernel": typing.NotRequired[float | None],
    "surface": typing.NotRequired[InputPathType | None],
    "surface": typing.NotRequired[InputPathType | None],
    "surface": typing.NotRequired[InputPathType | None],
    "only-minima": bool,
    "only-maxima": bool,
    "consolidate-mode": bool,
    "sum-maps": bool,
    "merged-volume": bool,
    "presmooth-fwhm": bool,
})
CiftiExtremaParamsDictTagged = typing.TypedDict('CiftiExtremaParamsDictTagged', {
    "@type": typing.Literal["workbench/cifti-extrema"],
    "cifti": InputPathType,
    "surface-distance": float,
    "volume-distance": float,
    "direction": str,
    "cifti-out": str,
    "threshold": typing.NotRequired[CiftiExtremaThresholdParamsDict | None],
    "volume-kernel": typing.NotRequired[float | None],
    "surface-kernel": typing.NotRequired[float | None],
    "surface": typing.NotRequired[InputPathType | None],
    "surface": typing.NotRequired[InputPathType | None],
    "surface": typing.NotRequired[InputPathType | None],
    "only-minima": bool,
    "only-maxima": bool,
    "consolidate-mode": bool,
    "sum-maps": bool,
    "merged-volume": bool,
    "presmooth-fwhm": bool,
})
CiftiExtremaParamsDict = _CiftiExtremaParamsDictNoTag | CiftiExtremaParamsDictTagged


def cifti_extrema_threshold(
    low: float,
    high: float,
) -> CiftiExtremaThresholdParamsDictTagged:
    """
    Build parameters.
    
    Args:
        low: the largest value to consider for being a minimum.
        high: the smallest value to consider for being a maximum.
    Returns:
        Parameter dictionary
    """
    params = {
        "@type": "threshold",
        "low": low,
        "high": high,
    }
    return params


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


def cifti_extrema_threshold_cargs(
    params: CiftiExtremaThresholdParamsDict,
    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([
        "-threshold",
        str(params.get("low", None)),
        str(params.get("high", None))
    ])
    return cargs


class CiftiExtremaOutputs(typing.NamedTuple):
    """
    Output object returned when calling `CiftiExtremaParamsDict(...)`.
    """
    root: OutputPathType
    """Output root folder. This is the root folder for all outputs."""
    cifti_out: OutputPathType
    """the output cifti"""


def cifti_extrema_params(
    cifti: InputPathType,
    surface_distance: float,
    volume_distance: float,
    direction: str,
    cifti_out: str,
    threshold: CiftiExtremaThresholdParamsDict | None = None,
    volume_kernel: float | None = None,
    surface_kernel: float | None = None,
    surface: InputPathType | None = None,
    surface_: InputPathType | None = None,
    surface_2: InputPathType | None = None,
    only_minima: bool = False,
    only_maxima: bool = False,
    consolidate_mode: bool = False,
    sum_maps: bool = False,
    merged_volume: bool = False,
    presmooth_fwhm: bool = False,
) -> CiftiExtremaParamsDictTagged:
    """
    Build parameters.
    
    Args:
        cifti: the input cifti.
        surface_distance: the minimum distance between extrema of the same\
            type, for surface components.
        volume_distance: the minimum distance between extrema of the same type,\
            for volume components.
        direction: which dimension to find extrema along, ROW or COLUMN.
        cifti_out: the output cifti.
        threshold: ignore small extrema.
        volume_kernel: smooth volume components before finding extrema\
            \
            the size of the gaussian volume smoothing kernel in mm, as sigma by\
            default.
        surface_kernel: smooth on the surface before finding extrema\
            \
            the size of the gaussian surface smoothing kernel in mm, as sigma\
            by default.
        surface: specify the cerebellum surface to use\
            \
            the cerebellum surface file.
        surface_: specify the right surface to use\
            \
            the right surface file.
        surface_2: specify the left surface to use\
            \
            the left surface file.
        only_minima: only find the minima.
        only_maxima: only find the maxima.
        consolidate_mode: use consolidation of local minima instead of a large\
            neighborhood.
        sum_maps: output the sum of the extrema maps instead of each map\
            separately.
        merged_volume: treat volume components as if they were a single\
            component.
        presmooth_fwhm: smoothing kernel distances are FWHM, not sigma.
    Returns:
        Parameter dictionary
    """
    params = {
        "@type": "workbench/cifti-extrema",
        "cifti": cifti,
        "surface-distance": surface_distance,
        "volume-distance": volume_distance,
        "direction": direction,
        "cifti-out": cifti_out,
        "only-minima": only_minima,
        "only-maxima": only_maxima,
        "consolidate-mode": consolidate_mode,
        "sum-maps": sum_maps,
        "merged-volume": merged_volume,
        "presmooth-fwhm": presmooth_fwhm,
    }
    if threshold is not None:
        params["threshold"] = threshold
    if volume_kernel is not None:
        params["volume-kernel"] = volume_kernel
    if surface_kernel is not None:
        params["surface-kernel"] = surface_kernel
    if surface is not None:
        params["surface"] = surface
    if surface_ is not None:
        params["surface"] = surface_
    if surface_2 is not None:
        params["surface"] = surface_2
    return params


def cifti_extrema_validate(
    params: typing.Any,
) -> None:
    """
    Validate parameters. Throws an error if `params` is not a valid
    `CiftiExtremaParamsDict` 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", None) is None:
        raise StyxValidationError("`cifti` must not be None")
    if not isinstance(params["cifti"], (pathlib.Path, str)):
        raise StyxValidationError(f'`cifti` has the wrong type: Received `{type(params.get("cifti", None))}` expected `InputPathType`')
    if params.get("surface-distance", None) is None:
        raise StyxValidationError("`surface-distance` must not be None")
    if not isinstance(params["surface-distance"], (float, int)):
        raise StyxValidationError(f'`surface-distance` has the wrong type: Received `{type(params.get("surface-distance", None))}` expected `float`')
    if params.get("volume-distance", None) is None:
        raise StyxValidationError("`volume-distance` must not be None")
    if not isinstance(params["volume-distance"], (float, int)):
        raise StyxValidationError(f'`volume-distance` has the wrong type: Received `{type(params.get("volume-distance", None))}` expected `float`')
    if params.get("direction", None) is None:
        raise StyxValidationError("`direction` must not be None")
    if not isinstance(params["direction"], str):
        raise StyxValidationError(f'`direction` has the wrong type: Received `{type(params.get("direction", None))}` expected `str`')
    if params.get("cifti-out", None) is None:
        raise StyxValidationError("`cifti-out` must not be None")
    if not isinstance(params["cifti-out"], str):
        raise StyxValidationError(f'`cifti-out` has the wrong type: Received `{type(params.get("cifti-out", None))}` expected `str`')
    if params.get("threshold", None) is not None:
        cifti_extrema_threshold_validate(params["threshold"])
    if params.get("volume-kernel", None) is not None:
        if not isinstance(params["volume-kernel"], (float, int)):
            raise StyxValidationError(f'`volume-kernel` has the wrong type: Received `{type(params.get("volume-kernel", None))}` expected `float | None`')
    if params.get("surface-kernel", None) is not None:
        if not isinstance(params["surface-kernel"], (float, int)):
            raise StyxValidationError(f'`surface-kernel` has the wrong type: Received `{type(params.get("surface-kernel", None))}` expected `float | None`')
    if params.get("surface", None) is not 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 | None`')
    if params.get("surface", None) is not 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 | None`')
    if params.get("surface", None) is not 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 | None`')
    if params.get("only-minima", False) is None:
        raise StyxValidationError("`only-minima` must not be None")
    if not isinstance(params["only-minima"], bool):
        raise StyxValidationError(f'`only-minima` has the wrong type: Received `{type(params.get("only-minima", False))}` expected `bool`')
    if params.get("only-maxima", False) is None:
        raise StyxValidationError("`only-maxima` must not be None")
    if not isinstance(params["only-maxima"], bool):
        raise StyxValidationError(f'`only-maxima` has the wrong type: Received `{type(params.get("only-maxima", False))}` expected `bool`')
    if params.get("consolidate-mode", False) is None:
        raise StyxValidationError("`consolidate-mode` must not be None")
    if not isinstance(params["consolidate-mode"], bool):
        raise StyxValidationError(f'`consolidate-mode` has the wrong type: Received `{type(params.get("consolidate-mode", False))}` expected `bool`')
    if params.get("sum-maps", False) is None:
        raise StyxValidationError("`sum-maps` must not be None")
    if not isinstance(params["sum-maps"], bool):
        raise StyxValidationError(f'`sum-maps` has the wrong type: Received `{type(params.get("sum-maps", False))}` expected `bool`')
    if params.get("merged-volume", False) is None:
        raise StyxValidationError("`merged-volume` must not be None")
    if not isinstance(params["merged-volume"], bool):
        raise StyxValidationError(f'`merged-volume` has the wrong type: Received `{type(params.get("merged-volume", False))}` expected `bool`')
    if params.get("presmooth-fwhm", False) is None:
        raise StyxValidationError("`presmooth-fwhm` must not be None")
    if not isinstance(params["presmooth-fwhm"], bool):
        raise StyxValidationError(f'`presmooth-fwhm` has the wrong type: Received `{type(params.get("presmooth-fwhm", False))}` expected `bool`')


def cifti_extrema_cargs(
    params: CiftiExtremaParamsDict,
    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-extrema"
    ])
    cargs.append(execution.input_file(params.get("cifti", None)))
    cargs.append(str(params.get("surface-distance", None)))
    cargs.append(str(params.get("volume-distance", None)))
    cargs.append(params.get("direction", None))
    cargs.append(params.get("cifti-out", None))
    if params.get("threshold", None) is not None:
        cargs.extend(cifti_extrema_threshold_cargs(params.get("threshold", None), execution))
    if params.get("volume-kernel", None) is not None:
        cargs.extend([
            "-volume-presmooth",
            str(params.get("volume-kernel", None))
        ])
    if params.get("surface-kernel", None) is not None:
        cargs.extend([
            "-surface-presmooth",
            str(params.get("surface-kernel", None))
        ])
    if params.get("surface", None) is not None:
        cargs.extend([
            "-cerebellum-surface",
            execution.input_file(params.get("surface", None))
        ])
    if params.get("surface", None) is not None:
        cargs.extend([
            "-right-surface",
            execution.input_file(params.get("surface", None))
        ])
    if params.get("surface", None) is not None:
        cargs.extend([
            "-left-surface",
            execution.input_file(params.get("surface", None))
        ])
    if params.get("only-minima", False):
        cargs.append("-only-minima")
    if params.get("only-maxima", False):
        cargs.append("-only-maxima")
    if params.get("consolidate-mode", False):
        cargs.append("-consolidate-mode")
    if params.get("sum-maps", False):
        cargs.append("-sum-maps")
    if params.get("merged-volume", False):
        cargs.append("-merged-volume")
    if params.get("presmooth-fwhm", False):
        cargs.append("-presmooth-fwhm")
    return cargs


def cifti_extrema_outputs(
    params: CiftiExtremaParamsDict,
    execution: Execution,
) -> CiftiExtremaOutputs:
    """
    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 = CiftiExtremaOutputs(
        root=execution.output_file("."),
        cifti_out=execution.output_file(params.get("cifti-out", None)),
    )
    return ret


def cifti_extrema_execute(
    params: CiftiExtremaParamsDict,
    runner: Runner | None = None,
) -> CiftiExtremaOutputs:
    """
    FIND EXTREMA IN A CIFTI FILE.
    
    Finds spatial locations in a cifti file that have more extreme values than
    all nearby locations in the same component (surface or volume structure).
    The input cifti file must have a brain models mapping along the specified
    direction. COLUMN is the direction that works on dtseries and dscalar. For
    dconn, if it is symmetric use COLUMN, otherwise use ROW.
    
    Args:
        params: The parameters.
        runner: Command runner.
    Returns:
        NamedTuple of outputs (described in `CiftiExtremaOutputs`).
    """
    cifti_extrema_validate(params)
    runner = runner or get_global_runner()
    execution = runner.start_execution(CIFTI_EXTREMA_METADATA)
    params = execution.params(params)
    cargs = cifti_extrema_cargs(params, execution)
    ret = cifti_extrema_outputs(params, execution)
    execution.run(cargs)
    return ret


def cifti_extrema(
    cifti: InputPathType,
    surface_distance: float,
    volume_distance: float,
    direction: str,
    cifti_out: str,
    threshold: CiftiExtremaThresholdParamsDict | None = None,
    volume_kernel: float | None = None,
    surface_kernel: float | None = None,
    surface: InputPathType | None = None,
    surface_: InputPathType | None = None,
    surface_2: InputPathType | None = None,
    only_minima: bool = False,
    only_maxima: bool = False,
    consolidate_mode: bool = False,
    sum_maps: bool = False,
    merged_volume: bool = False,
    presmooth_fwhm: bool = False,
    runner: Runner | None = None,
) -> CiftiExtremaOutputs:
    """
    FIND EXTREMA IN A CIFTI FILE.
    
    Finds spatial locations in a cifti file that have more extreme values than
    all nearby locations in the same component (surface or volume structure).
    The input cifti file must have a brain models mapping along the specified
    direction. COLUMN is the direction that works on dtseries and dscalar. For
    dconn, if it is symmetric use COLUMN, otherwise use ROW.
    
    Args:
        cifti: the input cifti.
        surface_distance: the minimum distance between extrema of the same\
            type, for surface components.
        volume_distance: the minimum distance between extrema of the same type,\
            for volume components.
        direction: which dimension to find extrema along, ROW or COLUMN.
        cifti_out: the output cifti.
        threshold: ignore small extrema.
        volume_kernel: smooth volume components before finding extrema\
            \
            the size of the gaussian volume smoothing kernel in mm, as sigma by\
            default.
        surface_kernel: smooth on the surface before finding extrema\
            \
            the size of the gaussian surface smoothing kernel in mm, as sigma\
            by default.
        surface: specify the cerebellum surface to use\
            \
            the cerebellum surface file.
        surface_: specify the right surface to use\
            \
            the right surface file.
        surface_2: specify the left surface to use\
            \
            the left surface file.
        only_minima: only find the minima.
        only_maxima: only find the maxima.
        consolidate_mode: use consolidation of local minima instead of a large\
            neighborhood.
        sum_maps: output the sum of the extrema maps instead of each map\
            separately.
        merged_volume: treat volume components as if they were a single\
            component.
        presmooth_fwhm: smoothing kernel distances are FWHM, not sigma.
        runner: Command runner.
    Returns:
        NamedTuple of outputs (described in `CiftiExtremaOutputs`).
    """
    params = cifti_extrema_params(
        cifti=cifti,
        surface_distance=surface_distance,
        volume_distance=volume_distance,
        direction=direction,
        cifti_out=cifti_out,
        threshold=threshold,
        volume_kernel=volume_kernel,
        surface_kernel=surface_kernel,
        surface=surface,
        surface_=surface_,
        surface_2=surface_2,
        only_minima=only_minima,
        only_maxima=only_maxima,
        consolidate_mode=consolidate_mode,
        sum_maps=sum_maps,
        merged_volume=merged_volume,
        presmooth_fwhm=presmooth_fwhm,
    )
    return cifti_extrema_execute(params, runner)


__all__ = [
    "CIFTI_EXTREMA_METADATA",
    "CiftiExtremaOutputs",
    "CiftiExtremaParamsDict",
    "CiftiExtremaParamsDictTagged",
    "CiftiExtremaThresholdParamsDict",
    "CiftiExtremaThresholdParamsDictTagged",
    "cifti_extrema",
    "cifti_extrema_execute",
    "cifti_extrema_params",
    "cifti_extrema_threshold",
]
