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

import typing
import pathlib
from styxdefs import *

VOLUME_DISTORTION_METADATA = Metadata(
    id="84c6e150f3059b96bf719ca37696b114cc3add00.boutiques",
    name="volume-distortion",
    package="workbench",
    container_image_tag="brainlife/connectome_workbench:1.5.0-freesurfer-update",
)


VolumeDistortionParameters = typing.TypedDict('VolumeDistortionParameters', {
    "@type": typing.NotRequired[typing.Literal["workbench/volume-distortion"]],
    "warpfield": str,
    "volume_out": str,
    "opt_fnirt_source_volume": typing.NotRequired[str | None],
    "opt_circular": bool,
    "opt_log2": bool,
})
VolumeDistortionParametersTagged = typing.TypedDict('VolumeDistortionParametersTagged', {
    "@type": typing.Literal["workbench/volume-distortion"],
    "warpfield": str,
    "volume_out": str,
    "opt_fnirt_source_volume": typing.NotRequired[str | None],
    "opt_circular": bool,
    "opt_log2": bool,
})


class VolumeDistortionOutputs(typing.NamedTuple):
    """
    Output object returned when calling `VolumeDistortionParameters(...)`.
    """
    root: OutputPathType
    """Output root folder. This is the root folder for all outputs."""
    volume_out: OutputPathType
    """the output distortion measures"""


def volume_distortion_params(
    warpfield: str,
    volume_out: str,
    opt_fnirt_source_volume: str | None = None,
    opt_circular: bool = False,
    opt_log2: bool = False,
) -> VolumeDistortionParametersTagged:
    """
    Build parameters.
    
    Args:
        warpfield: the warpfield to compute the distortion of.
        volume_out: the output distortion measures.
        opt_fnirt_source_volume: MUST be used if using a fnirt warpfield: the\
            source volume used when generating the warpfield.
        opt_circular: use the circle-based formula for the anisotropic measure.
        opt_log2: apply base-2 log transform.
    Returns:
        Parameter dictionary
    """
    params = {
        "@type": "workbench/volume-distortion",
        "warpfield": warpfield,
        "volume_out": volume_out,
        "opt_circular": opt_circular,
        "opt_log2": opt_log2,
    }
    if opt_fnirt_source_volume is not None:
        params["opt_fnirt_source_volume"] = opt_fnirt_source_volume
    return params


def volume_distortion_cargs(
    params: VolumeDistortionParameters,
    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("wb_command")
    cargs.append("-volume-distortion")
    cargs.append(params.get("warpfield", None))
    cargs.append(params.get("volume_out", None))
    if params.get("opt_fnirt_source_volume", None) is not None:
        cargs.extend([
            "-fnirt",
            params.get("opt_fnirt_source_volume", None)
        ])
    if params.get("opt_circular", False):
        cargs.append("-circular")
    if params.get("opt_log2", False):
        cargs.append("-log2")
    return cargs


def volume_distortion_outputs(
    params: VolumeDistortionParameters,
    execution: Execution,
) -> VolumeDistortionOutputs:
    """
    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 = VolumeDistortionOutputs(
        root=execution.output_file("."),
        volume_out=execution.output_file(params.get("volume_out", None)),
    )
    return ret


def volume_distortion_execute(
    params: VolumeDistortionParameters,
    runner: Runner | None = None,
) -> VolumeDistortionOutputs:
    """
    volume-distortion
    
    Calculate volume warpfield distortion.
    
    Calculates isotropic and anisotropic distortions in the volume warpfield. At
    each voxel, the gradient of the absolute warpfield is computed to obtain the
    local affine transforms for each voxel (jacobian matrices), and strain
    tensors are derived from them. The isotropic component (volumetric expansion
    ratio) is the product of the three principal strains. The default measure
    ('elongation') for the anisotropic component is the largest principal strain
    divided by the smallest.
    
    The -circular option instead calculates the anisotropic component by
    transforming the principal strains into log space, considering them as
    x-values of points on a circle 120 degrees apart, finds the circle's
    diameter, and transforms that back to a ratio.
    
    Author: Connectome Workbench Developers
    
    URL: https://github.com/Washington-University/workbench
    
    Args:
        params: The parameters.
        runner: Command runner.
    Returns:
        NamedTuple of outputs (described in `VolumeDistortionOutputs`).
    """
    runner = runner or get_global_runner()
    execution = runner.start_execution(VOLUME_DISTORTION_METADATA)
    params = execution.params(params)
    cargs = volume_distortion_cargs(params, execution)
    ret = volume_distortion_outputs(params, execution)
    execution.run(cargs)
    return ret


def volume_distortion(
    warpfield: str,
    volume_out: str,
    opt_fnirt_source_volume: str | None = None,
    opt_circular: bool = False,
    opt_log2: bool = False,
    runner: Runner | None = None,
) -> VolumeDistortionOutputs:
    """
    volume-distortion
    
    Calculate volume warpfield distortion.
    
    Calculates isotropic and anisotropic distortions in the volume warpfield. At
    each voxel, the gradient of the absolute warpfield is computed to obtain the
    local affine transforms for each voxel (jacobian matrices), and strain
    tensors are derived from them. The isotropic component (volumetric expansion
    ratio) is the product of the three principal strains. The default measure
    ('elongation') for the anisotropic component is the largest principal strain
    divided by the smallest.
    
    The -circular option instead calculates the anisotropic component by
    transforming the principal strains into log space, considering them as
    x-values of points on a circle 120 degrees apart, finds the circle's
    diameter, and transforms that back to a ratio.
    
    Author: Connectome Workbench Developers
    
    URL: https://github.com/Washington-University/workbench
    
    Args:
        warpfield: the warpfield to compute the distortion of.
        volume_out: the output distortion measures.
        opt_fnirt_source_volume: MUST be used if using a fnirt warpfield: the\
            source volume used when generating the warpfield.
        opt_circular: use the circle-based formula for the anisotropic measure.
        opt_log2: apply base-2 log transform.
        runner: Command runner.
    Returns:
        NamedTuple of outputs (described in `VolumeDistortionOutputs`).
    """
    params = volume_distortion_params(
        warpfield=warpfield,
        volume_out=volume_out,
        opt_fnirt_source_volume=opt_fnirt_source_volume,
        opt_circular=opt_circular,
        opt_log2=opt_log2,
    )
    return volume_distortion_execute(params, runner)


__all__ = [
    "VOLUME_DISTORTION_METADATA",
    "VolumeDistortionOutputs",
    "volume_distortion",
    "volume_distortion_execute",
    "volume_distortion_params",
]
