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

import typing
import pathlib
from styxdefs import *
import dataclasses

DWI2RESPONSE_METADATA = Metadata(
    id="edddbe80993b644221e1465a2dd0d5c280ed0192.boutiques",
    name="dwi2response",
    package="mrtrix",
    container_image_tag="mrtrix3/mrtrix3:3.0.4",
)


class Dwi2responseDhollanderOutputs(typing.NamedTuple):
    """
    Output object returned when calling `Dwi2responseDhollander(...)`.
    """
    root: OutputPathType
    """Output root folder. This is the root folder for all outputs."""
    out_sfwm: OutputPathType
    """Output single-fibre WM response function text file"""
    out_gm: OutputPathType
    """Output GM response function text file"""
    out_csf: OutputPathType
    """Output CSF response function text file"""


@dataclasses.dataclass
class Dwi2responseDhollander:
    """
    Unsupervised estimation of WM, GM and CSF response functions that does not
    require a T1 image (or segmentation thereof).
    This is an improved version of the Dhollander et al. (2016) algorithm for
    unsupervised estimation of WM, GM and CSF response functions, which includes
    the Dhollander et al. (2019) improvements for single-fibre WM response
    function estimation (prior to this update, the "dwi2response tournier"
    algorithm had been utilised specifically for the single-fibre WM response
    function estimation step).
    """
    input_: InputPathType
    """Input DWI dataset"""
    out_sfwm: str
    """Output single-fibre WM response function text file"""
    out_gm: str
    """Output GM response function text file"""
    out_csf: str
    """Output CSF response function text file"""
    erode: int | None = None
    """Number of erosion passes to apply to initial (whole brain) mask. Set to 0
    to not erode the brain mask. (default: 3)"""
    fa: float | None = None
    """FA threshold for crude WM versus GM-CSF separation. (default: 0.2)"""
    sfwm: float | None = None
    """Final number of single-fibre WM voxels to select, as a percentage of
    refined WM. (default: 0.5 per cent)"""
    gm: float | None = None
    """Final number of GM voxels to select, as a percentage of refined GM.
    (default: 2 per cent)"""
    csf: float | None = None
    """Final number of CSF voxels to select, as a percentage of refined CSF.
    (default: 10 per cent)"""
    wm_algo: typing.Literal["fa", "tax", "tournier"] | None = None
    """Use external dwi2response algorithm for WM single-fibre voxel selection
    (options: fa, tax, tournier) (default: built-in Dhollander 2019)"""
    
    def run(
        self,
        execution: Execution,
    ) -> list[str]:
        """
        Build command line arguments. This method is called by the main command.
        
        Args:
            execution: The execution object.
        Returns:
            Command line arguments
        """
        cargs = []
        cargs.append("dhollander")
        cargs.append(execution.input_file(self.input_))
        cargs.append(self.out_sfwm)
        cargs.append(self.out_gm)
        cargs.append(self.out_csf)
        if self.erode is not None:
            cargs.extend([
                "-erode",
                str(self.erode)
            ])
        if self.fa is not None:
            cargs.extend([
                "-fa",
                str(self.fa)
            ])
        if self.sfwm is not None:
            cargs.extend([
                "-sfwm",
                str(self.sfwm)
            ])
        if self.gm is not None:
            cargs.extend([
                "-gm",
                str(self.gm)
            ])
        if self.csf is not None:
            cargs.extend([
                "-csf",
                str(self.csf)
            ])
        if self.wm_algo is not None:
            cargs.extend([
                "-wm_algo",
                self.wm_algo
            ])
        return cargs
    
    def outputs(
        self,
        execution: Execution,
    ) -> Dwi2responseDhollanderOutputs:
        """
        Collect output file paths.
        
        Args:
            execution: The execution object.
        Returns:
            NamedTuple of outputs (described in `Dwi2responseDhollanderOutputs`).
        """
        ret = Dwi2responseDhollanderOutputs(
            root=execution.output_file("."),
            out_sfwm=execution.output_file(self.out_sfwm),
            out_gm=execution.output_file(self.out_gm),
            out_csf=execution.output_file(self.out_csf),
        )
        return ret


class Dwi2responseFaOutputs(typing.NamedTuple):
    """
    Output object returned when calling `Dwi2responseFa(...)`.
    """
    root: OutputPathType
    """Output root folder. This is the root folder for all outputs."""
    output: OutputPathType
    """The output response function text file"""


@dataclasses.dataclass
class Dwi2responseFa:
    """
    Use the old FA-threshold heuristic for single-fibre voxel selection and
    response function estimation.
    """
    input_: InputPathType
    """The input DWI"""
    output: str
    """The output response function text file"""
    erode: int | None = None
    """Number of brain mask erosion steps to apply prior to threshold (not used
    if mask is provided manually)"""
    number: int | None = None
    """The number of highest-FA voxels to use"""
    threshold: float | None = None
    """Apply a hard FA threshold, rather than selecting the top voxels"""
    
    def run(
        self,
        execution: Execution,
    ) -> list[str]:
        """
        Build command line arguments. This method is called by the main command.
        
        Args:
            execution: The execution object.
        Returns:
            Command line arguments
        """
        cargs = []
        cargs.append("fa")
        cargs.append(execution.input_file(self.input_))
        cargs.append(self.output)
        if self.erode is not None:
            cargs.extend([
                "-erode",
                str(self.erode)
            ])
        if self.number is not None:
            cargs.extend([
                "-number",
                str(self.number)
            ])
        if self.threshold is not None:
            cargs.extend([
                "-threshold",
                str(self.threshold)
            ])
        return cargs
    
    def outputs(
        self,
        execution: Execution,
    ) -> Dwi2responseFaOutputs:
        """
        Collect output file paths.
        
        Args:
            execution: The execution object.
        Returns:
            NamedTuple of outputs (described in `Dwi2responseFaOutputs`).
        """
        ret = Dwi2responseFaOutputs(
            root=execution.output_file("."),
            output=execution.output_file(self.output),
        )
        return ret


class Dwi2responseManualOutputs(typing.NamedTuple):
    """
    Output object returned when calling `Dwi2responseManual(...)`.
    """
    root: OutputPathType
    """Output root folder. This is the root folder for all outputs."""
    output: OutputPathType
    """Output response function text file"""


@dataclasses.dataclass
class Dwi2responseManual:
    """
    Derive a response function using an input mask image alone (i.e.
    pre-selected voxels).
    """
    input_: InputPathType
    """The input DWI"""
    in_voxels: InputPathType
    """Input voxel selection mask"""
    output: str
    """Output response function text file"""
    dirs: InputPathType | None = None
    """Manually provide the fibre direction in each voxel (a tensor fit will be
    used otherwise)"""
    
    def run(
        self,
        execution: Execution,
    ) -> list[str]:
        """
        Build command line arguments. This method is called by the main command.
        
        Args:
            execution: The execution object.
        Returns:
            Command line arguments
        """
        cargs = []
        cargs.append("manual")
        cargs.append(execution.input_file(self.input_))
        cargs.append(execution.input_file(self.in_voxels))
        cargs.append(self.output)
        if self.dirs is not None:
            cargs.extend([
                "-dirs",
                execution.input_file(self.dirs)
            ])
        return cargs
    
    def outputs(
        self,
        execution: Execution,
    ) -> Dwi2responseManualOutputs:
        """
        Collect output file paths.
        
        Args:
            execution: The execution object.
        Returns:
            NamedTuple of outputs (described in `Dwi2responseManualOutputs`).
        """
        ret = Dwi2responseManualOutputs(
            root=execution.output_file("."),
            output=execution.output_file(self.output),
        )
        return ret


class Dwi2responseMsmt5ttOutputs(typing.NamedTuple):
    """
    Output object returned when calling `Dwi2responseMsmt5tt(...)`.
    """
    root: OutputPathType
    """Output root folder. This is the root folder for all outputs."""
    out_wm: OutputPathType
    """Output WM response text file"""
    out_gm: OutputPathType
    """Output GM response text file"""
    out_csf: OutputPathType
    """Output CSF response text file"""


@dataclasses.dataclass
class Dwi2responseMsmt5tt:
    """
    Derive MSMT-CSD tissue response functions based on a co-registered
    five-tissue-type (5TT) image.
    """
    input_: InputPathType
    """The input DWI"""
    in_5tt: InputPathType
    """Input co-registered 5TT image"""
    out_wm: str
    """Output WM response text file"""
    out_gm: str
    """Output GM response text file"""
    out_csf: str
    """Output CSF response text file"""
    dirs: InputPathType | None = None
    """Manually provide the fibre direction in each voxel (a tensor fit will be
    used otherwise)"""
    fa: float | None = None
    """Upper fractional anisotropy threshold for GM and CSF voxel selection
    (default: 0.2)"""
    pvf: float | None = None
    """Partial volume fraction threshold for tissue voxel selection (default:
    0.95)"""
    wm_algo: typing.Literal["fa", "tax", "tournier"] | None = None
    """algorithm dwi2response algorithm to use for WM single-fibre voxel
    selection (options: fa, tax, tournier; default: tournier)"""
    sfwm_fa_threshold: float | None = None
    """Sets -wm_algo to fa and allows to specify a hard FA threshold for
    single-fibre WM voxels, which is passed to the -threshold option of the fa
    algorithm (warning: overrides -wm_algo option)"""
    
    def run(
        self,
        execution: Execution,
    ) -> list[str]:
        """
        Build command line arguments. This method is called by the main command.
        
        Args:
            execution: The execution object.
        Returns:
            Command line arguments
        """
        cargs = []
        cargs.append("msmt_5tt")
        cargs.append(execution.input_file(self.input_))
        cargs.append(execution.input_file(self.in_5tt))
        cargs.append(self.out_wm)
        cargs.append(self.out_gm)
        cargs.append(self.out_csf)
        if self.dirs is not None:
            cargs.extend([
                "-dirs",
                execution.input_file(self.dirs)
            ])
        if self.fa is not None:
            cargs.extend([
                "-fa",
                str(self.fa)
            ])
        if self.pvf is not None:
            cargs.extend([
                "-pvf",
                str(self.pvf)
            ])
        if self.wm_algo is not None:
            cargs.extend([
                "-wm_algo",
                self.wm_algo
            ])
        if self.sfwm_fa_threshold is not None:
            cargs.extend([
                "-sfwm_fa_threshold",
                str(self.sfwm_fa_threshold)
            ])
        return cargs
    
    def outputs(
        self,
        execution: Execution,
    ) -> Dwi2responseMsmt5ttOutputs:
        """
        Collect output file paths.
        
        Args:
            execution: The execution object.
        Returns:
            NamedTuple of outputs (described in `Dwi2responseMsmt5ttOutputs`).
        """
        ret = Dwi2responseMsmt5ttOutputs(
            root=execution.output_file("."),
            out_wm=execution.output_file(self.out_wm),
            out_gm=execution.output_file(self.out_gm),
            out_csf=execution.output_file(self.out_csf),
        )
        return ret


class Dwi2responseTaxOutputs(typing.NamedTuple):
    """
    Output object returned when calling `Dwi2responseTax(...)`.
    """
    root: OutputPathType
    """Output root folder. This is the root folder for all outputs."""
    output: OutputPathType
    """The output response function text file"""


@dataclasses.dataclass
class Dwi2responseTax:
    """
    Use the Tax et al. (2014) recursive calibration algorithm for single-fibre
    voxel selection and response function estimation.
    """
    input_: InputPathType
    """The input DWI"""
    output: str
    """The output response function text file"""
    peak_ratio: float | None = None
    """Second-to-first-peak amplitude ratio threshold"""
    max_iters: int | None = None
    """Maximum number of iterations"""
    convergence: float | None = None
    """Percentile change in any RF coefficient required to continue iterating"""
    
    def run(
        self,
        execution: Execution,
    ) -> list[str]:
        """
        Build command line arguments. This method is called by the main command.
        
        Args:
            execution: The execution object.
        Returns:
            Command line arguments
        """
        cargs = []
        cargs.append("tax")
        cargs.append(execution.input_file(self.input_))
        cargs.append(self.output)
        if self.peak_ratio is not None:
            cargs.extend([
                "-peak_ratio",
                str(self.peak_ratio)
            ])
        if self.max_iters is not None:
            cargs.extend([
                "-max_iters",
                str(self.max_iters)
            ])
        if self.convergence is not None:
            cargs.extend([
                "-convergence",
                str(self.convergence)
            ])
        return cargs
    
    def outputs(
        self,
        execution: Execution,
    ) -> Dwi2responseTaxOutputs:
        """
        Collect output file paths.
        
        Args:
            execution: The execution object.
        Returns:
            NamedTuple of outputs (described in `Dwi2responseTaxOutputs`).
        """
        ret = Dwi2responseTaxOutputs(
            root=execution.output_file("."),
            output=execution.output_file(self.output),
        )
        return ret


class Dwi2responseTournierOutputs(typing.NamedTuple):
    """
    Output object returned when calling `Dwi2responseTournier(...)`.
    """
    root: OutputPathType
    """Output root folder. This is the root folder for all outputs."""
    output: OutputPathType
    """The output response function text file"""


@dataclasses.dataclass
class Dwi2responseTournier:
    """
    Use the Tournier et al. (2013) iterative algorithm for single-fibre voxel
    selection and response function estimation.
    """
    input_: InputPathType
    """The input DWI"""
    output: str
    """The output response function text file"""
    number: int | None = None
    """Number of single-fibre voxels to use when calculating response
    function"""
    iter_voxels: int | None = None
    """Number of single-fibre voxels to select when preparing for the next
    iteration (default = 10 x value given in -number)"""
    dilate: int | None = None
    """Number of mask dilation steps to apply when deriving voxel mask to test
    in the next iteration"""
    max_iters: int | None = None
    """Maximum number of iterations"""
    
    def run(
        self,
        execution: Execution,
    ) -> list[str]:
        """
        Build command line arguments. This method is called by the main command.
        
        Args:
            execution: The execution object.
        Returns:
            Command line arguments
        """
        cargs = []
        cargs.append("tournier")
        cargs.append(execution.input_file(self.input_))
        cargs.append(self.output)
        if self.number is not None:
            cargs.extend([
                "-number",
                str(self.number)
            ])
        if self.iter_voxels is not None:
            cargs.extend([
                "-iter_voxels",
                str(self.iter_voxels)
            ])
        if self.dilate is not None:
            cargs.extend([
                "-dilate",
                str(self.dilate)
            ])
        if self.max_iters is not None:
            cargs.extend([
                "-max_iters",
                str(self.max_iters)
            ])
        return cargs
    
    def outputs(
        self,
        execution: Execution,
    ) -> Dwi2responseTournierOutputs:
        """
        Collect output file paths.
        
        Args:
            execution: The execution object.
        Returns:
            NamedTuple of outputs (described in `Dwi2responseTournierOutputs`).
        """
        ret = Dwi2responseTournierOutputs(
            root=execution.output_file("."),
            output=execution.output_file(self.output),
        )
        return ret


@dataclasses.dataclass
class Dwi2responseFslgrad:
    """
    Provide the diffusion gradient table in FSL bvecs/bvals format.
    """
    bvecs: InputPathType
    """Provide the diffusion-weighted gradient scheme used in the acquisition in
    FSL bvecs/bvals format files. If a diffusion gradient scheme is present in
    the input image header, the data provided with this option will be instead
    used."""
    bvals: InputPathType
    """Provide the diffusion-weighted gradient scheme used in the acquisition in
    FSL bvecs/bvals format files. If a diffusion gradient scheme is present in
    the input image header, the data provided with this option will be instead
    used."""
    
    def run(
        self,
        execution: Execution,
    ) -> list[str]:
        """
        Build command line arguments. This method is called by the main command.
        
        Args:
            execution: The execution object.
        Returns:
            Command line arguments
        """
        cargs = []
        cargs.append("-fslgrad")
        cargs.append(execution.input_file(self.bvecs))
        cargs.append(execution.input_file(self.bvals))
        return cargs


@dataclasses.dataclass
class Dwi2responseConfig:
    """
    temporarily set the value of an MRtrix config file entry.
    """
    key: str
    """temporarily set the value of an MRtrix config file entry."""
    value: str
    """temporarily set the value of an MRtrix config file entry."""
    
    def run(
        self,
        execution: Execution,
    ) -> list[str]:
        """
        Build command line arguments. This method is called by the main command.
        
        Args:
            execution: The execution object.
        Returns:
            Command line arguments
        """
        cargs = []
        cargs.append("-config")
        cargs.append(self.key)
        cargs.append(self.value)
        return cargs


class Dwi2responseOutputs(typing.NamedTuple):
    """
    Output object returned when calling `dwi2response(...)`.
    """
    root: OutputPathType
    """Output root folder. This is the root folder for all outputs."""
    algorithm: typing.Union[Dwi2responseDhollanderOutputs, Dwi2responseFaOutputs, Dwi2responseManualOutputs, Dwi2responseMsmt5ttOutputs, Dwi2responseTaxOutputs, Dwi2responseTournierOutputs]
    """Outputs from `Dwi2responseDhollander` or `Dwi2responseFa` or
    `Dwi2responseManual` or `Dwi2responseMsmt5tt` or `Dwi2responseTax` or
    `Dwi2responseTournier`."""


def dwi2response(
    algorithm: typing.Union[Dwi2responseDhollander, Dwi2responseFa, Dwi2responseManual, Dwi2responseMsmt5tt, Dwi2responseTax, Dwi2responseTournier],
    grad: InputPathType | None = None,
    fslgrad: Dwi2responseFslgrad | None = None,
    mask: InputPathType | None = None,
    voxels: str | None = None,
    shells: list[int] | None = None,
    lmax: list[int] | None = None,
    nocleanup: bool = False,
    scratch: str | None = None,
    continue_: str | None = None,
    info: bool = False,
    quiet: bool = False,
    debug: bool = False,
    force: bool = False,
    nthreads: int | None = None,
    config: list[Dwi2responseConfig] | None = None,
    help_: bool = False,
    version: bool = False,
    runner: Runner | None = None,
) -> Dwi2responseOutputs:
    """
    Estimate response function(s) for spherical deconvolution.
    dwi2response offers different algorithms for performing various types of
    response function estimation. The name of the algorithm must appear as the
    first argument on the command-line after ‘dwi2response’. The subsequent
    arguments and options depend on the particular algorithm being invoked.
    Each algorithm available has its own help page, including necessary
    references; e.g. to see the help page of the 'fa' algorithm, type
    'dwi2response fa'.
    
    Author: Robert E. Smith (robert.smith@florey.edu.au) & Thijs Dhollander
    (thijs.dhollander@gmail.com)
    
    URL:
    https://mrtrix.readthedocs.io/en/3.0.4/reference/commands/dwi2response.html
    
    Args:
        algorithm: Select the algorithm to be used to complete the script\
            operation; additional details and options become available once an\
            algorithm is nominated. Options are: dhollander, fa, manual, msmt_5tt,\
            tax, tournier.
        grad: Provide the diffusion gradient table in MRtrix format.
        fslgrad: Provide the diffusion gradient table in FSL bvecs/bvals format.
        mask: Only process voxels within the specified binary brain mask image.
        voxels: Output an image showing the final voxel selection(s).
        shells: b-value(s) to use in response function estimation\
            (comma-separated list in case of multiple b-values, b=0 must be\
            included explicitly).
        lmax: maximum harmonic degree(s) for response function estimation\
            (comma-separated list in case of multiple b-values).
        nocleanup: do not delete intermediate files during script execution,\
            and do not delete scratch directory at script completion.
        scratch: manually specify the path in which to generate the scratch\
            directory.
        continue_: continue the script from a previous execution; must provide\
            the scratch directory path, and the name of the last\
            successfully-generated file.
        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 `Dwi2responseOutputs`).
    """
    runner = runner or get_global_runner()
    execution = runner.start_execution(DWI2RESPONSE_METADATA)
    cargs = []
    cargs.append("dwi2response")
    cargs.extend(algorithm.run(execution))
    if grad is not None:
        cargs.extend([
            "-grad",
            execution.input_file(grad)
        ])
    if fslgrad is not None:
        cargs.extend(fslgrad.run(execution))
    if mask is not None:
        cargs.extend([
            "-mask",
            execution.input_file(mask)
        ])
    if voxels is not None:
        cargs.extend([
            "-voxels",
            voxels
        ])
    if shells is not None:
        cargs.extend([
            "-shells",
            ",".join(map(str, shells))
        ])
    if lmax is not None:
        cargs.extend([
            "-lmax",
            ",".join(map(str, lmax))
        ])
    if nocleanup:
        cargs.append("-nocleanup")
    if scratch is not None:
        cargs.extend([
            "-scratch",
            scratch
        ])
    if continue_ is not None:
        cargs.extend([
            "-continue",
            continue_
        ])
    if info:
        cargs.append("-info")
    if quiet:
        cargs.append("-quiet")
    if debug:
        cargs.append("-debug")
    if force:
        cargs.append("-force")
    if nthreads is not None:
        cargs.extend([
            "-nthreads",
            str(nthreads)
        ])
    if config is not None:
        cargs.extend([a for c in [s.run(execution) for s in config] for a in c])
    if help_:
        cargs.append("-help")
    if version:
        cargs.append("-version")
    ret = Dwi2responseOutputs(
        root=execution.output_file("."),
        algorithm=algorithm.outputs(execution),
    )
    execution.run(cargs)
    return ret


__all__ = [
    "DWI2RESPONSE_METADATA",
    "Dwi2responseConfig",
    "Dwi2responseDhollander",
    "Dwi2responseDhollanderOutputs",
    "Dwi2responseFa",
    "Dwi2responseFaOutputs",
    "Dwi2responseFslgrad",
    "Dwi2responseManual",
    "Dwi2responseManualOutputs",
    "Dwi2responseMsmt5tt",
    "Dwi2responseMsmt5ttOutputs",
    "Dwi2responseOutputs",
    "Dwi2responseTax",
    "Dwi2responseTaxOutputs",
    "Dwi2responseTournier",
    "Dwi2responseTournierOutputs",
    "dwi2response",
]
