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

import typing
import pathlib
from styxdefs import *

AFDCONNECTIVITY_METADATA = Metadata(
    id="a6fb5580a7faf6e50bbcf57a2c6385623c779645.boutiques",
    name="afdconnectivity",
    package="mrtrix",
    container_image_tag="mrtrix3/mrtrix3:3.0.4",
)


_AfdconnectivityConfigParamsDictNoTag = typing.TypedDict('_AfdconnectivityConfigParamsDictNoTag', {
    "key": str,
    "value": str,
})
AfdconnectivityConfigParamsDictTagged = typing.TypedDict('AfdconnectivityConfigParamsDictTagged', {
    "@type": typing.Literal["config"],
    "key": str,
    "value": str,
})
AfdconnectivityConfigParamsDict = _AfdconnectivityConfigParamsDictNoTag | AfdconnectivityConfigParamsDictTagged


_AfdconnectivityParamsDictNoTag = typing.TypedDict('_AfdconnectivityParamsDictNoTag', {
    "wbft": typing.NotRequired[InputPathType | None],
    "afd_map": typing.NotRequired[str | None],
    "all_fixels": bool,
    "info": bool,
    "quiet": bool,
    "debug": bool,
    "force": bool,
    "nthreads": typing.NotRequired[int | None],
    "config": typing.NotRequired[list[AfdconnectivityConfigParamsDict] | None],
    "help": bool,
    "version": bool,
    "image": InputPathType,
    "tracks": InputPathType,
})
AfdconnectivityParamsDictTagged = typing.TypedDict('AfdconnectivityParamsDictTagged', {
    "@type": typing.Literal["mrtrix/afdconnectivity"],
    "wbft": typing.NotRequired[InputPathType | None],
    "afd_map": typing.NotRequired[str | None],
    "all_fixels": bool,
    "info": bool,
    "quiet": bool,
    "debug": bool,
    "force": bool,
    "nthreads": typing.NotRequired[int | None],
    "config": typing.NotRequired[list[AfdconnectivityConfigParamsDict] | None],
    "help": bool,
    "version": bool,
    "image": InputPathType,
    "tracks": InputPathType,
})
AfdconnectivityParamsDict = _AfdconnectivityParamsDictNoTag | AfdconnectivityParamsDictTagged


def afdconnectivity_config(
    key: str,
    value: str,
) -> AfdconnectivityConfigParamsDictTagged:
    """
    Build parameters.
    
    Args:
        key: temporarily set the value of an MRtrix config file entry.
        value: temporarily set the value of an MRtrix config file entry.
    Returns:
        Parameter dictionary
    """
    params = {
        "@type": "config",
        "key": key,
        "value": value,
    }
    return params


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


def afdconnectivity_config_cargs(
    params: AfdconnectivityConfigParamsDict,
    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("-config")
    cargs.append(params.get("key", None))
    cargs.append(params.get("value", None))
    return cargs


class AfdconnectivityOutputs(typing.NamedTuple):
    """
    Output object returned when calling `AfdconnectivityParamsDict(...)`.
    """
    root: OutputPathType
    """Output root folder. This is the root folder for all outputs."""
    afd_map: OutputPathType | None
    """output a 3D image containing the AFD estimated for each voxel. """


def afdconnectivity_params(
    image: InputPathType,
    tracks: InputPathType,
    wbft: InputPathType | None = None,
    afd_map: str | None = None,
    all_fixels: bool = False,
    info: bool = False,
    quiet: bool = False,
    debug: bool = False,
    force: bool = False,
    nthreads: int | None = None,
    config: list[AfdconnectivityConfigParamsDict] | None = None,
    help_: bool = False,
    version: bool = False,
) -> AfdconnectivityParamsDictTagged:
    """
    Build parameters.
    
    Args:
        image: the input FOD image.
        tracks: the input track file defining the bundle of interest.
        wbft: provide a whole-brain fibre-tracking data set (of which the input\
            track file should be a subset), to improve the estimate of fibre bundle\
            volume in the presence of partial volume.
        afd_map: output a 3D image containing the AFD estimated for each voxel.
        all_fixels: if whole-brain fibre-tracking is NOT provided, then if\
            multiple fixels within a voxel are traversed by the pathway of\
            interest, by default the fixel with the greatest streamlines density is\
            selected to contribute to the AFD in that voxel. If this option is\
            provided, then ALL fixels with non-zero streamlines density will\
            contribute to the result, even if multiple fixels per voxel are\
            selected.
        info: display information messages.
        quiet: do not display information messages or progress status;\
            alternatively, this can be achieved by setting the MRTRIX_QUIET\
            environment variable to a non-empty string.
        debug: display debugging messages.
        force: force overwrite of output files (caution: using the same file as\
            input and output might cause unexpected behaviour).
        nthreads: use this number of threads in multi-threaded applications\
            (set to 0 to disable multi-threading).
        config: temporarily set the value of an MRtrix config file entry.
        help_: display this information page and exit.
        version: display version information and exit.
    Returns:
        Parameter dictionary
    """
    params = {
        "@type": "mrtrix/afdconnectivity",
        "all_fixels": all_fixels,
        "info": info,
        "quiet": quiet,
        "debug": debug,
        "force": force,
        "help": help_,
        "version": version,
        "image": image,
        "tracks": tracks,
    }
    if wbft is not None:
        params["wbft"] = wbft
    if afd_map is not None:
        params["afd_map"] = afd_map
    if nthreads is not None:
        params["nthreads"] = nthreads
    if config is not None:
        params["config"] = config
    return params


def afdconnectivity_validate(
    params: typing.Any,
) -> None:
    """
    Validate parameters. Throws an error if `params` is not a valid
    `AfdconnectivityParamsDict` 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("wbft", None) is not None:
        if not isinstance(params["wbft"], (pathlib.Path, str)):
            raise StyxValidationError(f'`wbft` has the wrong type: Received `{type(params.get("wbft", None))}` expected `InputPathType | None`')
    if params.get("afd_map", None) is not None:
        if not isinstance(params["afd_map"], str):
            raise StyxValidationError(f'`afd_map` has the wrong type: Received `{type(params.get("afd_map", None))}` expected `str | None`')
    if params.get("all_fixels", False) is None:
        raise StyxValidationError("`all_fixels` must not be None")
    if not isinstance(params["all_fixels"], bool):
        raise StyxValidationError(f'`all_fixels` has the wrong type: Received `{type(params.get("all_fixels", False))}` expected `bool`')
    if params.get("info", False) is None:
        raise StyxValidationError("`info` must not be None")
    if not isinstance(params["info"], bool):
        raise StyxValidationError(f'`info` has the wrong type: Received `{type(params.get("info", False))}` expected `bool`')
    if params.get("quiet", False) is None:
        raise StyxValidationError("`quiet` must not be None")
    if not isinstance(params["quiet"], bool):
        raise StyxValidationError(f'`quiet` has the wrong type: Received `{type(params.get("quiet", False))}` expected `bool`')
    if params.get("debug", False) is None:
        raise StyxValidationError("`debug` must not be None")
    if not isinstance(params["debug"], bool):
        raise StyxValidationError(f'`debug` has the wrong type: Received `{type(params.get("debug", False))}` expected `bool`')
    if params.get("force", False) is None:
        raise StyxValidationError("`force` must not be None")
    if not isinstance(params["force"], bool):
        raise StyxValidationError(f'`force` has the wrong type: Received `{type(params.get("force", False))}` expected `bool`')
    if params.get("nthreads", None) is not None:
        if not isinstance(params["nthreads"], int):
            raise StyxValidationError(f'`nthreads` has the wrong type: Received `{type(params.get("nthreads", None))}` expected `int | None`')
    if params.get("config", None) is not None:
        if not isinstance(params["config"], list):
            raise StyxValidationError(f'`config` has the wrong type: Received `{type(params.get("config", None))}` expected `list[AfdconnectivityConfigParamsDict] | None`')
        for e in params["config"]:
            afdconnectivity_config_validate(e)
    if params.get("help", False) is None:
        raise StyxValidationError("`help` must not be None")
    if not isinstance(params["help"], bool):
        raise StyxValidationError(f'`help` has the wrong type: Received `{type(params.get("help", False))}` expected `bool`')
    if params.get("version", False) is None:
        raise StyxValidationError("`version` must not be None")
    if not isinstance(params["version"], bool):
        raise StyxValidationError(f'`version` has the wrong type: Received `{type(params.get("version", False))}` expected `bool`')
    if params.get("image", None) is None:
        raise StyxValidationError("`image` must not be None")
    if not isinstance(params["image"], (pathlib.Path, str)):
        raise StyxValidationError(f'`image` has the wrong type: Received `{type(params.get("image", None))}` expected `InputPathType`')
    if params.get("tracks", None) is None:
        raise StyxValidationError("`tracks` must not be None")
    if not isinstance(params["tracks"], (pathlib.Path, str)):
        raise StyxValidationError(f'`tracks` has the wrong type: Received `{type(params.get("tracks", None))}` expected `InputPathType`')


def afdconnectivity_cargs(
    params: AfdconnectivityParamsDict,
    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("afdconnectivity")
    if params.get("wbft", None) is not None:
        cargs.extend([
            "-wbft",
            execution.input_file(params.get("wbft", None))
        ])
    if params.get("afd_map", None) is not None:
        cargs.extend([
            "-afd_map",
            params.get("afd_map", None)
        ])
    if params.get("all_fixels", False):
        cargs.append("-all_fixels")
    if params.get("info", False):
        cargs.append("-info")
    if params.get("quiet", False):
        cargs.append("-quiet")
    if params.get("debug", False):
        cargs.append("-debug")
    if params.get("force", False):
        cargs.append("-force")
    if params.get("nthreads", None) is not None:
        cargs.extend([
            "-nthreads",
            str(params.get("nthreads", None))
        ])
    if params.get("config", None) is not None:
        cargs.extend([a for c in [afdconnectivity_config_cargs(s, execution) for s in params.get("config", None)] for a in c])
    if params.get("help", False):
        cargs.append("-help")
    if params.get("version", False):
        cargs.append("-version")
    cargs.append(execution.input_file(params.get("image", None)))
    cargs.append(execution.input_file(params.get("tracks", None)))
    return cargs


def afdconnectivity_outputs(
    params: AfdconnectivityParamsDict,
    execution: Execution,
) -> AfdconnectivityOutputs:
    """
    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 = AfdconnectivityOutputs(
        root=execution.output_file("."),
        afd_map=execution.output_file(params.get("afd_map", None)) if (params.get("afd_map") is not None) else None,
    )
    return ret


def afdconnectivity_execute(
    params: AfdconnectivityParamsDict,
    runner: Runner | None = None,
) -> AfdconnectivityOutputs:
    """
    afdconnectivity
    
    Obtain an estimate of fibre connectivity between two regions using AFD and
    streamlines tractography.
    
    This estimate is obtained by determining a fibre volume (AFD) occupied by
    the pathway of interest, and dividing by the streamline length.
    
    If only the streamlines belonging to the pathway of interest are provided,
    then ALL of the fibre volume within each fixel selected will contribute to
    the result. If the -wbft option is used to provide whole-brain
    fibre-tracking (of which the pathway of interest should contain a subset),
    only the fraction of the fibre volume in each fixel estimated to belong to
    the pathway of interest will contribute to the result.
    
    Use -quiet to suppress progress messages and output fibre connectivity value
    only.
    
    For valid comparisons of AFD connectivity across scans, images MUST be
    intensity normalised and bias field corrected, and a common response
    function for all subjects must be used.
    
    Note that the sum of the AFD is normalised by streamline length to account
    for subject differences in fibre bundle length. This normalisation results
    in a measure that is more related to the cross-sectional volume of the tract
    (and therefore 'connectivity'). Note that SIFT-ed tract count is a superior
    measure because it is unaffected by tangential yet unrelated fibres.
    However, AFD connectivity may be used as a substitute when Anatomically
    Constrained Tractography is not possible due to uncorrectable EPI
    distortions, and SIFT may therefore not be as effective.
    
    Longer discussion regarding this command can additionally be found at:
    https://mrtrix.readthedocs.io/en/3.0.4/concepts/afd_connectivity.html (as
    well as in the relevant reference).
    
    References:
    
    Smith, R. E.; Raffelt, D.; Tournier, J.-D.; Connelly, A. Quantitative
    Streamlines Tractography: Methods and Inter-Subject Normalisation. Open
    Science Framework, https://doi.org/10.31219/osf.io/c67kn.
    
    Author: MRTrix3 Developers
    
    URL: https://www.mrtrix.org/
    
    Args:
        params: The parameters.
        runner: Command runner.
    Returns:
        NamedTuple of outputs (described in `AfdconnectivityOutputs`).
    """
    afdconnectivity_validate(params)
    runner = runner or get_global_runner()
    execution = runner.start_execution(AFDCONNECTIVITY_METADATA)
    params = execution.params(params)
    cargs = afdconnectivity_cargs(params, execution)
    ret = afdconnectivity_outputs(params, execution)
    execution.run(cargs)
    return ret


def afdconnectivity(
    image: InputPathType,
    tracks: InputPathType,
    wbft: InputPathType | None = None,
    afd_map: str | None = None,
    all_fixels: bool = False,
    info: bool = False,
    quiet: bool = False,
    debug: bool = False,
    force: bool = False,
    nthreads: int | None = None,
    config: list[AfdconnectivityConfigParamsDict] | None = None,
    help_: bool = False,
    version: bool = False,
    runner: Runner | None = None,
) -> AfdconnectivityOutputs:
    """
    afdconnectivity
    
    Obtain an estimate of fibre connectivity between two regions using AFD and
    streamlines tractography.
    
    This estimate is obtained by determining a fibre volume (AFD) occupied by
    the pathway of interest, and dividing by the streamline length.
    
    If only the streamlines belonging to the pathway of interest are provided,
    then ALL of the fibre volume within each fixel selected will contribute to
    the result. If the -wbft option is used to provide whole-brain
    fibre-tracking (of which the pathway of interest should contain a subset),
    only the fraction of the fibre volume in each fixel estimated to belong to
    the pathway of interest will contribute to the result.
    
    Use -quiet to suppress progress messages and output fibre connectivity value
    only.
    
    For valid comparisons of AFD connectivity across scans, images MUST be
    intensity normalised and bias field corrected, and a common response
    function for all subjects must be used.
    
    Note that the sum of the AFD is normalised by streamline length to account
    for subject differences in fibre bundle length. This normalisation results
    in a measure that is more related to the cross-sectional volume of the tract
    (and therefore 'connectivity'). Note that SIFT-ed tract count is a superior
    measure because it is unaffected by tangential yet unrelated fibres.
    However, AFD connectivity may be used as a substitute when Anatomically
    Constrained Tractography is not possible due to uncorrectable EPI
    distortions, and SIFT may therefore not be as effective.
    
    Longer discussion regarding this command can additionally be found at:
    https://mrtrix.readthedocs.io/en/3.0.4/concepts/afd_connectivity.html (as
    well as in the relevant reference).
    
    References:
    
    Smith, R. E.; Raffelt, D.; Tournier, J.-D.; Connelly, A. Quantitative
    Streamlines Tractography: Methods and Inter-Subject Normalisation. Open
    Science Framework, https://doi.org/10.31219/osf.io/c67kn.
    
    Author: MRTrix3 Developers
    
    URL: https://www.mrtrix.org/
    
    Args:
        image: the input FOD image.
        tracks: the input track file defining the bundle of interest.
        wbft: provide a whole-brain fibre-tracking data set (of which the input\
            track file should be a subset), to improve the estimate of fibre bundle\
            volume in the presence of partial volume.
        afd_map: output a 3D image containing the AFD estimated for each voxel.
        all_fixels: if whole-brain fibre-tracking is NOT provided, then if\
            multiple fixels within a voxel are traversed by the pathway of\
            interest, by default the fixel with the greatest streamlines density is\
            selected to contribute to the AFD in that voxel. If this option is\
            provided, then ALL fixels with non-zero streamlines density will\
            contribute to the result, even if multiple fixels per voxel are\
            selected.
        info: display information messages.
        quiet: do not display information messages or progress status;\
            alternatively, this can be achieved by setting the MRTRIX_QUIET\
            environment variable to a non-empty string.
        debug: display debugging messages.
        force: force overwrite of output files (caution: using the same file as\
            input and output might cause unexpected behaviour).
        nthreads: use this number of threads in multi-threaded applications\
            (set to 0 to disable multi-threading).
        config: temporarily set the value of an MRtrix config file entry.
        help_: display this information page and exit.
        version: display version information and exit.
        runner: Command runner.
    Returns:
        NamedTuple of outputs (described in `AfdconnectivityOutputs`).
    """
    params = afdconnectivity_params(
        wbft=wbft,
        afd_map=afd_map,
        all_fixels=all_fixels,
        info=info,
        quiet=quiet,
        debug=debug,
        force=force,
        nthreads=nthreads,
        config=config,
        help_=help_,
        version=version,
        image=image,
        tracks=tracks,
    )
    return afdconnectivity_execute(params, runner)


__all__ = [
    "AFDCONNECTIVITY_METADATA",
    "AfdconnectivityConfigParamsDict",
    "AfdconnectivityConfigParamsDictTagged",
    "AfdconnectivityOutputs",
    "AfdconnectivityParamsDict",
    "AfdconnectivityParamsDictTagged",
    "afdconnectivity",
    "afdconnectivity_config",
    "afdconnectivity_execute",
    "afdconnectivity_params",
]
