#!/usr/bin/env fslpython

# Written by Shaun Warrington, Saad Jbabdi & Stam Sotiropoulos (based on Marius de Groot autoPtx code)
# Human and Macaque protocols created by Shaun Warrington, Rogier Mars et al.
# Neonate protocols created by Ellie Thompson et al.
# Multi-template macaque protocols created by Stephania Assimopoulos et al.

import sys,os,glob,subprocess
import argparse,textwrap

FSLDIR = os.getenv('FSLDIR')
FSLINFMRIB = os.getenv('FSLINFMRIB')
FSLbin = os.path.join(FSLDIR, 'bin')
ptxbin_gpu = os.path.join(FSLbin, 'probtrackx2_gpu') # Location of probtrackx2_gpu binary
datadir = os.path.join(FSLDIR, 'data', 'xtract_data') # Location of xtract data

# some useful functions
def errchk(errflag):
    if errflag:
        print("Exit without doing anything..")
        quit()

def imgtest(fname):
    r = subprocess.run([f'{os.path.join(FSLbin, "imtest")} {fname}'], capture_output=True, text=True, shell=True)
    return int(r.stdout)

def applywarp(fin, out, ref, warp, dtype, interp):
    if interp == 'tri':
        r = subprocess.run([os.path.join(FSLbin, "applywarp"), '-i', fin, '-o', out, '-r', ref, '-w', warp, '-d', dtype, '--interp=trilinear'])
        subprocess.run([os.path.join(FSLbin, 'fslmaths'), out, '-thr', str(0.1), '-bin', out, '-odt', 'char'])
    else:
        r = subprocess.run([os.path.join(FSLbin, "applywarp"), '-i', fin, '-o', out, '-r', ref, '-w', warp, '-d', dtype, '--interp=nn'])

def applyisoxfm(fin, out, res, refimg, interp):
    if interp == 'tri':
        subprocess.run([os.path.join(FSLbin, 'flirt'), '-in', fin, '-out', out, '-applyisoxfm', str(res), '-ref', refimg, '-interp', 'trilinear'])
        subprocess.run([os.path.join(FSLbin, 'fslmaths'), out, '-thr', str(0.1), '-bin', out, '-odt', 'char'])
    else:
        subprocess.run([os.path.join(FSLbin, 'flirt'), '-in', fin, '-out', out, '-applyisoxfm', str(res), '-ref', refimg, '-interp', 'nearestneighbour'])

def warp_masks_to_space(refimg, warp, maskdict, interp):
    for m in ['seed', 'stop', 'exclude']:
        maskimg = os.path.join(maskdir, m)
        if imgtest(maskimg):
            applywarp(maskimg, os.path.join(maskout, m), refimg, warp, 'float', interp)
            maskdict[m] = os.path.join(maskout, m)
    return maskdict

def chk_ptr_str(sp):
    if argsa.p is None:
        p = os.path.join(datadir, sp)
        if argsa.structureList is None:
            structureList = os.path.join(p, 'structureList')
        else:
            structureList = argsa.structureList
    else:
        p = argsa.p
        if argsa.structureList is None:
            print("If selecting a protocol folder, must set argument '-str'")
            quit()
        else:
            structureList = argsa.structureList
    return p, structureList

def print_tract_list(spec):
    pfile = os.path.join(datadir, spec, 'structureList')
    print('\nTract Names:')
    tract_names = ''
    with open(pfile) as f:
        for line in f:
            struct = line.strip()
            if struct and not struct.startswith("#"):
                tract_names += f'{struct.split()[0]}, '
    print(tract_names[:-2])
    quit()

class MyParser(argparse.ArgumentParser):
    def error(self, message):
        sys.stderr.write('error: %s\n' % message)
        self.print_help()
        sys.exit(2)

class Usage(Exception):
    def __init__(self, msg):
        self.msg = msg


splash = r"""
 __  _______ ____      _    ____ _____
 \ \/ /_   _|  _ \    / \  / ___|_   _|
  \  /  | | | |_) |  / _ \| |     | |
  /  \  | | |  _ <  / ___ \ |___  | |
 /_/\_\ |_| |_| \_\/_/   \_\____| |_|
 
 """
print(splash)

parser = MyParser(prog='XTRACT',
                  description='XTRACT: Cross-species tractography',
                  formatter_class=argparse.RawDescriptionHelpFormatter,
                  epilog=textwrap.dedent('''Example usage:
                        xtract -bpx /data/Diffusion.bedpostX -out /data/xtract -species HUMAN -stdwarp std2diff.nii.gz diff2std.nii.gz -gpu
                  '''))

required = parser.add_argument_group('Required arguments')
optional = parser.add_argument_group('Optional arguments')

# Compulsory arguments:
required.add_argument("-bpx", metavar='<folder>', help="Path to bedpostx folder")
required.add_argument("-out", metavar='<folder>', help="Path to output folder")
required.add_argument("-species", metavar='<SPECIES>', choices=['HUMAN', 'MACAQUE', 'HUMAN_BABY', 'CUSTOM'], help="One of HUMAN or MACAQUE or HUMAN_BABY or CUSTOM.")

# Optional protocol arguments:
optional.add_argument("-tract_list", metavar='<list>', dest='tract_list', help="Comma separated tract list defining the subset of tracts to run (must follow xtract naming convention)")
optional.add_argument("-str", metavar='<file>', dest='structureList', help="Structures file (format: <tractName> [samples=1], 1 means 1000, '#' to skip lines)")
optional.add_argument("-p", metavar='<folder>', help=f"Protocols folder (all masks in same standard space) (Default={os.path.join(FSLDIR, 'data', 'xtract_data', '<SPECIES>')})")
optional.add_argument("-stdref", metavar='<reference>', help=f"Standard space reference image (Default = {os.path.join(FSLDIR, 'data', 'standard', 'MNI152_T1_1mm [HUMAN]')}, {os.path.join(datadir, 'standard', 'F99', 'mri', 'struct_brain [MACAQUE]')}, {os.path.join(datadir, 'standard', 'neonate', 'mri', 'schuh_template [HUMAN_BABY]')}")
optional.add_argument("-stdwarp", metavar='<path>', nargs=2, help=f"<std2diff> <diff2std> Non-linear Standard2diff and Diff2standard transforms (Default={os.path.join('bedpostx_dir', 'xfms', '{standard2diff_warp.nii.gz,diff2standard_warp.nii.gz}')})")
optional.add_argument("-mac_ext", metavar='<str>', choices=['F99', 'D99', 'INIA', 'NMT', 'YRK'], default=None, help="Macaque template extension (default F99)")

# Optional space arguments:
optional.add_argument("-native", action="store_true", default=False, help="Run tractography in native (diffusion) space")
optional.add_argument("-in_native", action="store_true", default=False, help="Protocol masks are already in native (diffusion) space")
optional.add_argument("-ref", metavar='<path>', default=False, nargs=3, help="<refimage> <diff2ref> <ref2diff> Reference image for running tractography in reference space, Diff2Reference and Reference2Diff transforms")

# Optional tracking/computing arguments:
optional.add_argument("-res", metavar='<mm>', type=float, default=0, help="Output resolution (Default=same as in protocol folders unless '-native' used)")
optional.add_argument("-ptx_options", metavar='<file>', help="Pass extra probtrackx2 options as a text file to override defaults, e.g. --steplength=0.2 --distthresh=10)")
optional.add_argument("-interp", metavar='<str>', choices=['nn', 'tri'], default='nn', help="If native/ref: default interpolation of protocol ROIs is nearest neighbour ('nn', since vXXX). For backwards compatability, trilinear plus thresholding ('tri') is available")
optional.add_argument("-gpu", action="store_true", default=False, help="Use GPU version")
optional.add_argument("-par", action="store_true", default=False, help="If cluster, run in parallel: submit 1 job per tract")
optional.add_argument("-print_list", dest='print_list', action="store_true", default=False, help="List the tract names used in XTRACT")
optional.add_argument("-version", dest='version', action="store_true", default=False, help="List the package versions")

if FSLINFMRIB is not None:
    hidden = parser.add_argument_group('Hidden arguments')
    hidden.add_argument("-queue", metavar='<str>', default=None, help="For job schedulers, specify the queue fsl_sub submits to")

argsa = parser.parse_args()

if FSLINFMRIB is None:
    argsa.queue = None

# print versions (xtract, xtract_data, ptx2)
if argsa.version:
    verlist = subprocess.run([os.path.join(FSLbin, "fslversion"), '-p'], capture_output=True, text=True)
    verlist = verlist.stdout.split('\n')
    verlist = [t for t in verlist if 'fsl-xtract' in t or 'ptx2' in t]
    print('Versions:')
    verlist = [print(f'{t.split(" - ")[0].replace(" ", "")}: {t.split(" - ")[1].replace(" ", "")}') for t in verlist]
    print('\n')

# rename compulsory arguments for ease
bpx = argsa.bpx
out = argsa.out
spec = argsa.species
res = argsa.res
interp = argsa.interp
errflag = 0

if argsa.mac_ext is not None:
    if spec != 'MACAQUE':
        print(f'Error: `-species` is set to {spec} but you have specified `-mac_ext`')
        print('Error: `-species` must be MACAQUE to use `-mac_ext`')
        errflag = 1
        errchk(errflag)
    elif argsa.mac_ext != "F99":
        spec = spec + '_' + argsa.mac_ext

# if print_tract_list, then print and quit
if argsa.print_list and (spec is None):
    parser.error("-print_list requires -species\n") 
elif argsa.print_list:
    print_tract_list(spec)
elif argsa.bpx is None or (spec is None) or (out is None):
    parser.error("-bpx, -out and -species are compulsory arguments\n")
            
# check compulsory arguments
if not os.path.isdir(bpx):
    print(f'Bedpostx folder {bpx} not found')
    errflag = 1

if os.path.isdir(out):
    print('Warning: output directory already exists. XTRACT may overwrite existing content.')

# check species, set defaults, and check arguments exist
if spec != 'CUSTOM':
    p, structureList = chk_ptr_str(spec)

if spec == 'HUMAN':
    if argsa.stdref is None:
        stdref = os.path.join(FSLDIR, 'data', 'standard', 'MNI152_T1_1mm')
    else:
        stdref = argsa.stdref
elif 'MACAQUE' in spec:
    if spec == 'MACAQUE':
        if argsa.stdref is None:
            stdref = os.path.join(datadir, 'standard', 'F99', 'mri', 'struct_brain')
        else:
            stdref = argsa.stdref
    else:
        if argsa.stdref is None:
            stdref = os.path.join(datadir, 'standard', 'macaque_multitemplate', spec)
        else:
            stdref = argsa.stdref
elif spec == 'HUMAN_BABY':
    if argsa.stdref is None:
        stdref = os.path.join(datadir, 'standard', 'Schuh40week', 'mri', 'schuh_lowres')
    else:
        stdref = argsa.stdref
elif spec == 'CUSTOM':
    if argsa.in_native is False:
        if argsa.stdref is None:
            print("If -species CUSTOM and not in_native, must set argument '-stdref'")
            errflag = 1
        else:
            stdref = argsa.stdref
    if argsa.p is None:
        print("If -species CUSTOM, must set argument '-p'")
        errflag = 1
    else:
        p = argsa.p
    if argsa.structureList is None:
        print("If -species CUSTOM, must set argument '-str'")
        errflag = 1
    else:
        structureList = argsa.structureList
errchk(errflag)

if spec not in ['HUMAN', 'CUSTOM', 'MACAQUE', 'MACAQUE_NMT']:
    print(f'WARNING: the extended set of subcortical tracts (Assimopoulos et al., 2025, eLife) is not available for {spec}')
    print('Only the tracts available in the selected protocol will be reconstructed.')

if argsa.in_native is False:
    if imgtest(stdref) == 0:
        print(f"Standard space reference image '-stdref' {stdref} not found")
        errflag = 1

if not os.path.isdir(p):
    print(f"Protocol folder {p} not found")
    errflag = 1

if not os.path.isfile(structureList):
    print(f"Structures files {structureList} not found")
    errflag = 1
errchk(errflag)

# check optional arguments and set defaults
# default warps: <std2diff> <diff2std>
if argsa.stdwarp is None and argsa.in_native is False:
    # or standard2diff.nii.gz (and vice versa)
    for std2diff in [os.path.join(bpx, 'xfms', 'standard2diff_warp.nii.gz'), os.path.join(bpx, 'xfms', 'standard2diff.nii.gz')]:
        if imgtest(std2diff) == 1:
            break
    for diff2std in [os.path.join(bpx, 'xfms', 'diff2standard_warp.nii.gz'), os.path.join(bpx, 'xfms', 'diff2standard.nii.gz')]:
        if imgtest(diff2std) == 1:
            break
elif argsa.in_native:
    std2diff, diff2std = None, None
else:
    std2diff, diff2std = argsa.stdwarp[0], argsa.stdwarp[1]

if argsa.in_native is False:
    if os.path.isfile(std2diff) == 0 and argsa.in_native is False:
        print(f'std2diff {std2diff} not found.')
        errflag = 1
    if os.path.isfile(diff2std) == 0 and argsa.in_native is False:
        print(f'diff2std {diff2std} not found.')
        errflag = 1
errchk(errflag)

# reference warps (if using): <refimage> <diff2ref> <ref2diff>
if argsa.ref is not False:
    ref = argsa.ref[0]
    diff2ref = argsa.ref[1]
    ref2diff = argsa.ref[2]
    if imgtest(ref) == 0:
        print(f'ref {ref} not found.')
        errflag = 1
    if os.path.isfile(diff2ref) == 0:
        print(f'diff2ref {diff2ref} not found.')
        errflag = 1
    if os.path.isfile(ref2diff) == 0:
        print(f'ref2diff {ref2diff} not found.')
        errflag = 1
errchk(errflag)

# GPU option
if argsa.gpu:
    ptxbin = ptxbin_gpu
else:
    ptxbin = os.path.join(FSLbin, 'probtrackx2')

ptx_opts = ''
if argsa.ptx_options:
    f = open(argsa.ptx_options, "r")
    ptx_opts = f.read()
    if "\n" in ptx_opts:
        print('Warning: new line(s) found in ptx_options. Removing.')
        ptx_opts = ptx_opts.strip()

print(f'SPECIES: {spec}')
os.makedirs(out, exist_ok=True)
os.makedirs(os.path.join(out, 'logs'), exist_ok=True)
os.makedirs(os.path.join(out, 'tracts'), exist_ok=True)

if argsa.native and argsa.ref is not False:
    print("You have selected the native space and ref space options")
    print("Must select EITHER '-native', '-ref <refimage> <diff2ref> <ref2diff>', OR use the default standard space")
    errflag = 1
errchk(errflag)

# Set common ptx options
nodif_bm = os.path.join(bpx, 'nodif_brain_mask')
opts = f" -s {os.path.join(bpx, 'merged')} -m {nodif_bm} -V 1"
opts += " --loopcheck --forcedir --opd --ompl"

# Add any user-defined ptx options
opts += f" {ptx_opts}"

if 'sampvox' not in ptx_opts: 
    opts += " --sampvox=1"
    
if 'randfib' not in ptx_opts: 
    opts += " --randfib=1"

# space options
if not argsa.native and argsa.ref is False and argsa.in_native is False:
    opts += f" --seedref={stdref} --xfm={std2diff} --invxfm={diff2std} "
elif argsa.ref and argsa.in_native is False:
    opts += f" --seedref={ref} --xfm={ref2diff} --invxfm={diff2ref} "

if argsa.ref is not False:
    print(" -- combining standard-to-diffusion and diffusion-to-reference transforms")
    std2ref = os.path.join(out, 'standard2ref')
    subprocess.run([os.path.join(FSLbin, 'convertwarp'), "-o", std2ref, "-r", ref, f"--warp1={std2diff}", f"--warp2={diff2ref}"])

# Loop over tracts and prepare commands
commands = os.path.join(out, 'commands.txt')
try:
    os.remove(commands)
except OSError:
    pass

# create structureList array
structure_arr = []
for structstring in open(structureList):
    structstring = structstring.split()
    if len(structstring) != 0 and not structstring[0].startswith("#"):
        structure_arr.append([structstring[0], structstring[1]])

# if running a subset of tracts, create a new subset of structure_arr here
if argsa.tract_list is not None:
    tracts = argsa.tract_list.split(',')
    structure_arr_reduced = []
    for t in tracts:
        # check if in structureList
        idx = [i for i,s in enumerate(structure_arr) if s[0] == t]
        if len(idx) != 1:
            print(f'Tract "{t}" not found in structureList {structureList}')
            print('Tract names must follow the xtract naming convention')
            print_tract_list(spec)
        else:
            structure_arr_reduced.append([structure_arr[idx[0]][0], structure_arr[idx[0]][1]])
    structure_arr = structure_arr_reduced

print('Preparing submission script...')
for struct, nseed in structure_arr:    
    structdir = os.path.join(out, 'tracts', struct)
    os.makedirs(structdir, exist_ok=True)
    nseed = int(float(nseed)*1000)
    maskdir = os.path.join(p, struct)
    maskdict = {'seed': '', 'target': '', 'exclude': '', 'stop': ''} # mask paths stored here
    #  DEALING WITH RESAMPLING --
    # Pick space to run tractography in (diffusion or standard)
    maskout = os.path.join(out, 'masks', struct) # only used if not standard
    if argsa.native and argsa.in_native is False:
        print(f"{struct} -- transforming masks into native space")
        os.makedirs(maskout, exist_ok=True)
        maskdict = warp_masks_to_space(nodif_bm, std2diff, maskdict, interp)
    elif argsa.ref is not False:
        print(f"{struct} -- transforming masks into ref space")
        os.makedirs(maskout, exist_ok=True)
        maskdict = warp_masks_to_space(ref, std2ref, maskdict, interp)
    elif argsa.in_native is not False:
        for m in ["seed", "stop", "exclude"]:
            maskimg = os.path.join(maskdir, f"{m}.nii.gz")
            maskdict[m] = maskimg
    else:
        for m in ['seed', 'stop', 'exclude']:
            maskimg = os.path.join(maskdir, f'{m}.nii.gz')
            if res > 0:
                os.makedirs(maskout, exist_ok=True)
                if imgtest(maskimg):
                    applyisoxfm(maskimg, os.path.join(maskout, m), res, maskimg, interp)
                maskdict[m] = os.path.join(maskout, m)
            else:
                maskdict[m] = maskimg

    # Deal with targets (in cases where there may be more than one)
    targets = sorted(glob.glob(os.path.join(maskdir, 'target*.nii.gz')))
    targetfile = os.path.join(out, 'tracts', struct, 'targets.txt')

    try:
        os.remove(targetfile)
    except OSError:
        pass

    if argsa.native and argsa.in_native is False:
        transformed_targets = []
        for tfile in targets:
            t = os.path.join(maskout, os.path.basename(tfile))
            applywarp(tfile, t, nodif_bm, std2diff, 'float', interp)
            transformed_targets.append(t)
        with open(targetfile, 'w') as f:
            print(*transformed_targets, file=f)
        maskdict['target'] = targetfile

    elif argsa.ref is not False:
        transformed_targets = []
        for tfile in targets:
            t = os.path.join(maskout, os.path.basename(tfile))
            applywarp(tfile, t, ref, std2ref, 'float', interp)
            transformed_targets.append(t)
        with open(targetfile, 'w') as f:
            print(*transformed_targets, file=f)
        maskdict['target'] = targetfile

    elif argsa.in_native is not False:
        with open(targetfile, "w") as f:
            print(*targets, file=f)
        maskdict["target"] = targetfile

    else:
        if res > 0:
            transformed_targets = []
            for tfile in targets:
                t = os.path.join(maskout, os.path.basename(tfile))
                applyisoxfm(tfile, t, res, tfile, interp)
                transformed_targets.append(t)
            with open(targetfile, 'w') as f:
                print(*transformed_targets, file=f)
            maskdict['target'] = targetfile
        else:
            with open(targetfile, 'w') as f:
                print(*targets, file=f)
            maskdict['target'] = targetfile
    
    # Get generic options
    struct_opts = opts
    if imgtest(maskdict['stop']):
        struct_opts += f' --stop={maskdict["stop"]}'

    if imgtest(maskdict['exclude']):
        struct_opts += f' --avoid={maskdict["exclude"]}'

    # add seed and targets
    struct_opts1 = f'{struct_opts} --nsamples={nseed} -x {maskdict["seed"]}'
    if not maskdict['target'] == '':
        struct_opts1 += f' --waypoints={maskdict["target"]}'
        
    # do we enforce a target ordering?
    if os.path.isfile(os.path.join(maskdir, 'wayorder')):
        struct_opts1 += f' --wayorder --waycond=AND'
        
    # outputs
    struct_opts1 += f' -o density --dir={structdir}'
    
    # Does the protocol define a second run with inverted seed / target masks?
    if os.path.isfile(os.path.join(maskdir, 'invert')):
        structdir_inv = os.path.join(structdir, 'tractsInv')
        os.makedirs(structdir_inv, exist_ok=True)
        
        # invert targets/seed
        targets_inv = open(targetfile, "r").read().rstrip().split('\n')
        targets_inv.reverse()
        targets_inv.append(maskdict["seed"])
        seed_inv = targets_inv.pop(0)
        targetfile_inv = os.path.join(out, 'tracts', struct, 'tractsInv', 'targets.txt')
        try:
            os.remove(targetfile_inv)
        except OSError:
            pass

        with open(targetfile_inv, 'w') as f:
            print(*targets_inv, file=f)

        maskdict_inv = maskdict.copy()
        maskdict_inv["seed"] = seed_inv
        maskdict_inv["target"] = targetfile_inv
        
        struct_opts2 = f'{struct_opts} --nsamples={nseed} -x {maskdict_inv["seed"]}' # could change this seed definition to text file of the targets for invert/wayorder combined
        struct_opts2 += f' --waypoints={maskdict_inv["target"]}'
        struct_opts2 += f' -o density --dir={structdir_inv}'
        
        mergecmd = f'{os.path.join(FSLbin, "fslmaths")} {os.path.join(structdir, "density")} -add {os.path.join(structdir_inv, "density")} {os.path.join(structdir, "sum_density")}'
        #Add waypoints (create command but don't execute)
        addcmd = f'echo "scale=5; `cat {os.path.join(structdir, "waytotal")}` + `cat {os.path.join(structdir_inv, "waytotal")}` "|bc > {os.path.join(structdir, "sum_waytotal")}'
        # Waypoint normalisation (create command but don't execute)
        normcmd = f'{os.path.join(FSLbin, "fslmaths")} {os.path.join(structdir, "sum_density")} -div `cat {os.path.join(structdir, "sum_waytotal")}` {os.path.join(structdir, "densityNorm")}'
        # normcmd += f'; {os.path.join(FSLbin, "fslmaths")} {os.path.join(structdir, "sum_density")} -log -div `cat {os.path.join(structdir, "sum_waytotal")}` {os.path.join(structdir, "densityLogNorm")}'
        # normcmd += f'; {os.path.join(FSLbin, "fslmaths")} {os.path.join(structdir, "sum_density")} -div `cat {os.path.join(structdir, "sum_waytotal")}` -add 1 -log {os.path.join(structdir, "densityNormAddLog")}'
        # Append to command list
        with open(commands, 'a') as f:
            print(f'{ptxbin} {struct_opts1}; {ptxbin} {struct_opts2}; {mergecmd}; {addcmd}; {normcmd}', file=f)

    else: # No invert-mode
        # Waypoint normalisation (create command but don't execute)
        normcmd = f'{os.path.join(FSLbin, "fslmaths")} {os.path.join(structdir, "density")} -div `cat {os.path.join(structdir, "waytotal")}` {os.path.join(structdir, "densityNorm")}'
        # Waypoint normalisation (create command but don't execute)
        # normcmd += f'; {os.path.join(FSLbin, "fslmaths")} {os.path.join(structdir, "density")} -log -div `cat {os.path.join(structdir, "waytotal")}` {os.path.join(structdir, "densityLogNorm")}'
        # normcmd += f'; {os.path.join(FSLbin, "fslmaths")} {os.path.join(structdir, "density")} -div `cat {os.path.join(structdir, "waytotal")}` -add 1 -log {os.path.join(structdir, "densityNormAddLog")}'
        # Append to command list
        with open(commands, 'a') as f:
            print(f'{ptxbin} {struct_opts1}; {normcmd}', file=f)

subprocess.run(['chmod', '+x', commands]);

# Submit/run commands.txt (handling whether cluster, GPU and parallel processing)
hq = subprocess.run([os.path.join(FSLbin, 'fsl_sub'), '--has_queues'], capture_output=True, text=True)
if hq.stdout.rstrip() == 'Yes':
    if argsa.gpu:
        if argsa.par:
            if argsa.queue is None:
                subprocess.run([os.path.join(FSLbin, 'fsl_sub'), '-T', '60', '-R', '30', '-n', '--coprocessor=cuda', '-l', os.path.join(out, "logs"), '-N', 'xtract', '-t', commands])
            else:
                subprocess.run([os.path.join(FSLbin, 'fsl_sub'), '-q', argsa.queue, '-T', '60', '-R', '30', '-n', '--coprocessor=cuda', '-l', os.path.join(out, "logs"), '-N', 'xtract', '-t', commands])
        else:
            if argsa.queue is None:
                subprocess.run([os.path.join(FSLbin, 'fsl_sub'), '-T', '600', '-R', '30', '-n', '--coprocessor=cuda', '-l', os.path.join(out, "logs"), '-N', 'xtract', 'sh', commands])
            else:
                subprocess.run([os.path.join(FSLbin, 'fsl_sub'), '-q', argsa.queue, '-T', '600', '-R', '30', '-n', '--coprocessor=cuda', '-l', os.path.join(out, "logs"), '-N', 'xtract', 'sh', commands])
    else:
        if argsa.par:
            if argsa.queue is None:
                subprocess.run([os.path.join(FSLbin, 'fsl_sub'), '-T', '300', '-R', '30', '-n', '-l', os.path.join(out, "logs"), '-N', 'xtract', '-t', commands])
            else:
                subprocess.run([os.path.join(FSLbin, 'fsl_sub'), '-q', argsa.queue, '-T', '300', '-R', '30', '-n', '-l', os.path.join(out, "logs"), '-N', 'xtract', '-t', commands])
        else:
            if argsa.queue is None:
                subprocess.run([os.path.join(FSLbin, 'fsl_sub'), '-T', '10080', '-R', '30', '-n', '-l', os.path.join(out, "logs"), '-N', 'xtract', 'sh', commands])#, '&'])
            else:
                subprocess.run([os.path.join(FSLbin, 'fsl_sub'), '-q', argsa.queue, '-T', '10080', '-R', '30', '-n', '-l', os.path.join(out, "logs"), '-N', 'xtract', 'sh', commands])#, '&'])
else:
    subprocess.run([commands], shell=True)

quit()
