Example #1
0
def _set_vol_space_cmd(fn, config):
    param = ''
    del_cmd = ''

    p, n, o, e = utils.afni_fileparts(fn)

    space = config.get('outvol_space', None)
    if space is not None:
        param += ' -space %s' % space

    view = config.get('outvol_view')
    if view is not None:
        param += ' -view %s' % view

        if len(o) and o[0] == '+' and o[1:].lower() != view.lower():
            trgfn = '%s/%s+%s' % (p, n, view.lower())
            del_cmd = 'rm %s*; ' % trgfn


    if param:
        p, n, o, e = utils.afni_fileparts(fn)
        cmd = 'cd %s; %s 3drefit -overwrite %s %s' % (p, del_cmd, param, n + o + e)
    else:
        cmd = 'echo "Not changing view or space for %s"' % fn
    return cmd
def _ext(config, for1D=False):
    '''Returns the extension for a file name'''
    if _is_surf(config):
        return '.1D.dset' if for1D else '.niml.dset'
    else:
        fn = config['data_files'][0]
        return ''.join(utils.afni_fileparts(fn)[2:])
Example #3
0
def _convert_vol_space_to_orig_cmd(fn):
    p, n, o, e = utils.afni_fileparts(fn)
    if o == '+orig':
        return "echo '%s' is already in orig space - no conversion" % fn

    t = '__tmp_foo_'
    while os.path.exists(p + '/' + t + o + e):
        t += 'x'

    cmds = ['cd %s' % p,
          '3drename -overwrite %s%s %s%s' % (n, o, t, o),
          '3drefit -view orig %s%s' % (t, o),
          '3drename -overwrite %s+orig %s+orig' % (t, n)]

    return ';'.join(cmds)
def _remove_files(config, list_of_files):
    # removes a list of files, if config allows for it
    # in the case of AFNI volume files, it removes HEAD and BRIK files
    if not config['keep_files']:
        for fn in list_of_files:
            fp = utils.afni_fileparts(fn)

            if fp[2]:
                # AFNI HEAD/BRIK combination
                # ensure we delete all of them
                exts = ['.HEAD', '.BRIK', '.BRIK.gz']
                fn = ''.join(fp[1:3])
            else:
                exts = ['']

            for ext in exts:
                full_fn = os.path.join(config['output_dir'], fn + ext)
                if os.path.exists(full_fn):
                    os.remove(full_fn)
Example #5
0
def run_makesurfmasks(config, env):
    refdir = config['refdir']
    overwrite = config['overwrite']

    if config['sid'] is None:
        raise ValueError('Need sid')

    sumfn = '%s_qa_surf_mask' % config['sid'] # output file

    fullext = config['outvol_fullext']
    volor = config['outvol_ext']

    sumfn_path = '%s/%s%s' % (refdir, sumfn, fullext)
    qafn_path = '%s/%s.png' % (refdir, sumfn)
    checkfn_paths = (sumfn_path, qafn_path)
    if all(map(os.path.exists, checkfn_paths)) and not overwrite:
        print "Already exist: %s" % (", ".join(checkfn_paths))
        return

    icolds, hemis = _get_hemis_icolds(config)

    volexts = ['%s%s' % (volor, e) for e in '.HEAD', '.BRIK*']




    sssuffix = config['sssuffix'] if config['expvol_ss'] else ''
    expvol_fn = '%s%s%s' % (utils.afni_fileparts(config['expvol'])[1],
                            sssuffix,
                            volor)


    #if overwrite or not os.path.exists('%s/%s' % (refdir, sv_al_nii_fn)):
    #    cmd = 'cd %s; 3dcopy -overwrite %s %s' % (refdir, sv_al_orig_fn, sv_al_nii_fn)
    #    utils.run_cmds(cmd, env)


    if hemis != ['l', 'r']:
        raise ValueError("Cannot run without left and right hemisphere")

    icold = max(icolds)

    oneDfn = '__t.1D'
    oneDtfn = '__tt.1D' # transposed
    cmds = ['cd %s' % refdir,
             '1deval -1D: -num %d -expr 1 > %s' % (icold ** 2 * 10 + 1, oneDfn),
             '1dtranspose %s > %s' % (oneDfn, oneDtfn)]

    utils.run_cmds(';'.join(cmds), env)


    tmpfns = [oneDfn, oneDtfn]

    s2v_cmd = ('3dSurf2Vol -map_func mask2 -data_expr "a*%%d" -spec %%s %%s -sv %s'
             ' -grid_parent %s. -prefix %%s -sdata %s -overwrite') % \
                                (expvol_fn, expvol_fn, oneDtfn)

    infix2val = {'-surf_A pial':1,
               '-surf_A smoothwm':2,
               '-surf_A smoothwm -surf_B pial -f_steps 20': 4}

    volfns = []
    for hemi in hemis:
        specfn = afni_suma_spec.canonical_filename(icold, hemi,
                                                       config['alsuffix'])

        for infix, val in infix2val.iteritems():
            fnprefix = '__m%d_%sh' % (val, hemi)
            cmd = s2v_cmd % (val, specfn, infix, fnprefix)
            utils.run_cmds('cd %s;%s' % (refdir, cmd))
            tmpfns.extend(['%s%s' % (fnprefix, e) for e in volexts])
            volfns.append(fnprefix + volor)

    cmds = ['cd %s' % refdir]
    catfn = '__cat'
    cmds.extend(['3dTcat -overwrite -prefix %s %s' % (catfn, ' '.join(volfns)),
                 '3dTstat -overwrite -sum -prefix %s %s%s' % (sumfn, catfn, volor)])
    tmpfns.extend(['%s%s' % (catfn, e) for e in volexts])


    cmds.extend('rm %s' % fn for fn in tmpfns)
    cmds.append('echo "Surface mask in %s"' % sumfn)

    utils.run_cmds(';'.join(cmds), env)

    # make plot
    if overwrite or not os.path.exists(qafn_path):
        expvol_path = '%s/%s' % (refdir, expvol_fn)
        _make_slice_plot(expvol_path,
                         sumfn_path,
                         qafn_path)
Example #6
0
def run_alignment(config, env):
    '''Aligns anat (which is assumed to be aligned with EPI data) to FreeSurfer SurfVol

    This function strips the anatomicals (by default), then uses align_epi_anat.py
    to estimate the alignment, then applies this transformation to the non-skull-stripped
    SurfVol and also to the surfaces. Some alignment headers will be nuked'''
    overwrite = config['overwrite']
    alignsuffix = config['al2expsuffix']
    refdir = config['refdir']

    fullext = config['outvol_fullext']
    ext = config['outvol_ext']

    if config['sid'] is None:
        raise ValueError('Need sid')

    cmds = []
    if not os.path.exists(config['refdir']):
        cmds.append('mkdir %(refdir)s' % config)

    # two volumes may have to be stripped: the inpput anatomical, and the surfvol.
    # put them in a list here and process them similarly
    surfvol = '%(refdir)s/%(sid)s_SurfVol%(outvol_fullext)s' % config
    surfvol_ss = '%(refdir)s/%(sid)s_SurfVol%(sssuffix)s%(outvol_fullext)s' % config

    e_p, e_n, _, _ = utils.afni_fileparts(config['expvol'])
    if config['expvol_ss']:
        e_n = '%s%s' % (e_n, config['sssuffix'])
    expvol = '%s/%s%s' % (refdir, e_n, fullext)

    volsin = [surfvol_ss, expvol]
    for volin in volsin:
        if not os.path.exists(volin):
            raise ValueError('File %s does not exist' % volin)

    a_n = utils.afni_fileparts(volsin[0])[1] # surfvol input root name
    ssalprefix = '%s%s' % (a_n, alignsuffix)

    unity = "1 0 0 0 0 1 0 0 0 0 1 0" # we all like unity, don't we?

    fullmatrixfn = '%s_mat.aff12.1D' % ssalprefix
    aloutfns = ['%s%s' % (ssalprefix, fullext), fullmatrixfn] # expected output files if alignment worked
    if config['overwrite'] or not all([os.path.exists('%s/%s' % (refdir, f)) for f in aloutfns]):
        alignedfn = '%s/%s%s' % (refdir, ssalprefix, fullext)

        if config['identity']:
            fullmatrix_content = '"MATRIX(%s)"' % unity.replace(" ", ",")

            cmd = 'cd "%s"; cat_matvec %s > %s; 3dcopy -overwrite %s%s %s%s%s' % (refdir, fullmatrix_content, fullmatrixfn, a_n, ext, a_n, alignsuffix, ext)
        else:
            # use different inputs depending on whether expvol is EPI or ANAT
            twovolpat = ('-anat %s -epi %s -anat2epi -epi_base 0 -anat_has_skull no -epi_strip None' if config['isepi']
                       else '-dset1 %s -dset2 %s -dset1to2 -dset1_strip None -dset2_strip None')
            # use this pattern to generate a suffix
            twovolsuffix = twovolpat % (volsin[0], volsin[1])

            aea_opts = config['aea_opts']
            if config['template']:
                aea_opts += " -Allineate_opts '-maxrot 10 -maxshf 10 -maxscl 1.5'"
            # align_epi_anat.py
            cmd = 'cd "%s"; align_epi_anat.py -overwrite -suffix %s %s %s' % (refdir, alignsuffix, twovolsuffix, aea_opts)

        cmds.append(cmd)

        cmds.append(_set_vol_space_cmd(alignedfn, config))

        utils.run_cmds(cmds, env)

    else:
        print "Alignment already done - skipping"

        # run these commands first, then check if everything worked properly


    cmds = []

    # see if the expected transformation file was found
    if not config['identity'] and not os.path.exists('%s/%s' % (refdir, fullmatrixfn)):
        raise Exception("Could not find %s in %s" % (fullmatrixfn, refdir))

    # now make a 3x4 matrix
    matrixfn = '%s%s.A2E.1D' % (a_n, alignsuffix)
    if overwrite or not os.path.exists('%s/%s' % (refdir, matrixfn)):
        cmds.append('cd "%s"; cat_matvec %s > %s || exit 1' % (refdir, fullmatrixfn, matrixfn))


    # make an aligned, non-skullstripped version of SurfVol in refdir
    alprefix = '%s_SurfVol%s' % (config['sid'], alignsuffix)
    svalignedfn = '%s/%s%s' % (refdir, alprefix, fullext)

    newgrid = 1 # size of anatomical grid in mm. We'll have to resample, otherwise 3dWarp does
              # not respect the corners of the volume (as of April 2012)

    if overwrite or not os.path.exists(svalignedfn):
        #if not config['fs_sid']:
        #    raise ValueError("Don't have a freesurfer subject id - cannot continue")

        #surfvolfn = '%s/%s_SurfVol+orig' % (config['sumadir'], config['fs_sid'])
        surfvolfn = '%s/T1.nii' % config['sumadir']
        cmds.append('cd "%s";3dWarp -overwrite -newgrid %f -matvec_out2in `cat_matvec -MATRIX %s` -prefix ./%s %s' %
                    (refdir, newgrid, matrixfn, alprefix, surfvolfn))
        cmds.append(_set_vol_space_cmd('%s/%s+orig' % (refdir, alprefix), config))

    else:
        print '%s already exists - skipping Warp' % svalignedfn

    utils.run_cmds(cmds, env)
    cmds = []

    # nuke afni headers
    headernukefns = ['%s%s' % (f, fullext) for f in [ssalprefix, alprefix]]
    headernukefields = ['ALLINEATE_MATVEC_B2S_000000',
                      'ALLINEATE_MATVEC_S2B_000000',
                      'WARPDRIVE_MATVEC_FOR_000000',
                      'WARPDRIVE_MATVEC_INV_000000']

    for fn in headernukefns:
        for field in headernukefields:
            # nuke transformation - otherwise AFNI does this unwanted transformation for us
            fullfn = '%s/%s' % (refdir, fn)

            if not (os.path.exists(fullfn) or config['identity']):
                raise ValueError("File %r does not exist" % fullfn)

            refitcmd = "3drefit -atrfloat %s '%s' %s" % (field, unity, fn)

            # only refit if not already in AFNI history (which is stored in HEADfile)
            cmd = 'cd "%s"; m=`grep "%s" %s | wc -w`; if [ $m -eq 0 ]; then %s; else echo "File %s seems already 3drefitted"; fi' % (refdir, refitcmd, fn, refitcmd, fn)
            cmds.append(cmd)
    utils.run_cmds('; '.join(cmds), env)
    cmds = []

    # run AddEdge so that volumes can be inspected visually for alignment
    if config['AddEdge']:
        use_ss = config['expvol_ss']

        # ae_{e,s}_n are AddEdge names for expvol and surfvol
        ae_e_n = utils.afni_fileparts(config['expvol'])[1]
        if use_ss:
            ae_e_n += config['sssuffix']
        ae_s_n = ssalprefix #if use_ss else alprefix

        # *_ne have the output extension as well
        ae_e_ne = ae_e_n + ext
        ae_s_ne = ae_s_n + ext

        addedge_fns = ['%s/_ae.ExamineList.log' % refdir]

        exts = ['HEAD', 'BRIK']
        orig_ext = '+orig'
        addedge_rootfns = ['%s_%s%%s' % (ae_e_n, postfix)
                            for postfix in ['e3', 'ec', ae_s_n + '_ec']]
        addedge_rootfns.extend(['%s_%s%%s' % (ae_s_n, postfix)
                            for postfix in ['e3', 'ec']])

        addedge_fns_pat = ['%s.%s' % (fn, e) for fn in addedge_rootfns for e in exts]

        addegde_pathfns_orig = map(lambda x:os.path.join(refdir, x % '+orig'), addedge_fns_pat) + addedge_fns
        addegde_pathfns_ext = map(lambda x:os.path.join(refdir, x % ext), addedge_fns_pat)
        addegde_exists = map(os.path.exists, addegde_pathfns_ext)
        if overwrite or not all(addegde_exists):
            ae_ns = (ae_e_n, ae_s_n)

            cmds.extend(map(lambda fn : 'if [ -e "%s" ]; then rm "%s"; fi' % (fn, fn), addegde_pathfns_orig + addegde_pathfns_ext))
            cmds.append(';'.join(['cd %s' % refdir] +
                                 [_convert_vol_space_to_orig_cmd('%s/%s%s' % (refdir, n, ext))
                                            for n in ae_ns] +
                                 ['\@AddEdge %s+orig %s+orig' % ae_ns]))

            set_space_fns = addegde_pathfns_orig + ['%s/%s%s.%s' % (refdir, fn, orig_ext, exts[0]) for fn in ae_ns]

            for fn in set_space_fns: #['%s/%s' % (refdir, fn % orig_ext) for fn in addedge_fns_pat]:
                if fn.endswith('.log'):
                    continue
                cmds.append('if [ -e %s ]; then %s; fi' % (fn, _set_vol_space_cmd(fn, config)))

            utils.run_cmds(cmds, env)
            cmds = []

        else:
            print "AddEdge seems to have been run already"

        sid = config['sid']
        plot_slice_fns = [(ae_e_n + '_e3', ae_s_n + '_e3', '%s_qa_e3.png' % sid),
                          (None, ae_e_n + '_' + ae_s_n + '_ec', '%s_qa_ec.png' % sid)]


        plot_slice_imgfns = ['%s/%s' % (refdir, fn) for fn in plot_slice_fns]
        if overwrite or not all(map(os.path.exists, plot_slice_imgfns)):
            slice_dims = [0, 1, 2]
            slice_pos = [.35, .45, .55, .65]
            for fns in plot_slice_fns:
                input_fns = []
                for i, fn in enumerate(fns):
                    if fn is not None:
                        fn = '%s/%s' % (refdir, fn)
                        if i <= 1:
                            fn += ext
                    input_fns.append(fn)

                fn1, fn2, fnout = input_fns
                if not os.path.exists(fnout):
                    _make_slice_plot(fn1, fn2, fnout)
                    print "QA Image saved to %s" % fnout
                else:
                    print "Already exists: %s" % fnout
        else:
            print "QA images already exist"



    # because AFNI uses RAI orientation but FreeSurfer LPI, make a new
    # affine transformation matrix in which the signs of
    # x and y coordinates are negated before and after the transformation
    matrixfn_LPI2RAI = '%s.A2E_LPI.1D' % ssalprefix
    if overwrite or not os.path.exists('%s/%s' % (refdir, matrixfn_LPI2RAI)):
        lpirai = '"MATRIX(-1,0,0,0,0,-1,0,0,0,0,1,0)"'
        cmd = ('cd %s; cat_matvec -ONELINE %s `cat_matvec -MATRIX %s` %s > %s' %
             (refdir, lpirai, matrixfn, lpirai, matrixfn_LPI2RAI))
        cmds.append(cmd)

    # apply transformation to surfaces
    [icolds, hemis] = _get_hemis_icolds(config)
    sumadir = config['sumadir']
    sumafiles = os.listdir(sumadir)


    origext = '.asc'
    ext = format2extension(config)
    tp = format2type(config)
    # process all hemispheres and ld values
    for icold in icolds:
        for hemi in hemis:
            pat = '%s%sh.?*%s' % (config['mi_icopat'] % icold, hemi, origext)
            for sumafile in sumafiles:
                if fnmatch.fnmatch(sumafile, pat):
                    if not sumafile.endswith(origext):
                        raise ValueError("%s does not end with %s" % (sumafile, origext))
                    #s = sumafile.split(".")
                    #s[len(s) - 2] += config['alsuffix'] # insert '_al' just before last dot
                    #alsumafile = ".".join(s)
                    extsumafile = sumafile[:-len(origext)]
                    alsumafile = extsumafile + config['alsuffix'] + ext

                    if config['overwrite'] or not os.path.exists('%s/%s' % (refdir, alsumafile)):
                        # now apply transformation
                        cmd = 'cd "%s";ConvertSurface -overwrite -i_fs %s/%s -o_%s ./%s -ixmat_1D %s' % \
                              (refdir, sumadir, sumafile, tp, alsumafile, matrixfn_LPI2RAI)
                        cmds.append(cmd)

                    # as of June 2012 copy the original sphere.reg (not aligned) as well
                    if sumafile == ('%s.sphere.reg%s' % (pat, ext)):
                        sumaout = '%s/%s' % (refdir, extsumafile + ext)
                        if config['overwrite'] or not os.path.exists(sumaout):
                            s = surf.read('%s/%s' % (sumadir, sumafile))
                            surf.write(s, sumaout)
                            #cmds.append('cp %s/%s %s/%s' % (sumadir, sumafile, refdir, sumafile))


        mapfn = (config['mi_icopat'] % icold) + config['hemimappingsuffix']
        srcpathfn = os.path.join(sumadir, mapfn)

        if os.path.exists(srcpathfn):
            trgpathfn = os.path.join(refdir, mapfn)
            if not os.path.exists(trgpathfn) or config['overwrite']:
                cmds.append('cp %s %s' % (srcpathfn, trgpathfn))

    utils.run_cmds(cmds, env)
Example #7
0
def run_skullstrip(config, env):
    fullext = config['outvol_fullext']

    overwrite = config['overwrite']
    refdir = config['refdir']
    cmds = []
    if not os.path.exists(refdir):
        cmds.append('mkdir %(refdir)s' % config)

    sumadir = config['sumadir']
    sid = config['sid']
    fs_sid = config['fs_sid']

    if not sid:
        raise ValueError("Subject id is not set, cannot continue")

    # process the surfvol anatomical.
    # because it's already skull stripped by freesurfer
    # simply copy it over; rename brain.nii to surfvol_ss
    surfvol_srcs = ['%s/%s' % (sumadir, fn)
                  for fn in ['brain.nii',
                             'T1.nii']]

    surfvol_trgs = ['%s/%s' % (refdir, fn)
                  for fn in ['%s_SurfVol_ss%s' % (sid, fullext),
                             '%s_SurfVol%s' % (sid, fullext)]]

    for src, trg in zip(surfvol_srcs, surfvol_trgs):
        if os.path.exists(trg) and not overwrite:
            print '%s already exists' % trg
        else:
            t_p, t_n, t_o, t_e = utils.afni_fileparts(trg)
            trg_short = '%s%s' % (t_n, t_o)
            cmds.append('cd "%s"; 3dresample -overwrite -orient LPI -inset %s -prefix ./%s' %
                        (refdir, src, trg_short))
            cmds.append(_set_vol_space_cmd('%s/%s+orig' % (refdir, t_n), config))

    # process experimental volume.
    expvol_src = config['expvol']
    do_ss = config['expvol_ss']
    [e_p, e_n, e_o, e_e] = utils.afni_fileparts(expvol_src)

    expvol_trg_prefix = '%s%s' % (e_n, config['sssuffix'] if do_ss else '')
    expvol_trg_tmp_prefix = '__tmp_%s' % expvol_trg_prefix

    expvol_trg = '%s/%s%s' % (refdir, expvol_trg_prefix, fullext)

    print "Attempt %s -> %s" % (expvol_src, expvol_trg)

    ext = config['outvol_ext']

    if overwrite or not utils.afni_fileexists(expvol_trg):
        if do_ss:
            cmds.append('cd "%s";3dSkullStrip -overwrite -prefix ./%s%s -input %s' %
                            (refdir, expvol_trg_tmp_prefix, ext, expvol_src))
        else:
            cmds.append('cd "%s";3dbucket -overwrite -prefix ./%s%s %s' %
                            (refdir, expvol_trg_tmp_prefix, ext, expvol_src))
        cmds.append('cd "%s"; 3dresample -overwrite -orient LPI -prefix %s -inset %s%s' %
                            (refdir, expvol_trg_prefix, expvol_trg_tmp_prefix, ext))
        cmds.append('rm %s/%s*' % (refdir, expvol_trg_tmp_prefix))
        cmds.append(_set_vol_space_cmd(expvol_trg, config))
    else:
        print "No skull strip because already exists: %s%s" % (expvol_trg_prefix, ext)

    utils.run_cmds(cmds, env)
Example #8
0
def augmentconfig(c):
    '''add more configuration values that are *derived* from the current configuration,
    and also checks whether some options are set properly'''

    # ensure surfdir is set properly.
    # normally it should end in 'surf'

    # try to be smart and deduce subject id from surfdir (if not set explicitly)
    surfdir = c['surfdir']
    if surfdir:
        surfdir = os.path.abspath(surfdir)
        parent, nm = os.path.split(surfdir)

        if nm != 'surf':
            jn = os.path.join(surfdir, 'surf')
            if os.path.exists(jn):
                surfdir = jn
        elif nm == 'SUMA':
            surfdir = parent

        if not (os.path.exists(surfdir) or os.path.split(surfdir)[1] == 'surf'):
            print('Warning: surface directory %s not does exist or does not end in "surf"' % surfdir)
            surfdir = None

        c['surfdir'] = surfdir

        # set SUMADIR as well
        c['sumadir'] = '%(surfdir)s/SUMA/' % c

    # derive subject id from surfdir

    sid = os.path.split(os.path.split(surfdir)[0])[1] if surfdir else None

    if c.get('sid') is None:
        c['sid'] = sid

    if c['sid'] is None:
        print"Warning: no subject id specified"


    c['prefix_sv2anat'] = 'SurfVol2anat'

    # update steps
    if c.get('steps', 'all') == 'all':
        c['steps'] = 'toafni+mapico+moresurfs+skullstrip+align+makespec+makespecboth+makesurfmasks'



    hasanatvol = 'anatvol' in c and c['anatvol']
    hasepivol = 'epivol' in c and c['epivol']
    hasexpvol = 'expvol' in c and c['expvol']
    hasisepi = 'isepi' in c

    if hasexpvol:
        if hasanatvol or hasepivol:
            raise Exception("expvol specified, but also anatvol or epivol - illegal!")
        if not hasisepi:
            raise Exception("not specified whether expvol is EPI (yes) or anat (no)")

    else:
        if hasanatvol:
            if 'epivol' in c and c['epivol']:
                raise Exception("Cannot have both anatvol and epivol")
            else:
                c['expvol'] = c['anatvol']
                c['isepi'] = False
                del(c['anatvol'])
        else:
            if hasepivol:
                c['expvol'] = c['epivol']
                c['isepi'] = True
                del(c['epivol'])
            else:
                print("Warning: no anatomical or functional experimental voume defined")

    def yesno2bool(d, k): # dict, key
        '''Assuming d[k] contains the word 'yes' or 'no', makes d[k] a boolean
        (True=='yes',False=='no'); otherwise an exception is thrown. The dict is updated'''
        val = d[k]
        if val is None:
            b = False
        elif type(val) == bool:
            b = val
        else:
            v = val.lower()
            if v == 'yes':
                b = True
            elif v == 'no':
                b = False
            else:
                raise Exception("Not yes or no: %s" % val)
        d[k] = b

    yesno2bool(c, 'AddEdge')

    if c['identity']:
        c['expvol_ss'] = c['anatval_ss'] = False
    else:
        yesno2bool(c, 'expvol_ss')
        yesno2bool(c, 'isepi')

    # see if we can get the fs_sid
    # (only if surfdir is set properly)
    # XXX not sure if this still makes sense
    c['fs_sid'] = None
    surfdir = c.get('surfdir', None)
    if not surfdir is None and os.path.exists(surfdir):
        fs_log_fn = os.path.join(surfdir, '..', 'scripts', 'recon-all.done')
        print "Looking in %s" % fs_log_fn
        if os.path.exists(fs_log_fn):
            with open(fs_log_fn) as f:
                lines = f.read().split('\n')
                for line in lines:
                    if line.startswith('SUBJECT'):
                        fs_sid = line[8:]
                        c['fs_sid'] = fs_sid
                        print "Found Freesurfer sid %s" % fs_sid
                        break

    if c['fs_sid'] is None:
        c['fs_sid'] = sid
        print "Unable to find proper Freesurfer sid"

    pathvars = ['anatvol', 'expvol', 'epivol', 'refdir', 'surfdir']
    for pathvar in pathvars:
        if pathvar in c and c[pathvar]:
            c[pathvar] = os.path.abspath(c[pathvar])
            print "Set absolute path for %s: %s" % (pathvar, c[pathvar])

    if c['template'] and c['notemplate']:
        error('Cannot have both template and notemplate')

    if 'expvol' in c:
        p, n, o, e = utils.afni_fileparts(c['expvol'])

        if c.get('outvol_space', None) is None:
            cmd = '3dAttribute TEMPLATE_SPACE %s' % c['expvol']
            outvol_space = utils.cmd_capture_output(cmd)
            outvol_space = outvol_space.split('~')[0].strip()
            if len(outvol_space) and not c['notemplate'] and outvol_space.lower() != 'orig':
                print "Detected TEMPLATE_SPACE=%s" % outvol_space
                c['outvol_space'] = outvol_space
                if o == '+orig':
                    o = '+tlrc'
                    print "Template space '%s' detected: output has extension %s" % (outvol_space, o)
                c['template'] = True
            else:
                c['outvol_space'] = '+orig'

        if len(o): #'+orig' or '+tlrc'
            c['outvol_ext'] = o
            c['outvol_fullext'] = o + e
            c['outvol_view'] = o[1:]
        else:
            # For NIFTI - output in orig or tlrc
            c['outvol_view'] = 'tlrc' if c['template'] else 'orig'
            c['outvol_ext'] = '+' + c['outvol_view']
            c['outvol_fullext'] = c['outvol_ext'] + '.HEAD'


    return c