Ejemplo n.º 1
0
def asegstats2table(fsdir,
                    output_directory=None,
                    fsconfig="/i2bm/local/freesurfer/SetUpFreeSurfer.sh"):
    """ Generate text/ascii tables of freesurfer parcellation stats data
    'aseg.stats'. This can then be easily imported into a spreadsheet
    and/or stats program.

    The labels are located here: $FREESURFER_HOME/FreeSurferColorLUT.txt

    <unit>
        <input name="fsdir" type="Directory" description="The
            freesurfer working directory with all the subjects."/>
        <input name="output_directory" type="Directory" description="The
            statistical destination folder."/>
        <input name="fsconfig" type="File" description="The freesurfer
            configuration batch."/>
        <output name="statfiles" type="List_File" description="The freesurfer
            summary stats."/>
    </unit>
    """
    # Parameter that will contain the output stats
    statfiles = []

    # Fist find all the subjects with a stat dir
    statdirs = glob.glob(os.path.join(fsdir, "*", "stats"))
    subjects = [item.lstrip(os.sep).split("/")[-2] for item in statdirs]
    if output_directory is not None:
        path = os.path.join(output_directory, "subjects.json")
        with open(path, "w") as open_file:
            json.dump(subjects, open_file, indent=4)

    # Save the FreeSurfer current working directory and set the new one
    fscwd = None
    if "SUBJECTS_DIR" in os.environ:
        fscwd = os.environ["SUBJECTS_DIR"]
    os.environ["SUBJECTS_DIR"] = fsdir

    # Create the output stat directory
    fsoutdir = os.path.join(fsdir, "stats")
    if not os.path.isdir(fsoutdir):
        os.makedirs(fsoutdir)

    # Call freesurfer
    statfile = os.path.join(fsoutdir, "aseg_stats_volume.csv")
    statfiles.append(statfile)
    cmd = ["asegstats2table", "--subjects"] + subjects + [
        "--meas", "volume", "--tablefile", statfile, "--delimiter", "comma"
    ]
    recon = FSWrapper(cmd, shfile=fsconfig)
    recon()
    if recon.exitcode != 0:
        raise FreeSurferRuntimeError(recon.cmd[0], " ".join(recon.cmd[1:]),
                                     recon.stderr + recon.stdout)

    # Restore the FreeSurfer working directory
    if fscwd is not None:
        os.environ["SUBJECTS_DIR"] = fscwd

    return statfiles
Ejemplo n.º 2
0
def mri_surf2surf(hemi,
                  input_surface_file,
                  output_surface_file,
                  ico_order,
                  fsdir,
                  sid,
                  fsconfig="/i2bm/local/freesurfer/SetUpFreeSurfer.sh"):
    """ Resample surface vertices.

    Wrapper around the FreeSurfer 'mri_surf2surf' command to create the
    described texture.

    Parameters
    ----------
    hemi: str (mandatory)
        hemisphere ('lh' or 'rh').
    input_surface_file: str (mandatory)
        input surface path.
    output_surface_file: str (mandatory)
        output '.mgz' surface path.
    ico_order: int (mandatory)
        icosahedron order in [0, 7] that will be used to generate the cortical
        surface texture at a specific tessalation (the corresponding cortical
        surface can be resampled using the
        'clindmri.segmentation.freesurfer.resample_cortical_surface' function).
    fsdir: str (mandatory)
        FreeSurfer subjects directory 'SUBJECTS_DIR'.
    sid: str (mandatory)
        FreeSurfer subject identifier.
    fsconfig: str (optional)
        The FreeSurfer '.sh' config file.
    """
    # Check input parameters
    if hemi not in ["lh", "rh"]:
        raise ValueError("'{0}' is not a valid hemisphere value which must be "
                         "in ['lh', 'rf']".format(hemi))
    if ico_order < 0 or ico_order > 7:
        raise ValueError("'Ico order '{0}' is not in 0-7 "
                         "range.".format(ico_order))

    # Set the output surface extension if necessary
    if not output_surface_file.endswith(".mgz"):
        output_surface_file += ".mgz"

    # Define FreeSurfer command
    cmd = [
        "mri_surf2surf", "--hemi", hemi, "--srcsurfval", input_surface_file,
        "--srcsubject", sid, "--trgsubject", "ico", "--trgicoorder",
        str(ico_order), "--trgsurfval", output_surface_file, "--sd", fsdir,
        "--trg_type", "mgz"
    ]

    # Execute the FS command
    recon = FSWrapper(cmd, shfile=fsconfig)
    recon()
    if recon.exitcode != 0:
        raise FreeSurferRuntimeError(recon.cmd[0], " ".join(recon.cmd[1:]),
                                     recon.stderr + recon.stdout)
Ejemplo n.º 3
0
def mri_binarize(inputfile,
                 outputfile,
                 match=[],
                 wm=False,
                 fsconfig="/i2bm/local/freesurfer/SetUpFreeSurfer.sh"):
    """ Binarize a FreeSurfer label map.

    USAGE: mri_binarize

   --i invol  : input volume

   --min min  : min thresh (def is -inf)
   --max max  : max thresh (def is +inf)
   --pct P : set threshold to capture top P% (in mask or total volume)
   --rmin rmin  : compute min based on rmin*globalmean
   --rmax rmax  : compute max based on rmax*globalmean
   --match matchval <matchval2 ...>  : match instead of threshold
   --wm : set match vals to 2 and 41 (aseg for cerebral WM)
   --ventricles : set match vals those for aseg ventricles+choroid (not 4th)
   --wm+vcsf : WM and ventricular CSF, including choroid (not 4th)

   --o outvol : output volume
   --count countfile : save number of hits in ascii file (hits,ntotvox,pct)

   --binval    val    : set vox within thresh to val (default is 1)
   --binvalnot notval : set vox outside range to notval (default is 0)
   --inv              : set binval=0, binvalnot=1
   --frame frameno    : use 0-based frame of input (default is 0)
   --frame-sum : sum frames together before binarizing
   --frame-and : take intersection (AND) of frames. No --min needed.
   --merge mergevol   : merge with mergevolume
   --mask maskvol       : must be within mask
   --mask-thresh thresh : set thresh for mask (def is 0.5)
   --abs : take abs of invol first (ie, make unsigned)
   --bincol : set binarized voxel value to its column number
   --zero-edges : zero the edge voxels
   --zero-slice-edges : zero the edge slice voxels
   --dilate ndilate: dilate binarization in 3D
   --erode  nerode: erode binarization in 3D (after any dilation)
   --erode2d nerode2d: erode binarization in 2D (after any 3D erosion)

   --debug     turn on debugging
   --checkopts don't run anything, just check options and exit
   --help      print out information on how to use this program
   --version   print out version and exit
    """
    # Call freesurfer
    cmd = ["mri_binarize", "--i", inputfile, "--o", outputfile]
    if len(match) > 0:
        cmd.append("--match")
        cmd.extend(match)
    if wm:
        cmd.append("--wm")
    recon = FSWrapper(cmd, shfile=fsconfig)
    recon()
    if recon.exitcode != 0:
        raise FreeSurferRuntimeError(recon.cmd[0], " ".join(recon.cmd[1:]),
                                     recon.stderr + recon.stdout)
Ejemplo n.º 4
0
def run_freesurfer_cmd(cmd, subjects_dir=None, add_fsl_env=False,
                       fsl_init="/etc/fsl/5.0/fsl.sh"):
    """
    To avoid repeating the code to run Freesurfer and check exitcode
    everywhere.
    Step:
        - add $SUBJECTS_DIR to the environment if requested
        - add FSL's environment if requested (some Freesurfer commands require
          FSL)
        - run the Freesurfer cmd
        - check exit code

    Parameters
    ----------
    cmd: list of str
        the command to run (subprocess like).
    subjects_dir: str, default None.
        To set the $SUBJECTS_DIR environment variable.
    add_fsl_env:  bool, default False
        To activate the FSL environment, required for commands like bbregister.
    fsl_init: str
        Path to the Bash script setting the FSL environment, if needed.
    """
    fsprocess = FSWrapper(cmd)

    if subjects_dir is not None:
        fsprocess.environment["SUBJECTS_DIR"] = subjects_dir

    if add_fsl_env:
        fsl_env = environment(fsl_init)
        for k, i in fsl_env.items():
            if k not in fsprocess.environment:
                fsprocess.environment[k] = i
            else:
                # A variable that exists in both FS and FSL environments
                if k == "PATH":
                    fsprocess.environment["PATH"] += ":" + fsl_env["PATH"]
                else:
                    pass  # ignore this variable

    fsprocess()  # Run
    if fsprocess.exitcode != 0:
        raise FreeSurferRuntimeError(cmd[0], " ".join(cmd[1:]))

    return fsprocess
Ejemplo n.º 5
0
def conformed_to_native_space(
        fsdir,
        output_directory,
        fsconfig="/i2bm/local/freesurfer/SetUpFreeSurfer.sh"):
    """ Create a registration matrix between the conformed space (orig.mgz)
    and the native anatomical (rawavg.mgz).

    <unit>
        <input name="fsdir" type="Directory" description="The
            freesurfer working directory with all the subjects."/>
        <input name="output_directory" type="Directory" description="The
            default resample destination folder."/>
        <input name="fsconfig" type="File" description="The freesurfer
            configuration batch."/>
        <output name="trffiles" type="List_File"
            description="The conformed to native transformation files."/>
    </unit>
    """
    # Get all the subjects with a 'mri' directory
    mridirs = glob.glob(os.path.join(fsdir, "*", "mri"))
    with open(os.path.join(output_directory, "mris.json"), "w") as open_file:
        json.dump(mridirs, open_file, indent=4)

    # Go through all the subjects with the desired folder
    trffiles = []
    for mdir in mridirs:

        # Get some information based on the folder path
        subject_id = mdir.rstrip("/").split("/")[-2]
        convertdir = os.path.join(fsdir, subject_id, "convert")
        if not os.path.isdir(convertdir):
            os.makedirs(convertdir)

        # Check that the two images of interest are present
        rawfile = os.path.join(mdir, "rawavg.mgz")
        origfile = os.path.join(mdir, "orig.mgz")
        if not (os.path.isfile(rawfile) and os.path.isfile(origfile)):
            raise ValueError("In folder '{0}' can't find file '{1}' or file "
                             "'{2}'.".format(mdir, rawfile, origfile))

        # Construct the FS command
        trffile = os.path.join(convertdir, "register.native.dat")
        trffiles.append(trffile)
        cmd = [
            "tkregister2", "--mov", rawfile, "--targ", origfile, "--reg",
            trffile, "--noedit", "--regheader"
        ]

        # Execute the FS command
        recon = FSWrapper(cmd, shfile=fsconfig)
        recon()
        if recon.exitcode != 0:
            raise FreeSurferRuntimeError(recon.cmd[0], " ".join(recon.cmd[1:]),
                                         recon.stderr)

    return trffiles
Ejemplo n.º 6
0
def register_diffusion_to_anatomy(outdir,
                                  nodif_brain,
                                  subject_id,
                                  fs_subjects_dir = None,
                                  subdir          = "diff_to_anat",
                                  fsl_init        = "/etc/fsl/5.0/fsl.sh"):
    """
    Register the diffusion to the anatomy (T1) using Freesurfer bbregister
    (boundary-based registration).
    <unit>
        <input name="outdir"          type="Directory"           />
        <input name="nodif_brain"     type="File"                />
        <input name="subject_id"      type="Str"                 />
        <input name="fs_subjects_dir" type="Directory"           />
        <input name="subdir"          type="Str"                 />
        <input name="fsl_init"        type="File"                />

        <output name="dif2anat_dat"   type="File" description="
            The .dat file created by tkregister/bbregister cmd." />
    </unit>
    """

    if fs_subjects_dir is None:
        if "SUBJECTS_DIR" in os.environ:
            fs_subjects_dir = os.environ["SUBJECTS_DIR"]
        else:
            raise ValueError("Missing <SUBJECTS_DIR>: set the $SUBJECTS_DIR "
                             "environment variable for Freesurfer or pass it "
                             "as an argument.")

    # If a subdirectory name has been passed, adapt outdir
    if subdir:
        outdir = os.path.join(outdir, subdir)

    # Create outdir if it does not exist
    if not os.path.isdir(outdir):
        os.makedirs(outdir)

    dif2anat_dat = os.path.join(outdir, "dif2anat.dat")
    cmd = ["bbregister", "--s", subject_id, "--mov", nodif_brain,
           "--reg", dif2anat_dat, "--dti", "--init-fsl"]
    fsprocess = FSWrapper(cmd)
    fsprocess.environment["SUBJECTS_DIR"] = fs_subjects_dir

    # bbregister requires FSL, so we have to add the FSL environment
    fsl_env = environment(fsl_init)
    for k, i in fsl_env.items():
        if k not in fsprocess.environment:
            fsprocess.environment[k] = i
        else:
            # A variable that exists in both FS and FSL environments
            if k == "PATH":
                fsprocess.environment["PATH"] += ":" + fsl_env["PATH"]
            else:
                pass  # ignore this variable

    fsprocess()  # Run
    if fsprocess.exitcode != 0:
        raise FreeSurferRuntimeError(cmd[0], " ".join(cmd[1:]))

    return dif2anat_dat
Ejemplo n.º 7
0
def resample_cortical_surface(
        fsdir,
        regex,
        output_directory=None,
        orders=[4, 5, 6, 7],
        surface_name="white",
        fsconfig="/i2bm/local/freesurfer/SetUpFreeSurfer.sh"):
    """ Resamples one cortical surface onto an icosahedron.

    Resample the white or pial FreeSurfer cotical surface using the
    'mri_surf2surf' command. Map also the associated annotation file.

    Can resample at different icosahedron order which specifies the size of the
    icosahedron according to the following table:
    Order  Number of Vertices
    0              12
    1              42
    2             162
    3             642
    4            2562
    5           10242
    6           40962
    7          163842

    <unit>
        <input name="fsdir" type="Directory" description="The
            freesurfer working directory with all the subjects."/>
        <input name="regex" type="String" description="A regular expression
            used to locate the surface files to be converted from the 'fsdir'
            directory."/>
        <input name="output_directory" type="Directory" description="The
            default resample destination folder."/>
        <input name="orders" type="List_Int" description="The icosahedron
            orders."/>
        <input name="surface_name" type="String" description="The surface we
            want to resample ('white' or 'pial')."/>
        <input name="fsconfig" type="File" description="The freesurfer
            configuration batch."/>
        <output name="resamplefiles" type="List_File" description="The
            resample surfaces."/>
        <output name="annotfiles" type="List_File" description="The
            resample annotations."/>
    </unit>
    """
    # Check input parameters
    if surface_name not in ["white", "pial"]:
        raise ValueError("'{0}' is not a valid surface value which must be in "
                         "['white', 'pial']".format(surface_name))
    norders = numpy.asarray(orders)
    if norders.min() < 0 or norders.max() > 7:
        raise ValueError("'At least one value in {0} is not in 0-7 "
                         "range.".format(orders))

    # Get all the subjects with the specified surface
    surfaces = glob.glob(os.path.join(fsdir, regex))
    if output_directory is not None:
        path = os.path.join(output_directory, "surfaces.json")
        with open(path, "w") as open_file:
            json.dump(surfaces, open_file, indent=4)

    # Go through all the subjects with the desired surface
    resamplefiles = []
    annotfiles = []
    for surf in surfaces:

        # Get some information based on the surface path
        subject_id = surf.split("/")[-3]
        hemi = os.path.basename(surf).split(".")[0]
        convertdir = os.path.join(fsdir, subject_id, "convert")
        if not os.path.isdir(convertdir):
            os.makedirs(convertdir)

        # Go through all specified orders
        for level in orders:

            # Construct the FS surface map command
            convertfile = os.path.join(
                convertdir, "{0}.{1}.{2}".format(hemi, surface_name, level))
            resamplefiles.append(convertfile)
            cmd = [
                "mri_surf2surf", "--sval-xyz", surface_name, "--srcsubject",
                subject_id, "--trgsubject", "ico", "--trgicoorder",
                str(level), "--tval", convertfile, "--tval-xyz", "--hemi",
                hemi, "--sd", fsdir
            ]

            # Execute the FS command
            recon = FSWrapper(cmd, shfile=fsconfig)
            recon()
            if recon.exitcode != 0:
                raise FreeSurferRuntimeError(recon.cmd[0],
                                             " ".join(recon.cmd[1:]),
                                             recon.stderr + recon.stdout)

            # Construct the FS label map command
            annotfile = os.path.join(convertdir,
                                     "{0}.aparc.annot.{1}".format(hemi, level))
            annotfiles.append(annotfile)
            if not os.path.isfile(annotfile):
                svalannot = os.path.join(fsdir, subject_id, "label",
                                         "{0}.aparc.annot".format(hemi))
                cmd = [
                    "mri_surf2surf", "--srcsubject", subject_id,
                    "--trgsubject", "ico", "--trgicoorder",
                    str(level), "--hemi", hemi, "--sval-annot", svalannot,
                    "--tval", annotfile, "--sd", fsdir
                ]

                # Execute the FS command
                recon = FSWrapper(cmd, shfile=fsconfig)
                recon()
                if recon.exitcode != 0:
                    raise FreeSurferRuntimeError(recon.cmd[0],
                                                 " ".join(recon.cmd[1:]),
                                                 recon.stderr + recon.stdout)

    # Remove duplicate annotation files
    annotfiles = list(set(annotfiles))

    return resamplefiles, annotfiles
Ejemplo n.º 8
0
def mri_vol2surf(hemi,
                 volume_file,
                 texture_file,
                 ico_order,
                 dat_file,
                 fsdir,
                 sid,
                 surface_name="white",
                 fsconfig="/i2bm/local/freesurfer/SetUpFreeSurfer.sh"):
    """ Assigns values from a volume to each surface vertex.

    Wrapper around the FreeSurfer 'mri_vol2surf' command to create the
    described texture.

    Parameters
    ----------
    hemi: str (mandatory)
        hemisphere ('lh' or 'rh').
    volume_file: str (mandatory)
        input volume path.
    texture_file: str (mandatory)
        output texture file.
    ico_order: int (mandatory)
        icosahedron order in [0, 7] that will be used to generate the cortical
        surface texture at a specific tessalation (the corresponding cortical
        surface can be resampled using the
        'clindmri.segmentation.freesurfer.resample_cortical_surface' function).
    dat_file: str (mandatory)
        structural to FreeSurfer space affine transformation matrix '.dat'
        file as computed by 'tkregister2'.
    fsdir: str (mandatory)
        FreeSurfer subjects directory 'SUBJECTS_DIR'.
    sid: str (mandatory)
        FreeSurfer subject identifier.
    surface_name: str (optional, default 'white')
        The surface we  want to resample ('white' or 'pial').
    fsconfig: str (optional)
        The FreeSurfer '.sh' config file.
    """
    # Check input parameters
    if hemi not in ["lh", "rh"]:
        raise ValueError("'{0}' is not a valid hemisphere value which must be "
                         "in ['lh', 'rf']".format(hemi))
    if surface_name not in ["white", "pial"]:
        raise ValueError("'{0}' is not a valid surface value which must be in "
                         "['white', 'pial']".format(surface_name))
    if ico_order < 0 or ico_order > 7:
        raise ValueError("'Ico order '{0}' is not in 0-7 "
                         "range.".format(ico_order))

    # Construct the FS vol2surf command
    cmd = [
        "mri_vol2surf", "--src", volume_file, "--out", texture_file,
        "--srcreg", dat_file, "--hemi", hemi, "--trgsubject", "ico",
        "--icoorder", "{0}".format(ico_order), "--surf", surface_name, "--sd",
        fsdir, "--srcsubject", sid, "--noreshape", "--out_type", "mgz"
    ]

    # Execute the FS command
    recon = FSWrapper(cmd, shfile=fsconfig)
    recon()
    if recon.exitcode != 0:
        raise FreeSurferRuntimeError(recon.cmd[0], " ".join(recon.cmd[1:]),
                                     recon.stderr + recon.stdout)
Ejemplo n.º 9
0
def mri_convert(fsdir,
                regex,
                output_directory=None,
                reslice=True,
                interpolation="interpolate",
                fsconfig="/i2bm/local/freesurfer/SetUpFreeSurfer.sh"):
    """ Export Freesurfer "*.mgz" image in Nifti format.

    Convert in native space: the destination image is resliced like the
    'rawavg.mgz' file if the reslice option is set. The converted file will
    then have a '.native' suffix.

    <unit>
        <input name="fsdir" type="Directory" description="The
            freesurfer working directory with all the subjects."/>
        <input name="regex" type="String" description="A regular expression
            used to locate the files to be converted from the 'fsdir'
            directory."/>
        <input name="output_directory" type="Directory" description="The
            conversion destination folder."/>
        <input name="reslice" type="Bool" description="If true reslice the
            input images like the raw image."/>
        <input name="interpolation" type="String" description="The
            interpolation method: interpolate|weighted|nearest|cubic."/>
        <input name="fsconfig" type="File" description="The freesurfer
            configuration batch."/>
        <output name="niftifiles" type="List_File" description="The converted
            nifti files."/>
    </unit>
    """
    # Check the interpolation method
    if interpolation not in ["interpolate", "weighted", "nearest", "cubic"]:
        raise ValueError(
            "'{0}' is not a valid interpolation method.".format(interpolation))

    # Get the images to convert from the regex
    inputs = glob.glob(os.path.join(fsdir, regex))
    if output_directory is not None:
        path = os.path.join(output_directory, "inputs.json")
        with open(path, "w") as open_file:
            json.dump(inputs, open_file, indent=4)

    # Convert each input file
    niftifiles = []
    for inputfile in inputs:

        # Create the output directory
        subject = inputfile.replace(fsdir, "")
        subject = subject.lstrip(os.sep).split(os.sep)[0]
        outdir = os.path.join(fsdir, subject, "convert")
        if not os.path.isdir(outdir):
            os.makedirs(outdir)

        # Create the FS command
        basename = os.path.basename(inputfile).replace(".mgz", "")
        cmd = ["mri_convert", "--resample_type", interpolation]
        # "--out_orientation", "RAS"]
        if reslice:
            reference_file = os.path.join(fsdir, subject, "mri", "rawavg.mgz")
            if not os.path.isfile(reference_file):
                raise ValueError("'{0}' does not exists, can't reslice image "
                                 "'{1}'.".format(reference_file, inputfile))
            cmd += ["--reslice_like", reference_file]
            basename = basename + ".native"
        converted_file = os.path.join(outdir, basename + ".nii.gz")
        niftifiles.append(converted_file)
        cmd += [inputfile, converted_file]

        # Execute the FS command
        recon = FSWrapper(cmd, shfile=fsconfig)
        recon()
        if recon.exitcode != 0:
            raise FreeSurferRuntimeError(recon.cmd[0], " ".join(recon.cmd[1:]),
                                         recon.stderr + recon.stdout)

    return niftifiles
Ejemplo n.º 10
0
def recon_all(fsdir,
              anatfile,
              sid,
              output_directory=None,
              fsconfig="/i2bm/local/freesurfer/SetUpFreeSurfer.sh"):
    """ Performs all the FreeSurfer cortical reconstruction process.

    Processing stages:

    * Motion Correction and Conform
    * NU (Non-Uniform intensity normalization)
    * Talairach transform computation
    * Intensity Normalization 1
    * Skull Strip
    * EM Register (linear volumetric registration)
    * CA Intensity Normalization
    * CA Non-linear Volumetric Registration
    * Remove Neck
    * LTA with Skull
    * CA Label (Volumetric Labeling, ie Aseg) and Statistics
    * Intensity Normalization 2 (start here for control points)
    * White matter segmentation
    * Edit WM With ASeg
    * Fill (start here for wm edits)
    * Tessellation (begins per-hemisphere operations)
    * Smooth1
    * Inflate1
    * QSphere
    * Automatic Topology Fixer
    * Final Surfs (start here for brain edits for pial surf)
    * Smooth2
    * Inflate2
    * Spherical Mapping
    * Spherical Registration
    * Spherical Registration, Contralateral hemisphere
    * Map average curvature to subject
    * Cortical Parcellation - Desikan_Killiany and Christophe (Labeling)
    * Cortical Parcellation Statistics
    * Cortical Ribbon Mask
    * Cortical Parcellation mapping to Aseg

    <unit>
        <input name="fsdir" type="Directory" description="The
            freesurfer working directory with all the subjects."/>
        <input name="anatfile" type="File" desc="The input anatomical image
            to be segmented with freesurfer."/>
        <input name="sid" type="Str" description="The current subject
            identifier."/>
        <input name="output_directory" type="Directory" description="The
            freesurfer runtime folder."/>
        <input name="fsconfig" type="File" description="The freesurfer
            configuration batch."/>
        <output name="subjfsdir" type="Directory" description="Path to the
            resulting freesurfer segmentation."/>
    </unit>
    """
    # Create the fs output directory if necessary
    if not os.path.isdir(fsdir):
        os.makedirs(fsdir)

    # Call freesurfer
    cmd = ["recon-all", "-all", "-subjid", sid, "-i", anatfile, "-sd", fsdir]
    recon = FSWrapper(cmd, shfile=fsconfig)
    recon()
    if recon.exitcode != 0:
        raise FreeSurferRuntimeError(recon.cmd[0], " ".join(recon.cmd[1:]),
                                     recon.stderr + recon.stdout)
    subjfsdir = os.path.join(fsdir, sid)

    return subjfsdir