diff --git a/bip/data/FileTree.tree b/bip/data/FileTree.tree
index a698b9dd71f7ca5d95b6c25e16ea26d9bb64ebb0..57aa223b92cf152f659fa663a7c01fa20cbb0894 100644
--- a/bip/data/FileTree.tree
+++ b/bip/data/FileTree.tree
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:52f28bc678b0b136720d8eb04d6f8e4d56840e08de11c12fad48330e59418e63
-size 19808
+oid sha256:3691c74c7e48e228306c84723a8cecc4fca4edf3b89d16849cb2ee9c7f70fb2b
+size 19899
diff --git a/bip/ext_wrappers/__init__.py b/bip/ext_wrappers/__init__.py
index 6f7897898f281a690e4665229ffd80b3f89e5792..685f904fbf475979d62409f401c445ca7b21c06c 100755
--- a/bip/ext_wrappers/__init__.py
+++ b/bip/ext_wrappers/__init__.py
@@ -11,4 +11,6 @@
 them to be called from Python.
 """
 
-from bip.ext_wrappers.freesurfer   import  (recon_all)
+from bip.ext_wrappers.freesurfer import (recon_all,
+                                         asegstats2table,
+                                         aparcstats2table)
diff --git a/bip/ext_wrappers/extwrapperutils.py b/bip/ext_wrappers/extwrapperutils.py
deleted file mode 100644
index 31fe79ba166de58facfc0f9d63b2d279a4a6900a..0000000000000000000000000000000000000000
--- a/bip/ext_wrappers/extwrapperutils.py
+++ /dev/null
@@ -1,1297 +0,0 @@
-#!/usr/bin/env python
-#
-# wrapperutils.py - Functions and decorators used by the FSL wrapper
-# functions.
-#
-# Author: Paul McCarthy <pauldmccarthy@gmail.com>
-# Author: Martin Craig <martin.craig@eng.ox.ac.uk>
-#
-"""This module contains functions and decorators used by the FSL wrapper
-functions.
-
-
-The :func:`cmdwrapper` and :func:`fslwrapper` functions are convenience
-decorators which allow you to write your wrapper function such that it simply
-generates the command-line needed to respectively run a standard shell
-command or a FSL command. For example::
-
-
-    @fslwrapper
-    def fslreorient2std(input, output):
-        return ['fslreorient2std', input, output]
-
-
-When this ``fslreorient2std`` function is called, the ``fslwrapper`` decorator
-will take care of invoking the command in a standardised way.
-
-
-The :func:`applyArgStyle` function can be used to automatically convert
-keyword arguments into command-line arguments, based on a set of standard
-patterns. For example::
-
-
-    @fslwrapper
-    def flirt(src, ref, **kwargs):
-        cmd  = ['flirt', '-in', src, '-ref', ref]
-        return cmd + applyArgStyle('-=', **kwargs)
-
-
-The :func:`fileOrImage` and :func:`fileOrArray` functions can be used to
-decorate a wrapper function such that in-memory ``nibabel`` images or Numpy
-arrays can be passed in as arguments - they will be automatically saved out to
-files, and then the file names passed into the wrapper function. For example::
-
-
-    @fileOrImage('src', 'ref')
-    @fslwrapper
-    def flirt(src, ref, **kwargs):
-        cmd  = ['flirt', '-in', src, '-ref', ref]
-        return cmd + applyArgStyle('-=', **kwargs)
-
-
-Now this ``flirt`` function can be called either with file names, or
-``nibabel`` images.
-
-
-.. note:: Because the :func:`fileOrImage` and :func:`fileOrArray` decorators
-          manipulate the return value of the decorated function, they should
-          be applied *after* any other decorators. Furthermore, if you need to
-          apply both a ``fileOrImage`` and ``fileOrArray`` decorator to a
-          function, they should be grouped together, e.g.::
-
-              @fileOrImage('a', 'b')
-              @fileOrArray('c', 'd')
-              @fslwrapper
-              def func(**kwargs):
-                  ...
-
-
-Command outputs can also be loaded back into memory by using the special
-:data:`LOAD` value when calling a wrapper function. For example::
-
-
-    @fileOrImage('src', 'ref', 'out')
-    @fslwrapper
-    def flirt(src, ref, **kwargs):
-        cmd  = ['flirt', '-in', src, '-ref', ref]
-        return cmd + applyArgStyle('-=', **kwargs)
-
-
-If we set the ``out`` argument to ``LOAD``, the output image will be loaded
-and returned::
-
-    src     = nib.load('src.nii')
-    ref     = nib.load('ref.nii')
-    aligned = flirt(src, ref, out=LOAD)['out']
-"""
-
-
-import itertools       as it
-import os.path         as op
-import collections.abc as abc
-import                    os
-import                    re
-import                    sys
-import                    glob
-import                    random
-import                    string
-import                    pathlib
-import                    fnmatch
-import                    inspect
-import                    logging
-import                    tempfile
-import                    warnings
-import                    functools
-import                    contextlib
-
-import nibabel as nib
-import numpy   as np
-
-import fsl.utils.run        as run
-import fsl.utils.assertions as asrt
-import fsl.utils.path       as fslpath
-import fsl.utils.tempdir    as tempdir
-import fsl.data.image       as fslimage
-
-
-log = logging.getLogger(__name__)
-
-
-def _update_wrapper(wrapper, wrapped, *args, **kwargs):
-    """Replacement for the built-in ``functools.update_wrapper``. This
-    implementation ensures that the wrapper function has an attribute
-    called ``__wrapped__``, which refers to the ``wrapped`` function.
-
-    This custom function is only needed in Python versions < 3.4.
-    """
-
-    wrapper = functools.update_wrapper(wrapper, wrapped, *args, **kwargs)
-
-    # Python >= 3.4 does things right
-    if (sys.version_info[0] * 10 + sys.version_info[1]) < 34:
-        wrapper.__wrapped__ = wrapped
-    return wrapper
-
-
-def _unwrap(func):
-    """Replacement for the built-in ``inspect.unwrap`` function, which
-    is not present in Python versions prior to 3.4.
-    """
-
-    # Python >= 3.4 has an inspect.unwrap function
-    if (sys.version_info[0] * 10 + sys.version_info[1]) >= 34:
-        return inspect.unwrap(func)
-
-    # Otherwise we follow the __wrapped__ chain ourselves
-    if hasattr(func, '__wrapped__'):
-        return _unwrap(func.__wrapped__)
-
-    return func
-
-
-def genxwrapper(func, runner):
-    """This function is used by :func:`cmdwrapper` and :func:`fslwrapper`.
-    It is not intended to be used in any other circumstances.
-
-    This function generates a wrapper function which calls ``func`` to
-    generate a command-line call, and then uses ``runner`` to invoke that
-    command.
-
-    ``func`` is assumed to be a wrapper function which generates a command-
-    line. ``runner`` is assumed to be Either :func:`.run.run` or
-    :func:`.run.runfsl`.
-
-    The generated wrapper function will pass all of its arguments to ``func``,
-    and will then pass the generated command-line to ``runner``, returning
-    whatever is returned.
-
-    The following keyword arguments will be intercepted by the wrapper
-    function, and will *not* be passed to ``func``:
-
-      - ``stdout``:   Passed to ``runner``. Defaults to ``True``.
-      - ``stderr``:   Passed to ``runner``. Defaults to ``True``.
-      - ``exitcode``: Passed to ``runner``. Defaults to ``False``.
-      - ``submit``:   Passed to ``runner``. Defaults to ``None``.
-      - ``log``:      Passed to ``runner``. Defaults to ``{'tee':True}``.
-      - ``cmdonly``:  Passed to ``runner``. Defaults to ``False``.
-
-    The default values for these arguments are stored in the
-    ``genxwrapper.run_options`` dictionary. This dictionary should not be
-    changed directly, but rather can be temporarily modified via the
-    :func:`wrapperconfig` context manager function.
-
-    :arg func:   A function which generates a command line.
-    :arg runner: Either :func:`.run.run` or :func:`.run.runfsl`.
-    """
-
-    def wrapper(*args, **kwargs):
-        opts     = genxwrapper.run_options
-        stdout   = kwargs.pop('stdout',   opts['stdout'])
-        stderr   = kwargs.pop('stderr',   opts['stderr'])
-        exitcode = kwargs.pop('exitcode', opts['exitcode'])
-        submit   = kwargs.pop('submit',   opts['submit'])
-        cmdonly  = kwargs.pop('cmdonly',  opts['cmdonly'])
-        logg     = kwargs.pop('log',      opts['log'])
-
-        # many wrapper functions use fsl.utils.assertions
-        # statements to check that input arguments are
-        # valid. Disable these if the cmdonly argument is
-        # being used to generate a command without running
-        # it.
-        with asrt.disabled(cmdonly):
-            cmd = func(*args, **kwargs)
-
-        return runner(cmd,
-                      stderr=stderr,
-                      log=logg,
-                      submit=submit,
-                      cmdonly=cmdonly,
-                      stdout=stdout,
-                      exitcode=exitcode)
-
-    return _update_wrapper(wrapper, func)
-
-
-genxwrapper.run_options = {
-    'stdout'   : True,
-    'stderr'   : True,
-    'exitcode' : False,
-    'submit'   : None,
-    'log'      : {'tee' : True},
-    'cmdonly'  : False
-}
-
-
-def cmdwrapper(func):
-    """This decorator can be used on functions which generate a command line.
-    It will pass the return value of the function to the
-    :func:`fsl.utils.run.run` function in a standardised manner.
-
-    See the :func:`genxwrapper` function for details.
-    """
-    return genxwrapper(func, run.run)
-
-
-def fslwrapper(func):
-    """This decorator can be used on functions which generate a FSL command
-    line. It will pass the return value of the function to the
-    :func:`fsl.utils.run.runfsl` function in a standardised manner.
-
-    See the :func:`genxwrapper` function for details.
-    """
-    return genxwrapper(func, run.runfsl)
-
-
-@contextlib.contextmanager
-def wrapperconfig(**kwargs):
-    """Context manager to be used when calling wrapper functions. Can modify
-    the options/arguments that are passed to :func:`fsl.utils.run.run` when
-    calling a command from a wrapper function. For example::
-
-        with wrapperconfig(stdout=False):
-            bet('struct', 'struct_brain')
-    """
-    opts = dict(genxwrapper.run_options)
-    genxwrapper.run_options.update(kwargs)
-    try:
-        yield
-    finally:
-        genxwrapper.run_options = opts
-
-
-SHOW_IF_TRUE = object()
-"""Constant to be used in the ``valmap`` passed to the :func:`applyArgStyle`
-function.
-
-When a ``SHOW_IF_TRUE`` argument is ``True``, it is added to the generated
-command line arguments.
-"""
-
-
-HIDE_IF_TRUE = object()
-"""Constant to be used in the ``valmap`` passed to the :func:`applyArgStyle`
-function.
-
-When a ``HIDE_IF_TRUE`` argument is ``True``, it is suppressed from the
-generated command line arguments.
-"""
-
-
-def applyArgStyle(style=None,
-                  valsep=None,
-                  argmap=None,
-                  valmap=None,
-                  singlechar_args=False,
-                  charstyle=None,
-                  charsep=None,
-                  **kwargs):
-    """Turns the given ``kwargs`` into command line options. This function
-    is intended to be used to automatically generate command line options
-    from arguments passed into a Python function.
-
-    The default settings will generate arguments that match typical UNIX
-    conventions, e.g. ``-a val``, ``--arg=val``, ``-a val1 val2``,
-    ``--arg=val1,val2``.
-
-    The ``style`` and ``valsep`` options (and ``charstyle`` and ``charsep``,
-    for single-character/short arguments) control how key-value pairs are
-    converted into command-line options:
-
-
-    =========  ==========  ===========================
-    ``style``  ``valsep``  Result
-    =========  ==========  ===========================
-    ``'-'``    ``' '``     ``-name val1 val2 val3``
-    ``'-'``    ``'"'``     ``-name "val1 val2 val3"``
-    ``'-'``    ``','``     ``-name val1,val2,val3``
-    ``'--'``   ``' '``     ``--name val1 val2 val3``
-    ``'--'``   ``'"'``     ``--name "val1 val2 val3"``
-    ``'--'``   ``','``     ``--name val1,val2,val3``
-    ``'-='``   ``' '``     Not supported
-    ``'-='``   ``'"'``     ``-name="val1 val2 val3"``
-    ``'-='``   ``','``     ``-name=val1,val2,val3``
-    ``'--='``  ``' '``     Not supported
-    ``'--='``  ``'"'``     ``--name="val1 val2 val3"``
-    ``'--='``  ``','``     ``--name=val1,val2,val3``
-    =========  ==========  ===========================
-
-
-    :arg style:     Controls how the ``kwargs`` are converted into command-line
-                    options - must be one of ``'-'``, ``'--'``, ``'-='``, or
-                    ``'--='`` (the default).
-
-    :arg valsep:    Controls how the values passed to command-line options
-                    which expect multiple arguments are delimited - must be
-                    one of ``' '``, ``','`` or ``'"'``. Defaults to ``' '``
-                    if ``'=' not in style``, ``','`` otherwise.
-
-    :arg argmap:    Dictionary of ``{kwarg-name : cli-name}`` mappings. This be
-                    used if you want to use different argument names in your
-                    Python function for the command-line options.
-
-    :arg valmap:    Dictionary of ``{cli-name : value}`` mappings. This can be
-                    used to define specific semantics for some command-line
-                    options. Acceptable values for ``value`` are as follows
-
-                     - :data:`SHOW_IF_TRUE` - if the argument is present, and
-                       ``True`` in ``kwargs``, the command line option
-                       will be added (without any arguments).
-
-                     - :data:`HIDE_IF_TRUE` - if the argument is present, and
-                       ``False`` in ``kwargs``, the command line option
-                       will be added (without any arguments).
-
-                     - Any other constant value. If the argument is present
-                       in ``kwargs``, its command-line option will be
-                       added, with the constant value as its argument.
-
-                    The argument for any options not specified in the
-                    ``valmap`` will be converted into strings.
-
-    :arg charstyle: Separate style specification for single-character
-                    arguments. If ``style == '--='``, defaults to ``'-'``,
-                    matching UNIX conventions. Otherwise defaults to the
-                    value of ``style``.
-
-    :arg charsep:   Controls how the values passed to command-line options
-                    which expect multiple arguments are delimited - must be
-                    one of ``' '``, ``','`` or ``'"'``. Defaults to ``' '``
-                    if ``'=' not in style``, ``','`` otherwise.
-
-    :arg singlechar_args: If ``True``, equivalent to ``charstyle='-'``. This
-                          argument remains for compatibility, but may be
-                          removed in a future version.
-
-    :arg kwargs: Arguments to be converted into command-line options.
-
-    :returns:    A sequence containing the generated command-line options, the
-                 same as what ``shlex.split`` would generate for a properly
-                 quoted string.
-    """
-
-    if style is None:
-        style = '--='
-
-    if charstyle is None:
-        if   singlechar_args: charstyle = '-'
-        elif style == '--=':  charstyle = '-'
-        else:                 charstyle = style
-
-    if valsep is None:
-        if '=' in style: valsep = ','
-        else:            valsep = ' '
-
-    if charsep is None:
-        if '=' in charstyle: charsep = ','
-        else:                charsep = ' '
-
-    if style not in ('-', '--', '-=', '--='):
-        raise ValueError(f'Invalid style: {style}')
-    if charstyle not in ('-', '--', '-=', '--='):
-        raise ValueError(f'Invalid charstyle: {charstyle}')
-    if valsep not in (' ', ',', '"'):
-        raise ValueError(f'Invalid valsep: {valsep}')
-    if charsep not in (' ', ',', '"'):
-        raise ValueError(f'Invalid charsep: {charsep}')
-
-    # It makes no sense to combine argument+value
-    # with an equals sign, but not have the value
-    # quoted (e.g "--arg=val1 val2 val3").
-    if '=' in style and valsep == ' ':
-        raise ValueError(f'Incompatible style {style} '
-                         'and valsep ({valsep})')
-    if '=' in charstyle and charsep == ' ':
-        raise ValueError(f'Incompatible style {charstyle} '
-                         'and valsep ({charsep})')
-
-    if argmap is None: argmap = {}
-    if valmap is None: valmap = {}
-
-    # Format the argument.
-    def fmtarg(arg, style):
-        if style in ('--', '--='): return f'--{arg}'
-        else:                      return f'-{arg}'
-
-    # Formt the argument value.
-    def fmtval(val, sep):
-        if isinstance(val, abc.Sequence) and (not isinstance(val, str)):
-            val = [str(v) for v in val]
-            if   sep == ' ': return val
-            elif sep == '"': return [' '.join(val)]
-            else:            return [sep.join(val)]
-        else:
-            return [str(val)]
-
-    # Combine the argument and value together.
-    # val is assumed to be a sequence.
-    def fmtargval(arg, val, style):
-        # if '=' in style, val will
-        # always be a single string
-        if '=' in style: return ['{}={}'.format(arg, val[0])]
-        else:            return [arg] + val
-
-    args = []
-
-    for k, v in kwargs.items():
-
-        if v is None: continue
-
-        if len(k) == 1: sty, sep = charstyle, charsep
-        else:           sty, sep = style,     valsep
-
-        k    = argmap.get(k, k)
-        mapv = valmap.get(k, fmtval(v, sep))
-        k    = fmtarg(k, sty)
-
-        if mapv in (SHOW_IF_TRUE, HIDE_IF_TRUE):
-            if (mapv is SHOW_IF_TRUE and     v) or \
-               (mapv is HIDE_IF_TRUE and not v):
-                args.append(k)
-        else:
-            args.extend(fmtargval(k, mapv, sty))
-
-    return args
-
-
-def namedPositionals(func, args):
-    """Given a function, and a sequence of positional arguments destined
-    for that function, identifies the name for each positional argument.
-    Variable positional arguments are given an automatic name.
-
-    :arg func: Function which will accept ``args`` as positionals.
-    :arg args: Tuple of positional arguments to be passed to ``func``.
-    """
-
-    # Remove any decorators
-    # from the function
-    func = _unwrap(func)
-
-    # getargspec is the only way to
-    # get the names of positional
-    # arguments in Python 2.x.
-    if sys.version_info[0] < 3:
-        spec     = inspect.getargspec(func)
-        argnames = spec.args
-        varargs  = spec.varargs
-
-    # But getargspec is deprecated
-    # in python 3.x
-    else:
-
-        # getfullargspec is deprecated in
-        # python 3.5, but not in python 3.6.
-        with warnings.catch_warnings():
-            warnings.filterwarnings('ignore', category=DeprecationWarning)
-            spec     = inspect.getfullargspec(func)
-            argnames = spec.args
-            varargs  = spec.varargs
-
-    # we only care about the arguments
-    # that are being passed in
-    argnames = argnames[:len(args)]
-
-    # generate names for varargs
-    nvarargs = len(args) - len(argnames)
-    suffix   = namedPositionals.varargsSuffix
-    if varargs is not None and nvarargs > 0:
-        argnames += [f'{varargs}{i}{suffix}' for i in range(nvarargs)]
-
-    return argnames
-namedPositionals.varargsSuffix = '_VARARG'
-
-
-LOAD = object()
-"""Constant used by the :class:`FileOrThing` class to indicate that an output
-file should be loaded into memory and returned as a Python object.
-"""
-
-
-class FileOrThing:
-    """Decorator which ensures that certain arguments which are passed into the
-    decorated function are always passed as file names. Both positional and
-    keyword arguments can be specified.
-
-
-    The ``FileOrThing`` class is not intended to be used directly - see the
-    :func:`fileOrImage` and :func:`fileOrArray` decorator functions for more
-    details.
-
-
-    These decorators are intended for functions which wrap a command-line tool,
-    i.e. where some inputs/outputs need to be specified as file names.
-
-
-    **Inputs**
-
-
-    Any arguments which are not of type ``Thing`` are passed through to the
-    decorated function unmodified.  Arguments which are of type ``Thing`` are
-    saved to a temporary file, and the name of that file is passed to the
-    function.
-
-
-    **Outputs**
-
-
-    If an argument is given the special :data:`LOAD` value, it is assumed
-    to be an output argument. In this case, it is replaced with a temporary
-    file name then, after the function has completed, that file is loaded
-    into memory, and the value returned (along with the function's output,
-    and any other arguments with a value of ``LOAD``).
-
-
-    **Return value**
-
-
-    Functions decorated with a ``FileOrThing`` decorator will always return a
-    ``dict``-like object, where the function's actual return value is
-    accessible via an attribute called ``stdout``. All output arguments with a
-    value of ``LOAD`` will be present as dictionary entries, with the keyword
-    argument names used as keys; these values will also be accessible as
-    attributes of the results dict, when possible. Any ``LOAD`` output
-    arguments which were not generated by the function will not be present in
-    the dictionary.
-
-
-    **Exceptions**
-
-
-    The above description holds in all situations, except when arguments called
-    ``submit`` and/or ``cmdonly`` are passed, and are set to values which
-    evaluate to ``True``. In this case, the ``FileOrThing`` decorator will pass
-    all arguments straight through to the decorated function, and will return
-    its return value unchanged.
-
-    This is because most functions that are decorated with the
-    :func:`fileOrImage` or :func:`fileOrArray` decorators will invoke a call
-    to :func:`.run.run` or :func:`.runfsl`, where:
-
-      - a value of ``submit=True`` will cause the command to be executed
-        asynchronously on a cluster platform.
-      - a value of ``cmdonly=True`` will cause the command to *not* be executed,
-        but instead the command that would have been executed is returned.
-
-    A :exc:`ValueError` will be raised if the decorated function is called
-    with ``submit=True`` and/or ``cmdonly=True``, and with any in-memory
-    objects or ``LOAD`` symbols.
-
-
-    **Example**
-
-
-    As an example of using the ``fileOrArray`` decorator on a function
-    which concatenates two files containing affine transformations, and
-    saves the output to a file::
-
-        # if atob, btoc, or output are passed
-        # in as arrays, they are converted to
-        # file names.
-        @fileOrArray('atob', 'btoc', 'output')
-        def concat(atob, btoc, output=None):
-
-            # inputs are guaranteed to be files
-            atob = np.loadtxt(atob)
-            btoc = np.loadtxt(atoc)
-
-            atoc = np.dot(btoc, atob)
-
-            if output is not None:
-                np.savetxt(output, atoc)
-
-            return 'Done'
-
-
-    Because we have decorated the ``concat`` function with :func:`fileToArray`,
-    it can be called with either file names, or Numpy arrays::
-
-
-        # All arguments are passed through
-        # unmodified - the output will be
-        # saved to a file called atoc.mat.
-        concat('atob.txt', 'btoc.txt', 'atoc.mat')
-
-        # The function's return value
-        # is accessed via an attribute called
-        # "stdout" on the dict
-        assert concat('atob.txt', 'btoc.txt', 'atoc.mat').stdout == 'Done'
-
-        # Outputs to be loaded into memory
-        # are returned in a dictionary,
-        # with argument names as keys. Values
-        # can be accessed as dict items, or
-        # as attributes.
-        atoc = concat('atob.txt', 'btoc.txt', LOAD)['atoc']
-        atoc = concat('atob.txt', 'btoc.txt', LOAD).atoc
-
-        # In-memory inputs are saved to
-        # temporary files, and those file
-        # names are passed to the concat
-        # function.
-        atoc = concat(np.diag([2, 2, 2, 0]),
-                      np.diag([3, 3, 3, 3]), LOAD).atoc
-
-
-    **Using with other decorators**
-
-
-    ``FileOrThing`` decorators can be chained with other ``FileOrThing``
-    decorators, and other decorators.  When multiple ``FileOrThing``
-    decorators are used on a single function, the outputs from each decorator
-    are merged together into a single dict-like object.
-
-
-    ``FileOrThing`` decorators can be used with any other decorators
-    **as long as** they do not manipulate the return value, and as long as
-    the ``FileOrThing`` decorators are adjacent to each other.
-    """
-
-
-    class Results(dict):
-        """A custom ``dict`` type used to return outputs from a function
-        decorated with ``FileOrThing``. All outputs are stored as dictionary
-        items, with the argument name as key, and the output object (the
-        "thing") as value.
-
-        Where possible (i.e. for outputs named with a valid Python
-        identifier), the outputs are also made accessible as attributes of
-        the ``Results`` object.
-
-        The decorated function's actual return value is accessible via the
-        :meth:`stdout` property.
-        """
-
-
-        def __init__(self, stdout):
-            """Create a ``Results`` dict.
-
-            :arg stdout: Return value of the decorated function (typically a
-                         tuple containing the standard output and error of the
-                         underlying command).
-            """
-            super().__init__()
-            self.__stdout = stdout
-
-
-        def __setitem__(self, key, val):
-            """Add an item to the dict. The item is also added as an attribute.
-            """
-            super().__setitem__(key, val)
-            setattr(self, key, val)
-
-
-        @property
-        def stdout(self):
-            """Access the return value of the decorated function. """
-            return self.__stdout
-
-
-    def __init__(self,
-                 func,
-                 prepIn,
-                 prepOut,
-                 load,
-                 removeExt,
-                 *args,
-                 **kwargs):
-        """Initialise a ``FileOrThing`` decorator.
-
-        :arg func:      The function to be decorated.
-
-        :arg prepIn:    Function which returns a file name to be used in
-                        place of an input argument.
-
-        :arg prepOut:   Function which generates a file name to use for
-                        arguments that were set to :data:`LOAD`.
-
-        :arg load:      Function which is called to load items for arguments
-                        that were set to :data:`LOAD`. Must accept the
-                        following arguments:
-
-                         - the name of the argument
-                         - path to the file to be loaded
-
-        :arg removeExt: Function which can remove a file extension from a file
-                        path.
-
-        :arg outprefix: Must be passed as a keyword argument. The name of a
-                        positional or keyword argument to the function, which
-                        specifies an output file name prefix.  All other
-                        arguments with names that begin with this prefix may
-                        be interpreted as things to ``LOAD``.
-
-        All other positional arguments are interpreted as the names of the
-        arguments to the function which will be handled by this
-        ``FileOrThing`` decorator. If not provided, *all* arguments passed to
-        the function will be handled.
-
-
-        The ``prepIn`` and ``prepOut`` functions must accept the following
-        positional arguments:
-
-          - A directory in which all temporary input/output files should be
-            stored
-
-          - The name of the keyword argument to be processed
-
-          - The argument value that was passed in
-        """
-
-        self.__func      = func
-        self.__prepIn    = prepIn
-        self.__prepOut   = prepOut
-        self.__load      = load
-        self.__removeExt = removeExt
-        self.__things    = args
-        self.__outprefix = kwargs.get('outprefix', None)
-
-
-    def __call__(self, *args, **kwargs):
-        """Function which calls ``func``, ensuring that any arguments of
-        type ``Thing`` are saved to temporary files, and any arguments
-        with the value :data:`LOAD` are loaded and returned.
-
-        All other arguments are passed through to ``func``.
-        """
-
-        func     = self.__func
-        argnames = namedPositionals(func, args)
-
-        # Special case - if fsl.utils.run[fsl] is
-        # being decorated (e.g. via cmdwrapper/
-        # fslwrapper), and submit=True or
-        # cmdonly=True, this call will ultimately
-        # submit the job to the cluster, or will
-        # return the command that would have been
-        # executed, and will return immediately.
-        #
-        # We error if we are given any in-memory
-        # things, or LOAD symbols.
-        #
-        # n.b. testing values to be strings could
-        # interfere with the fileOrText decorator.
-        # Possible solution is to use pathlib?
-        if kwargs.get('submit',  False) or \
-           kwargs.get('cmdonly', False):
-            allargs = {**dict(zip(argnames, args)), **kwargs}
-            for name, val in allargs.items():
-                if (name in self.__things) and (not isinstance(val, str)):
-                    raise ValueError('Cannot use in-memory objects '
-                                     'or LOAD with submit=True!')
-            return func(*args, **kwargs)
-
-        # If this FileOrThing is being called
-        # by another FileOrThing don't create
-        # another working directory. We do this
-        # sneakily, by setting an attribute on
-        # the wrapped function which stores the
-        # current working directory.
-        wrapped     = _unwrap(func)
-        fot_workdir = getattr(wrapped, '_fot_workdir', None)
-        parent      = fot_workdir is None
-
-        # Create a tempdir to store any temporary
-        # input/output things, but don't change
-        # into it, as file paths passed to the
-        # function may be relative.
-        with tempdir.tempdir(changeto=False, override=fot_workdir) as td:
-
-            log.debug('Redirecting LOADed outputs to %s', td)
-
-            # Replace any things with file names.
-            # Also get a list of LOAD outputs
-            args = self.__prepareArgs(parent, td, argnames, args, kwargs)
-            args, kwargs, outprefix, outfiles, prefixes = args
-
-            # The prefix/patterns may be
-            # overridden by a parent FoT
-            outprefix = getattr(wrapped, '_fot_outprefix', outprefix)
-            prefixes  = getattr(wrapped, '_fot_prefixes',  prefixes)
-
-            # if there are any other FileOrThings
-            # in the decorator chain, get them to
-            # use our working directory, and
-            # prefixes, instead of creating their
-            # own.
-            if parent:
-                setattr(wrapped, '_fot_workdir',   td)
-                setattr(wrapped, '_fot_outprefix', outprefix)
-                setattr(wrapped, '_fot_prefixes',  prefixes)
-
-            # Call the function
-            try:
-                result = func(*args, **kwargs)
-
-            finally:
-                # if we're the top-level FileOrThing
-                # decorator, remove the attributes we
-                # added above.
-                if parent:
-                    delattr(wrapped, '_fot_workdir')
-                    delattr(wrapped, '_fot_outprefix')
-                    delattr(wrapped, '_fot_prefixes')
-
-            return self.__generateResult(
-                td, result, outprefix, outfiles, prefixes)
-
-
-    def __prepareArgs(self, parent, workdir, argnames, args, kwargs):
-        """Prepares all input and output arguments to be passed to the
-        decorated function. Any arguments with a value of :data:`LOAD` are
-        passed to the ``prepOut`` function specified at :meth:`__init__`.
-        All other arguments are passed through the ``prepIn`` function.
-
-        :arg parent:   ``True`` if this ``FileOrThing`` is the first in a
-                       chain of ``FileOrThing`` decorators.
-
-        :arg workdir:  Directory in which all temporary files should be stored.
-
-        :arg argnames: Names for each positional argument.
-
-        :arg args:     Positional arguments to be passed to the decorated
-                       function.
-
-        :arg kwargs:   Keyword arguments to be passed to the decorated
-                       function.
-
-        :returns:      A tuple containing:
-
-                        - An updated copy of ``args``.
-
-                        - An updated copy of ``kwargs``.
-
-                        - The output file prefix that was actually passed in
-                          (it is subsequently modified so that prefixed outputs
-                          are redirected to a temporary location). All prefixed
-                          outputs that are not ``LOAD``ed should be moved into
-                          this directory. ``None`` if there is no output
-                          prefix.
-
-                        - A dictionary of ``{ name : filename }`` mappings,
-                          for all arguments with a value of ``LOAD``.
-
-                        - A dictionary of ``{ filepat : replstr }`` paths, for
-                          all output-prefix arguments with a value of ``LOAD``.
-        """
-
-        # These containers keep track
-        # of output files which are to
-        # be loaded into memory
-        outfiles      = dict()
-        prefixedFiles = dict()
-
-        allargs  = {k : v for k, v in zip(argnames, args)}
-        allargs.update(kwargs)
-
-        # Has an output prefix been specified?
-        prefix     = allargs.get(self.__outprefix, None)
-        realPrefix = None
-
-        # Prefixed outputs are only
-        # managed by the parent
-        # FileOrthing in a chain of
-        # FoT decorators.
-        if not parent:
-            prefix = None
-
-        # If so, replace it with a new output
-        # prefix which will redirect all output
-        # to the temp dir.
-        #
-        # Importantly, here we assume that the
-        # underlying function (and hence the
-        # underlying command-line tool) will
-        # accept an output prefix which contains
-        # a directory path.
-        if prefix is not None:
-            if isinstance(prefix, pathlib.Path):
-                prefix = op.abspath(prefix)
-
-            # If prefix is set to LOAD,
-            # all generated output files
-            # should be loaded - we use a
-            # randomly generated prefix,
-            # and add it to prefixedFiles,
-            # so that every file which
-            # starts with it will be
-            # loaded.
-            if prefix is LOAD:
-                prefix                = random.sample(string.ascii_letters, 10)
-                prefix                = ''.join(prefix)
-                prefixedFiles[prefix] = self.__outprefix
-
-            realPrefix                = prefix
-            fakePrefix                = op.join(workdir, prefix)
-            allargs[self.__outprefix] = fakePrefix
-
-            log.debug('Replacing output prefix: %s -> %s',
-                      realPrefix, fakePrefix)
-
-            # If the prefix specifies a
-            # directory, make sure it
-            # exists (remember that we're
-            # in a temporary directory)
-            pdir = op.dirname(fakePrefix)
-            if pdir != '' and not op.exists(pdir):
-                os.makedirs(pdir)
-
-        if len(self.__things) > 0: things = self.__things
-        else:                      things = allargs.keys()
-
-        for name, val in list(allargs.items()):
-
-            # don't process the
-            # outprefix argument
-            if name == self.__outprefix:
-                continue
-
-            # is this argument referring
-            # to a prefixed output?
-            isprefixed = (prefix is not None and
-                          name.startswith(prefix))
-
-            if not any((isprefixed,
-                        name in things,
-                        name.endswith(namedPositionals.varargsSuffix))):
-                continue
-
-            # Prefixed output files may only
-            # be given a value of LOAD
-            if isprefixed and val is not LOAD:
-                raise ValueError('Cannot specify name of prefixed file - the '
-                                 'name is defined by the output prefix: '
-                                 '{}'.format(name))
-
-            if val is LOAD:
-
-                # this argument refers to an output
-                # that is generated from the output
-                # prefix argument, and doesn't map
-                # directly to an argument of the
-                # function. So we don't pass it
-                # through.
-                if isprefixed:
-                    prefixedFiles[name] = name
-                    allargs.pop(name)
-
-                # regular output-file argument
-                else:
-                    outfile = self.__prepOut(workdir, name, val)
-                    outfiles[name] = outfile
-                    allargs[ name] = outfile
-
-            # Assumed to be an input file
-            else:
-                # sequences may be
-                # accepted for inputs
-                if isinstance(val, (list, tuple)):
-                    infile = list(val)
-                    for i, v in enumerate(val):
-                        v = self.__prepIn(workdir, name, v)
-                        if v is not None:
-                            infile[i] = v
-
-                else:
-                    infile = self.__prepIn(workdir, name, val)
-
-                if infile is not None:
-                    allargs[name] = infile
-
-        if realPrefix is not None and len(prefixedFiles) == 0:
-            allargs[self.__outprefix] = realPrefix
-
-        # Turn any Path objects into absolute path
-        # strings. Don't use Path.resolve(), as it
-        # returns a relative path for non-existent
-        # files/dirs on Windows/certain Python
-        # versions.
-        for k, v in allargs.items():
-            if isinstance(v, pathlib.Path):
-                allargs[k] = op.abspath(v)
-
-        args   = [allargs.pop(k) for k in argnames]
-        kwargs = allargs
-
-        return args, kwargs, realPrefix, outfiles, prefixedFiles
-
-
-    def __generateResult(
-            self, workdir, result, outprefix, outfiles, prefixes):
-        """Loads function outputs and returns a :class:`Results` object.
-
-        Called by :meth:`__call__` after the decorated function has been
-        called. Figures out what files should be loaded, and loads them into
-        a ``Results`` object.
-
-        :arg workdir:   Directory which contains the function outputs.
-        :arg result:    Function return value.
-        :arg outprefix: Original output prefix that was passed into the
-                        function (or ``None`` if one wasn't passed)
-        :arg outfiles:  Dictionary containing output files to be loaded (see
-                        :meth:`__prepareArgs`).
-        :arg prefixes:  Dictionary containing output-prefix patterns to be
-                        loaded (see :meth:`__prepareArgs`).
-
-        :returns:       A ``Results`` object containing all loaded outputs.
-        """
-
-        # make a Results object to store
-        # the output. If we are decorating
-        # another FileOrThing, the
-        # results will get merged together
-        # into a single Results dict.
-        if not isinstance(result, FileOrThing.Results):
-            result = FileOrThing.Results(result)
-
-        # Load the LOADed outputs
-        for oname, ofile in outfiles.items():
-
-            log.debug('Loading output %s: %s', oname, ofile)
-
-            if op.exists(ofile): oval = self.__load(oname, ofile)
-            else:                oval = None
-
-            result[oname] = oval
-
-        # No output prefix - we're done
-        if outprefix is None or len(prefixes) == 0:
-            return result
-
-        # Load or move output-prefixed files.
-        # Find all files with a name that
-        # matches the prefix that was passed
-        # in (recursing into matching sub-
-        # directories too).
-        allPrefixed = glob.glob(op.join(workdir, '{}*'.format(outprefix)))
-        allPrefixed = [fslpath.allFiles(f) if op.isdir(f) else [f]
-                       for f in allPrefixed]
-
-        for prefixed in it.chain(*allPrefixed):
-            fullpath = prefixed
-            prefixed = op.relpath(prefixed, workdir)
-            for prefPat, prefName in prefixes.items():
-                if not fnmatch.fnmatch(prefixed, '{}*'.format(prefPat)):
-                    continue
-
-                log.debug('Loading prefixed output %s [%s]: %s',
-                          prefPat, prefName, prefixed)
-
-                noext   = self.__removeExt(prefixed)
-                prefPat = prefPat.replace('\\', '\\\\')
-                noext   = re.sub('^' + prefPat, prefName, noext)
-                withext = re.sub('^' + prefPat, prefName, prefixed)
-
-                # if the load function returns
-                # None, this file is probably
-                # not of the correct type.
-                fval = self.__load(noext, fullpath)
-                if fval is not None:
-
-                    # If there is already an item in result with the
-                    # name (stripped of prefix), then instead store
-                    # the result with the full prefixed name
-                    if noext not in result:
-                        result[noext] = fval
-                    else:
-                        result[withext] = fval
-                    break
-
-        return result
-
-
-def fileOrImage(*args, **kwargs):
-    """Decorator which can be used to ensure that any NIfTI images are saved
-    to file, and output images can be loaded and returned as ``nibabel``
-    image objects or :class:`.Image` objects.
-    """
-
-    # keep track of the input argument
-    # types on each call, so we know
-    # whether to return a fsl.Image or
-    # a nibabel image
-    intypes = []
-
-    def prepIn(workdir, name, val):
-
-        infile = None
-
-        if isinstance(val, fslimage.Image):
-            intypes.append(fslimage.Image)
-
-        elif isinstance(val, nib.nifti1.Nifti1Image):
-            intypes.append(nib.nifti1.Nifti1Image)
-
-        if isinstance(val, fslimage.Image):
-            val = val.nibImage
-
-        if isinstance(val, nib.nifti1.Nifti1Image):
-            infile = val.get_filename()
-
-            # in-memory image - we have
-            # to save it out to a file
-            if infile is None or not op.exists(infile):
-                hd, infile = tempfile.mkstemp(fslimage.defaultExt(),
-                                              dir=workdir)
-                os.close(hd)
-
-                # Create a copy of the input image and
-                # save that, so the original doesn't
-                # get associated with the temp file
-                val = nib.nifti1.Nifti1Image(
-                    np.asanyarray(val.dataobj), None, val.header)
-                val.to_filename(infile)
-
-        return infile
-
-    def prepOut(workdir, name, val):
-        return op.join(workdir, '{}.nii.gz'.format(name))
-
-    def load(name, path):
-
-        if not fslimage.looksLikeImage(path):
-            return None
-
-        # create an independent in-memory
-        # copy of the image file
-        img  = nib.load(path, mmap=False)
-        data = np.asanyarray(img.dataobj)
-
-        # if any arguments were fsl images,
-        # that takes precedence.
-        if fslimage.Image in intypes:
-            return fslimage.Image(data, header=img.header, name=name)
-
-        # but if all inputs were file names,
-        # nibabel takes precedence
-        elif nib.nifti1.Nifti1Image in intypes or len(intypes) == 0:
-            return nib.nifti1.Nifti1Image(data, None, img.header)
-
-        # this function should not be called
-        # under any other circumstances
-        else:
-            raise RuntimeError('Cannot handle type: {}'.format(intypes))
-
-    def decorator(func):
-        fot = FileOrThing(func,
-                          prepIn,
-                          prepOut,
-                          load,
-                          fslimage.removeExt,
-                          *args,
-                          **kwargs)
-
-        def wrapper(*args, **kwargs):
-            result = fot(*args, **kwargs)
-            intypes[:] = []
-            return result
-
-        return _update_wrapper(wrapper, func)
-
-    return decorator
-
-
-def fileOrArray(*args, **kwargs):
-    """Decorator which can be used to ensure that any Numpy arrays are saved
-    to text files, and output files can be loaded and returned as Numpy arrays.
-    """
-
-    def prepIn(workdir, name, val):
-
-        infile = None
-
-        if isinstance(val, np.ndarray):
-            hd, infile = tempfile.mkstemp('.txt', dir=workdir)
-            os.close(hd)
-            np.savetxt(infile, val, fmt='%0.18f')
-
-        return infile
-
-    def prepOut(workdir, name, val):
-        return op.join(workdir, '{}.txt'.format(name))
-
-    def load(_, path):
-        try:              return np.loadtxt(path)
-        except Exception: return None
-
-    def decorator(func):
-        fot = FileOrThing(func,
-                          prepIn,
-                          prepOut,
-                          load,
-                          fslpath.removeExt,
-                          *args,
-                          **kwargs)
-
-        def wrapper(*args, **kwargs):
-            return fot(*args, **kwargs)
-
-        return _update_wrapper(wrapper, func)
-
-    return decorator
-
-
-def fileOrText(*args, **kwargs):
-    """Decorator which can be used to ensure that any text output (e.g. log
-    file) are saved to text files, and output files can be loaded and returned
-    as strings.
-
-    To be able to distinguish between input values and input file paths, the
-    ``fileOrText`` decorator requires that input and output file paths are
-    passed in as ``pathlib.Path`` objects. For example, given a function
-    like this::
-
-        @fileOrText()
-        def myfunc(infile, outfile):
-            ...
-
-    if we want to pass file paths for both ``infile`` and ``outfile``, we would
-    do this::
-
-        from pathlib import Path
-        myfunc(Path('input.txt'), Path('output.txt'))
-
-    Input values may be passed in as normal strings, e.g.::
-
-        myfunc('input data', Path('output.txt'))
-
-    Output values can be loaded as normal via the :attr:`LOAD` symbol, e.g.::
-
-        myfunc(Path('input.txt'), LOAD)
-    """
-
-    def prepIn(workdir, name, val):
-
-        infile = None
-
-        if not isinstance(val, pathlib.Path):
-            with tempfile.NamedTemporaryFile(mode='w',
-                                             suffix='.txt',
-                                             dir=workdir,
-                                             delete=False) as f:
-                f.write(val)
-                infile = f.name
-        return infile
-
-    def prepOut(workdir, name, val):
-        return op.join(workdir, '{}.txt'.format(name))
-
-    def load(_, path):
-        try:
-            with open(path, "r") as f:
-                return f.read()
-        except Exception: return None
-
-    def decorator(func):
-        fot = FileOrThing(func,
-                          prepIn,
-                          prepOut,
-                          load,
-                          fslpath.removeExt,
-                          *args,
-                          **kwargs)
-
-        def wrapper(*args, **kwargs):
-            return fot(*args, **kwargs)
-
-        return _update_wrapper(wrapper, func)
-
-    return decorator
diff --git a/bip/ext_wrappers/freesurfer.py b/bip/ext_wrappers/freesurfer.py
index 6aa8dabc351c67bd315b0bca24f85409e53f4927..ad636b2cd87a0ab63ba8b647bb56dd8b52c4df03 100644
--- a/bip/ext_wrappers/freesurfer.py
+++ b/bip/ext_wrappers/freesurfer.py
@@ -8,24 +8,49 @@
 
 """
 
-
+import os
 import fsl.utils.assertions as asrt
-from fsl.utils.deprecated import deprecated
-from . import wrapperutils  as wutils
+from fsl.wrappers import wrapperutils as wutils
+
+
+import sys
+
+def eprint(*args, **kwargs):
+    print(*args, file=sys.stderr, **kwargs)
 
 
+@wutils.fileOrImage('infile')
 @wutils.cmdwrapper
-def recon_all(subjid, directive, **kwargs):
-    """Wrapper for the ``xfibres_gpu`` command.
+def recon_all(subjects_dir, directive, subjid, infile, FLAIR=None, **kwargs):
+    """Wrapper for the ``recon-all`` command.
+    """
+    #asrt.assertIsNifti(*infile)
 
-"""
+    os.environ["SUBJECTS_DIR"] = subjects_dir
+
+    cmd = ['recon-all', "-"+directive + " -s " + subjid ]
+    cmd += [ " -i " + subjects_dir + "/" + infile ]
 
-    valmap = {
-        'FLAIRpial' : wutils.SHOW_IF_TRUE,
-    }
+    if FLAIR:
+        cmd += [ " -FLAIR " + subjects_dir + "/" + FLAIR + " -FLAIRpial" ]
 
-    cmd = ['recon-all', "-"+directive] 
+    return cmd
+
+@wutils.cmdwrapper
+def asegstats2table(subjects_dir, mask, tablefile, subjects, **kwargs):
+    """Wrapper for the ``asegstats2table`` command.
+    """
+    os.environ["SUBJECTS_DIR"] = subjects_dir
+    cmd = ['asegstats2table']
+
+    return cmd
+
+@wutils.cmdwrapper
+def aparcstats2table(subjects_dir, mask, tablefile, subjects, hemi, atlas,
+                     **kwargs):
+    """Wrapper for the ``aparcstats2table`` command.
+    """
+    os.environ["SUBJECTS_DIR"] = subjects_dir
+    cmd = ['aparcstats2table']
 
-    cmd += wutils.applyArgStyle('-', valmap=valmap, **kwargs)
- 
     return cmd
diff --git a/bip/main.py b/bip/main.py
index 70da130271060b3819c3761bfea9e2eea503d10c..cea402ea829a8b32883beb60aad4bc46582de0c1 100755
--- a/bip/main.py
+++ b/bip/main.py
@@ -19,6 +19,7 @@ import bip
 from bip.utils import setup_logging
 from bip.pipelines.struct_T1       import struct_T1
 from bip.pipelines.struct_T2_FLAIR import struct_T2_FLAIR
+from bip.pipelines.struct_FS       import struct_FS
 from bip.pipelines.struct_swMRI    import struct_swMRI
 from bip.pipelines.struct_asl      import struct_asl
 from bip.pipelines.dMRI_fieldmap   import dMRI_fieldmap
@@ -335,6 +336,7 @@ def main():
 
     pipe, targets = struct_T1.add_to_pipeline(ctx, pipe, tree, targets)
     pipe, targets = struct_T2_FLAIR.add_to_pipeline(ctx, pipe, tree, targets)
+    pipe, targets = struct_FS.add_to_pipeline(ctx, pipe, tree, targets)
     pipe, targets = struct_swMRI.add_to_pipeline(ctx, pipe, tree, targets)
     pipe, targets = struct_asl.add_to_pipeline(ctx, pipe, tree, targets)
     pipe, targets = dMRI_fieldmap.add_to_pipeline(ctx, pipe, tree, targets)
diff --git a/bip/pipelines/struct_FS/FS_get_IDPs.py b/bip/pipelines/struct_FS/FS_get_IDPs.py
new file mode 100755
index 0000000000000000000000000000000000000000..4d19117d079591231a7f9e948007fb80737f9920
--- /dev/null
+++ b/bip/pipelines/struct_FS/FS_get_IDPs.py
@@ -0,0 +1,72 @@
+#!/usr/bin/env python
+#
+# asl_get_IDPs.py - Sub-pipeline generating the IDPs of the ASL pipeline.
+#
+# Author: Fidel Alfaro Almagro <fidel.alfaroalmagro@ndcn.ox.ac.uk>
+# Author: Paul McCarthy <pauldmccarthy@gmail.com>
+# Author: Michiel Cottaar <michiel.cottaar@ndcn.ox.ac.uk>
+#
+# pylint: disable=C0103,E0602,C0114,C0115,C0116,R0913,R0914,R0915
+# pylint: disable=W0613,R1718
+#
+
+import logging
+from pipe_tree import In, Out, Ref
+from bip.utils import redirect_logging
+
+log = logging.getLogger(__name__)
+
+def run(ctx,
+        region_analysis_gm_csv:  In,
+        logs_dir:                Ref,
+        ASL_region_analysis_dir: Ref,
+        ASL_IDPs:                Out):
+
+    with redirect_logging('asl_get_IDPs', outdir=logs_dir):
+
+        result = ctx.subject
+
+        asl_format_file = ctx.get_data("asl/asl_format.txt")
+
+        with open(asl_format_file, 'rt', encoding="utf-8") as f:
+            asl_format = [x.strip().split() for x in f.readlines()]
+
+        regions = set([x[0] for x in asl_format])
+
+        for region in regions:
+            file_name_1 = ASL_region_analysis_dir + "/" + region + ".csv"
+            file_name_2 = ASL_region_analysis_dir + "/" + region + ".txt"
+
+            with open(file_name_1, 'rt', encoding="utf-8") as f:
+                file_data = f.read()
+
+            file_data = file_data.replace(", ", "_-_")
+            file_data = file_data.replace('"', "")
+            file_data = file_data.replace(" ", "_")
+
+            with open(file_name_2, 'wt', encoding="utf-8") as f:
+                f.write(file_data)
+
+
+        for elem in asl_format:
+
+            fil    = elem[0]
+            row    = elem[1]
+            column = elem[2]
+
+            file_name = ASL_region_analysis_dir + "/" + fil + ".txt"
+
+            with open(file_name, 'rt', encoding="utf-8") as f:
+                file_data = [x.strip().split(",") for x in f.readlines()]
+
+            for line in file_data:
+                if line[0] == row:
+                    val = line[int(column)]
+            if val == "":
+                val = "NaN"
+
+            result += " " + val
+
+        with open(ASL_IDPs, 'wt', encoding="utf-8") as f:
+            f.write(result + "\n")
+           
\ No newline at end of file
diff --git a/bip/pipelines/struct_FS/FS_proc.py b/bip/pipelines/struct_FS/FS_proc.py
new file mode 100755
index 0000000000000000000000000000000000000000..9c048d1501167371610ccc87c4117e4276ce8f07
--- /dev/null
+++ b/bip/pipelines/struct_FS/FS_proc.py
@@ -0,0 +1,36 @@
+#!/usr/bin/env python
+#
+# FS_proc.py - Sub-pipeline with the FreeSurfer main processing.
+#
+# Author: Fidel Alfaro Almagro <fidel.alfaroalmagro@ndcn.ox.ac.uk>
+# Author: Paul McCarthy <pauldmccarthy@gmail.com>
+# Author: Michiel Cottaar <michiel.cottaar@ndcn.ox.ac.uk>
+#
+# pylint: disable=C0103,E0602,C0114,C0115,C0116,R0913,R0914,R0915
+# pylint: disable=W0613
+#
+
+import os
+import logging
+from pipe_tree import In, Out, Ref
+from bip import ext_wrappers
+from bip.utils import redirect_logging
+
+log = logging.getLogger(__name__)
+
+def run(ctx,
+        T1_unbiased:                In,
+        T2_FLAIR_unbiased:          In(optional=True),
+        logs_dir:                   Ref,
+        rh_entorhinal_exvivo_label: Out):
+
+    with redirect_logging('FS_proc', outdir=logs_dir):
+        opt_T2_FLAIR = None
+
+        if os.path.exists(T2_FLAIR_unbiased):
+            opt_T2_FLAIR = T2_FLAIR_unbiased
+
+        ext_wrappers.recon_all(subjects_dir=os.getcwd(), directive="all",
+                               subjid="FreeSurfer", infile=T1_unbiased,
+                               FLAIR=opt_T2_FLAIR)
+        print("PATATA")
diff --git a/bip/pipelines/struct_FS/FS_segm.py b/bip/pipelines/struct_FS/FS_segm.py
new file mode 100755
index 0000000000000000000000000000000000000000..94d33618fab0b249e4b8b9cf77a761f06afaea90
--- /dev/null
+++ b/bip/pipelines/struct_FS/FS_segm.py
@@ -0,0 +1,167 @@
+#!/usr/bin/env python
+#
+# asl_proc.py - Sub-pipeline with the ASL main processing.
+#
+# Author: Fidel Alfaro Almagro <fidel.alfaroalmagro@ndcn.ox.ac.uk>
+# Author: Paul McCarthy <pauldmccarthy@gmail.com>
+# Author: Michiel Cottaar <michiel.cottaar@ndcn.ox.ac.uk>
+#
+# pylint: disable=C0103,E0602,C0114,C0115,C0116,R0913,R0914,R0915
+# pylint: disable=W0613
+#
+
+import os
+import glob
+import logging
+from shutil import copyfile
+from fsl import wrappers
+from pipe_tree import In, Out, Ref
+from gradunwarp.core.gradient_unwarp_apply import gradient_unwarp_apply
+from bip.utils import redirect_logging
+from bip.commands.bb_read_json_field import bb_read_json_field
+
+log = logging.getLogger(__name__)
+
+def run(ctx,
+        T1:                            In,
+        T1_brain:                      In,
+        T1_to_MNI_warp:                In,
+        fieldmap_fout_to_T1_brain_rad: In,
+        ASL_M0:                        In,
+        ASL_M0_json:                   In,
+        logs_dir:                      Ref,
+        ASL_GDC:                       Ref,
+        OXASL_ra_dir:                  Ref,
+        T1_fast_prefix:                Ref,
+        ASL_PLD_prefix:                Ref,
+        ASL_raw_dir:                   Ref,
+        ASL_M0_ud:                     Out,
+        ASL_M0_ud_warp:                Out,
+        ASL_DATA_wrongorder:           Out,
+        ASL_DATA:                      Out,
+        ASL_DATA_diff:                 Out,
+        ASL_DATA_diff_mean:            Out,
+        ASL_control:                   Out,
+        ASL_label:                     Out,
+        CALIB:                         Out,
+        CALIB_json:                    Out,
+        ASL_qc_modelfit:               Out,
+        ASL_mni_right_amygdala:        Out,
+        ASL_masks_right_amygdala:      Out,
+        ASL_native_right_amygdala:     Out,
+        ASL_struct_90_wm:              Out,
+        ASL_calib_M0:                  Out,
+        ASL_struct_ACBV_calib:         Out,
+        ASL_std_ACBV_calib:            Out,
+        region_analysis_gm_csv:        Out):
+
+    with redirect_logging('asl_proc', outdir=logs_dir):
+
+        BBASL_ROI_DIR = ctx.get_data("asl/ukb_rois/")
+
+        ###############################################
+        # Initial check for Phase Encoding Directions #
+        ###############################################
+        list_PEDs = []
+
+        for fil in glob.glob(ASL_raw_dir + "/*.json"):
+            list_PEDs.append(bb_read_json_field(fileName=fil,
+                                fieldName="PhaseEncodingDirection"))
+
+        if len(list_PEDs) != 12:
+            error_msg =  "ERROR: Wrong phase-encoding-direction in some of the "
+            error_msg += "files (or wrong number of files). "
+            error_msg += "ASL will not be processed."
+            print(error_msg)
+            # TODO: Make unusable this modality
+            # bb_make_unusable ASL $src "2 Wrong_acquisition"
+
+        ##################
+        # Pre-processing #
+        ##################
+        list_fils_control = glob.glob(ASL_PLD_prefix + "*_control.nii.gz")
+        list_fils_control.sort()
+        list_fils_label = glob.glob(ASL_PLD_prefix + "*_label.nii.gz")
+        list_fils_label.sort()
+
+        wrappers.fslmerge("t", ASL_control, *list_fils_control)
+        wrappers.fslmerge("t", ASL_label, *list_fils_label)
+        wrappers.fslmerge("t", ASL_DATA_wrongorder, ASL_label, ASL_control)
+
+        os.symlink("../raw/ASL_M0.nii.gz", CALIB)
+        os.symlink("../raw/ASL_M0.json",   CALIB_json)
+
+        TE = bb_read_json_field(fileName=CALIB_json, fieldName="EchoTime",
+                                rounding = 3, multFactor=1000)
+
+        #Gradient distortion correction applied to the M0
+        if ctx.gdc != '':
+            #Calculate and apply the Gradient Distortion Unwarp
+            # TODO: Review the "half=True" in next version
+            gradient_unwarp_apply(WD=ASL_GDC, infile=CALIB, outfile=ASL_M0_ud,
+                                  owarp=ASL_M0_ud_warp,gradcoeff=ctx.gdc,
+                                  vendor='siemens', nojac=True, half=False)
+        else:
+            copyfile(src=CALIB, dst=ASL_M0_ud)
+
+
+        ##############
+        # Processing #
+        ##############
+        # Use asl_file to get into alternating tag-control
+        wrappers.asl_file(data=ASL_DATA_wrongorder, out=ASL_DATA, ntis=5,
+                          iaf="tcb")
+
+        # PWI generation - this is more of a sanity check than anything else
+        # now use ASL file to get difference images
+        wrappers.asl_file(data=ASL_DATA, out=ASL_DATA_diff,
+                          mean=ASL_DATA_diff_mean, ntis=5, iaf="tc", diff=True)
+
+
+        #######################
+        # PERFUSION ANALSYSIS #
+        #######################
+
+        raa_list = [BBASL_ROI_DIR + "MNI_seg_max_prob_masked_RandL.nii.gz",
+                    BBASL_ROI_DIR + "HO_L_Cerebral_WM_thr80.nii.gz",
+                    BBASL_ROI_DIR + "HO_R_Cerebral_WM_thr80.nii.gz",
+                    BBASL_ROI_DIR + "VascularTerritories_ero.nii.gz"]
+        raa_labels_list = [BBASL_ROI_DIR + "MNI_seg_max_prob_masked_RandL.txt",
+                           BBASL_ROI_DIR + "HO_L_Cerebral_WM_thr80.txt",
+                           BBASL_ROI_DIR + "HO_R_Cerebral_WM_thr80.txt",
+                           BBASL_ROI_DIR + "VascularTerritories_ero.txt"]
+
+        wrappers.oxford_asl(data=ASL_DATA,
+                            out=OXASL_ra_dir,
+                            c=CALIB,
+                            s=T1,
+                            regfrom_method="pwi",
+                            reg_init_bbr=True,
+                            sbrain=T1_brain,
+                            fastsrc=T1_fast_prefix,
+                            warp=T1_to_MNI_warp,
+                            fmap=fieldmap_fout_to_T1_brain_rad,
+                            fmapmag=T1,
+                            fmapmagbrain=T1_brain,
+                            gdcwarp=ASL_M0_ud_warp,
+                            iaf="tc",
+                            ibf="rpt",
+                            mc="on",
+                            tis=[2.2, 2.6, 3.0, 3.4, 3.8],
+                            casl=True,
+                            bolus=1.8,
+                            fixbolus=True,
+                            cgain=10,
+                            spatial=True,
+                            tr=5,
+                            te=TE,
+                            echospacing=0.0005,
+                            pedir="x",
+                            gm_thresh=0.7,
+                            cmethod="voxel",
+                            nofmapreg=True,
+                            region_analysis=True,
+                            region_analysis_atlas= raa_list,
+                            region_analysis_atlas_labels= raa_labels_list,
+                            region_analysis_save_rois=True,
+                            qc_output=True)
diff --git a/bip/pipelines/struct_FS/struct_FS.py b/bip/pipelines/struct_FS/struct_FS.py
new file mode 100755
index 0000000000000000000000000000000000000000..a3df06c3aa1b0474f41d43f77fc83bda1b4ad101
--- /dev/null
+++ b/bip/pipelines/struct_FS/struct_FS.py
@@ -0,0 +1,30 @@
+#!/usr/bin/env python
+#
+# struct_FS.py - Pipeline with the FreeSurfer processing.
+#
+# Author: Fidel Alfaro Almagro <fidel.alfaroalmagro@ndcn.ox.ac.uk>
+# Author: Paul McCarthy <pauldmccarthy@gmail.com>
+# Author: Michiel Cottaar <michiel.cottaar@ndcn.ox.ac.uk>
+#
+# pylint: disable=C0103,E0602,C0114,C0115,C0116,R0913,R0914,R0915
+#
+
+import logging
+from bip.utils import redirect_logging
+from bip.pipelines.struct_FS import FS_proc#, FS_segm, FS_get_IDPs
+
+log = logging.getLogger(__name__)
+
+def add_to_pipeline(ctx, pipe, tree, targets):
+
+    logs_dir=tree.get('logs_dir')
+
+    with redirect_logging('pipe_struct_FS', outdir=logs_dir):
+        pipe(FS_proc.run, submit=dict(jobtime=200), kwargs={'ctx' : ctx})
+        targets.append('rh_entorhinal_exvivo_label')
+        #pipe(FS_segm.run, submit=dict(jobtime=200), kwargs={'ctx' : ctx})
+        #targets.append('ASL_IDPs')
+        #pipe(FS_get_IDPs.run, submit=dict(jobtime=200), kwargs={'ctx' : ctx})
+        #targets.append('FS_IDPs')
+
+    return pipe, targets
diff --git a/bip/pipelines/struct_asl/struct_asl.py b/bip/pipelines/struct_asl/struct_asl.py
index 2f172e02aa3792ea1891c77a3e44c193430e637d..2a591ae528fab9f2bda6736293689759828f3c5f 100755
--- a/bip/pipelines/struct_asl/struct_asl.py
+++ b/bip/pipelines/struct_asl/struct_asl.py
@@ -11,8 +11,7 @@
 
 import logging
 from bip.utils import redirect_logging
-from bip.pipelines.struct_asl import asl_proc
-from bip.pipelines.struct_asl import asl_get_IDPs
+from bip.pipelines.struct_asl import asl_proc, asl_get_IDPs
 
 log = logging.getLogger(__name__)
 
diff --git a/init_vars b/init_vars
index 28f0319f2dea21c09b4a9975d0f54163b6f92558..c06cda20c79b92f4f04935787d4cd041f7625a81 100755
--- a/init_vars
+++ b/init_vars
@@ -1,18 +1,35 @@
 #!/bin/bash
 
+# For the pipeline. Requires the existence of a SWdir with:
+#  - The pipeline
+#  - fsl
+#  - freesurfer 
 export BB_BIN_DIR="$SWdir/bip"
 export FSLDIR="$SWdir/fsl"
 
+# For FSL
 source $FSLDIR/etc/fslconf/fsl.sh
-source $FSLDIR/bin/activate ukb
 
 export FSLOUTPUTTYPE="NIFTI_GZ"
 export FSLSUB_CONF="$SWdir/bip/fsl_sub.yml"
 
+# For FreeSurfer
+unset FSFAST_HOME
+unset MNI_DIR
+unset FSL_DIR
+export FREESURFER_HOME="$SWdir/freesurfer_7.3.2"
+export MNI_DIR="${FREESURFER_HOME}/mni"
+source $FREESURFER_HOME/SetUpFreeSurfer.sh
+
+# Activate the environment
+source $FSLDIR/bin/activate ukb
+
+# Unsetting some problematic variables
 unset PYTHONPATH
 unset LC_ALL
 unset LC_CTYPE
 
+# Creating a useful alias
 alias runbip="$BB_BIN_DIR/bip/main.py"
 PS1="(ukb) \! "`whoami`@`hostname|cut -d. -f1`@$(basename $(tty))" | \t | \w $ " ; 
 export PS1
\ No newline at end of file