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

import typing
import pathlib
from styxdefs import *

SURFACE_GEODESIC_DISTANCE_ALL_TO_ALL_METADATA = Metadata(
    id="0be135c0c6479332f2fdfb0600eae50aaa990514.workbench",
    name="surface-geodesic-distance-all-to-all",
    package="workbench",
    container_image_tag="nx10x/workbench:2.1.0",
)


_SurfaceGeodesicDistanceAllToAllParamsDictNoTag = typing.TypedDict('_SurfaceGeodesicDistanceAllToAllParamsDictNoTag', {
    "surface": InputPathType,
    "cifti-out": str,
    "area-metric": typing.NotRequired[InputPathType | None],
    "limit-mm": typing.NotRequired[float | None],
    "roi-metric": typing.NotRequired[InputPathType | None],
    "naive": bool,
})
SurfaceGeodesicDistanceAllToAllParamsDictTagged = typing.TypedDict('SurfaceGeodesicDistanceAllToAllParamsDictTagged', {
    "@type": typing.Literal["workbench/surface-geodesic-distance-all-to-all"],
    "surface": InputPathType,
    "cifti-out": str,
    "area-metric": typing.NotRequired[InputPathType | None],
    "limit-mm": typing.NotRequired[float | None],
    "roi-metric": typing.NotRequired[InputPathType | None],
    "naive": bool,
})
SurfaceGeodesicDistanceAllToAllParamsDict = _SurfaceGeodesicDistanceAllToAllParamsDictNoTag | SurfaceGeodesicDistanceAllToAllParamsDictTagged


class SurfaceGeodesicDistanceAllToAllOutputs(typing.NamedTuple):
    """
    Output object returned when calling `SurfaceGeodesicDistanceAllToAllParamsDict(...)`.
    """
    root: OutputPathType
    """Output root folder. This is the root folder for all outputs."""
    cifti_out: OutputPathType
    """single-hemisphere dconn containing the distances"""


def surface_geodesic_distance_all_to_all_params(
    surface: InputPathType,
    cifti_out: str,
    area_metric: InputPathType | None = None,
    limit_mm: float | None = None,
    roi_metric: InputPathType | None = None,
    naive: bool = False,
) -> SurfaceGeodesicDistanceAllToAllParamsDictTagged:
    """
    Build parameters.
    
    Args:
        surface: the surface to compute on.
        cifti_out: single-hemisphere dconn containing the distances.
        area_metric: vertex areas to use to correct the distances on a\
            group-average surface\
            \
            the corrected vertex areas, as a metric.
        limit_mm: stop at a specified distance\
            \
            distance in mm to stop at.
        roi_metric: only output distances for vertices inside an ROI\
            \
            the ROI as a metric file.
        naive: use only neighbors, don't crawl triangles (not recommended).
    Returns:
        Parameter dictionary
    """
    params = {
        "@type": "workbench/surface-geodesic-distance-all-to-all",
        "surface": surface,
        "cifti-out": cifti_out,
        "naive": naive,
    }
    if area_metric is not None:
        params["area-metric"] = area_metric
    if limit_mm is not None:
        params["limit-mm"] = limit_mm
    if roi_metric is not None:
        params["roi-metric"] = roi_metric
    return params


def surface_geodesic_distance_all_to_all_validate(
    params: typing.Any,
) -> None:
    """
    Validate parameters. Throws an error if `params` is not a valid
    `SurfaceGeodesicDistanceAllToAllParamsDict` 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("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("area-metric", None) is not None:
        if not isinstance(params["area-metric"], (pathlib.Path, str)):
            raise StyxValidationError(f'`area-metric` has the wrong type: Received `{type(params.get("area-metric", None))}` expected `InputPathType | None`')
    if params.get("limit-mm", None) is not None:
        if not isinstance(params["limit-mm"], (float, int)):
            raise StyxValidationError(f'`limit-mm` has the wrong type: Received `{type(params.get("limit-mm", None))}` expected `float | None`')
    if params.get("roi-metric", None) is not None:
        if not isinstance(params["roi-metric"], (pathlib.Path, str)):
            raise StyxValidationError(f'`roi-metric` has the wrong type: Received `{type(params.get("roi-metric", None))}` expected `InputPathType | None`')
    if params.get("naive", False) is None:
        raise StyxValidationError("`naive` must not be None")
    if not isinstance(params["naive"], bool):
        raise StyxValidationError(f'`naive` has the wrong type: Received `{type(params.get("naive", False))}` expected `bool`')


def surface_geodesic_distance_all_to_all_cargs(
    params: SurfaceGeodesicDistanceAllToAllParamsDict,
    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-geodesic-distance-all-to-all"
    ])
    cargs.append(execution.input_file(params.get("surface", None)))
    cargs.append(params.get("cifti-out", None))
    if params.get("area-metric", None) is not None:
        cargs.extend([
            "-corrected-areas",
            execution.input_file(params.get("area-metric", None))
        ])
    if params.get("limit-mm", None) is not None:
        cargs.extend([
            "-limit",
            str(params.get("limit-mm", None))
        ])
    if params.get("roi-metric", None) is not None:
        cargs.extend([
            "-roi",
            execution.input_file(params.get("roi-metric", None))
        ])
    if params.get("naive", False):
        cargs.append("-naive")
    return cargs


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


def surface_geodesic_distance_all_to_all_execute(
    params: SurfaceGeodesicDistanceAllToAllParamsDict,
    runner: Runner | None = None,
) -> SurfaceGeodesicDistanceAllToAllOutputs:
    """
    COMPUTE GEODESIC DISTANCES FROM ALL VERTICES.
    
    Computes geodesic distance from every vertex to every vertex, outputting a
    single-hemisphere dconn file. If you are only interested in a few vertices,
    see -surface-geodesic-distance. When -limit is specified, any vertex beyond
    the limit is assigned the value -1.
    
    The -roi option makes the output file smaller by not outputting distances to
    or from vertices outside the ROI, but paths are still allowed to go outside
    the ROI when finding distances to other vertices.
    
    The -corrected-areas option should be used when the input is a group average
    surface - group average surfaces have significantly less surface area than
    individual surfaces do, and therefore distances measured on them would be
    smaller than measuring them on individual surfaces. In this case, the input
    to this option should be a group average of the output of
    -surface-vertex-areas for each subject.
    
    If -naive is not specified, the algorithm uses not just immediate neighbors,
    but also neighbors derived from crawling across pairs of triangles that
    share an edge.
    
    Args:
        params: The parameters.
        runner: Command runner.
    Returns:
        NamedTuple of outputs (described in `SurfaceGeodesicDistanceAllToAllOutputs`).
    """
    surface_geodesic_distance_all_to_all_validate(params)
    runner = runner or get_global_runner()
    execution = runner.start_execution(SURFACE_GEODESIC_DISTANCE_ALL_TO_ALL_METADATA)
    params = execution.params(params)
    cargs = surface_geodesic_distance_all_to_all_cargs(params, execution)
    ret = surface_geodesic_distance_all_to_all_outputs(params, execution)
    execution.run(cargs)
    return ret


def surface_geodesic_distance_all_to_all(
    surface: InputPathType,
    cifti_out: str,
    area_metric: InputPathType | None = None,
    limit_mm: float | None = None,
    roi_metric: InputPathType | None = None,
    naive: bool = False,
    runner: Runner | None = None,
) -> SurfaceGeodesicDistanceAllToAllOutputs:
    """
    COMPUTE GEODESIC DISTANCES FROM ALL VERTICES.
    
    Computes geodesic distance from every vertex to every vertex, outputting a
    single-hemisphere dconn file. If you are only interested in a few vertices,
    see -surface-geodesic-distance. When -limit is specified, any vertex beyond
    the limit is assigned the value -1.
    
    The -roi option makes the output file smaller by not outputting distances to
    or from vertices outside the ROI, but paths are still allowed to go outside
    the ROI when finding distances to other vertices.
    
    The -corrected-areas option should be used when the input is a group average
    surface - group average surfaces have significantly less surface area than
    individual surfaces do, and therefore distances measured on them would be
    smaller than measuring them on individual surfaces. In this case, the input
    to this option should be a group average of the output of
    -surface-vertex-areas for each subject.
    
    If -naive is not specified, the algorithm uses not just immediate neighbors,
    but also neighbors derived from crawling across pairs of triangles that
    share an edge.
    
    Args:
        surface: the surface to compute on.
        cifti_out: single-hemisphere dconn containing the distances.
        area_metric: vertex areas to use to correct the distances on a\
            group-average surface\
            \
            the corrected vertex areas, as a metric.
        limit_mm: stop at a specified distance\
            \
            distance in mm to stop at.
        roi_metric: only output distances for vertices inside an ROI\
            \
            the ROI as a metric file.
        naive: use only neighbors, don't crawl triangles (not recommended).
        runner: Command runner.
    Returns:
        NamedTuple of outputs (described in `SurfaceGeodesicDistanceAllToAllOutputs`).
    """
    params = surface_geodesic_distance_all_to_all_params(
        surface=surface,
        cifti_out=cifti_out,
        area_metric=area_metric,
        limit_mm=limit_mm,
        roi_metric=roi_metric,
        naive=naive,
    )
    return surface_geodesic_distance_all_to_all_execute(params, runner)


__all__ = [
    "SURFACE_GEODESIC_DISTANCE_ALL_TO_ALL_METADATA",
    "SurfaceGeodesicDistanceAllToAllOutputs",
    "SurfaceGeodesicDistanceAllToAllParamsDict",
    "SurfaceGeodesicDistanceAllToAllParamsDictTagged",
    "surface_geodesic_distance_all_to_all",
    "surface_geodesic_distance_all_to_all_execute",
    "surface_geodesic_distance_all_to_all_params",
]
