diff --git a/fsl/data/atlases.py b/fsl/data/atlases.py
index 9fe33df9e2ce2b9a5a77fb1630dc5f6819ee778c..2bfc7ea257ada8ba01e87175781ed0740f388fa0 100644
--- a/fsl/data/atlases.py
+++ b/fsl/data/atlases.py
@@ -88,6 +88,7 @@ import xml.etree.ElementTree as et
 import os.path               as op
 import                          glob
 import                          collections
+import                          threading
 import                          logging
 
 import numpy                 as np
@@ -109,28 +110,49 @@ def listAtlases(refresh=False):
                   loaded from the atlas files. Otherwise, previously
                   loaded descriptions are returned (see 
                   :attr:`ATLAS_DESCRIPTIONS`).
+
+    .. note:: This function is thread-safe, because *FSLeyes* calls it
+              in a multi-threaded manner (to avoid blocking the GUI).
     """
 
     _setAtlasDir()
 
     if ATLAS_DIR is None:
         return []
+    
+    # Make sure the atlas description
+    # refresh is only performed by one
+    # thread. If a thread is loading
+    # the descriptions, any other thread
+    # which enters the function will
+    # block here until the descriptions
+    # are loaded. When it continues,
+    # it will see a populated
+    # ATLAS_DESCRIPTIONS list.
+    LOAD_ATLAS_LOCK.acquire()
 
     if len(ATLAS_DESCRIPTIONS) == 0:
         refresh = True
 
-    if not refresh:
-        return list(ATLAS_DESCRIPTIONS.values())
+    try:
+        if refresh:
+
+            log.debug('Loading atlas descriptions')
+            
+            atlasFiles = glob.glob(op.join(ATLAS_DIR, '*.xml'))
+            atlasDescs = map(AtlasDescription, atlasFiles)
+            atlasDescs = sorted(atlasDescs, key=lambda d: d.name)
 
-    atlasFiles = glob.glob(op.join(ATLAS_DIR, '*.xml'))
-    atlasDescs = map(AtlasDescription, atlasFiles)
-    atlasDescs = sorted(atlasDescs, key=lambda d: d.name)
+            ATLAS_DESCRIPTIONS.clear()
 
-    ATLAS_DESCRIPTIONS.clear()
+            for i, desc in enumerate(atlasDescs):
+                desc.index                       = i
+                ATLAS_DESCRIPTIONS[desc.atlasID] = desc
+        else:
+            atlasDescs = list(ATLAS_DESCRIPTIONS.values())
 
-    for i, desc in enumerate(atlasDescs):
-        desc.index                       = i
-        ATLAS_DESCRIPTIONS[desc.atlasID] = desc
+    finally:
+        LOAD_ATLAS_LOCK.release()
 
     return list(atlasDescs)
 
@@ -189,12 +211,24 @@ class AtlasDescription(object):
 
     ================= ======================================================
     ``atlasID``       The atlas ID, as described above.
+    
     ``name``          Name of the atlas.
+    
     ``atlasType``     Atlas type - either *probabilistic* or *label*.
+    
     ``images``        A list of images available for this atlas - usually
                       :math:`1mm^3` and :math:`2mm^3` images are present.
+    
     ``summaryImages`` For probabilistic atlases, a list of *summary* images,
                       which are just 3D labelled variants of the atlas.
+    
+    ``pixdims``       A list of ``(x, y, z)`` pixdim tuples in mm, one for
+                      each image in ``images``.
+
+    ``xforms``        A list of affine transformation matrices (as ``4*4``
+                      ``numpy`` arrays), one for each image in ``images``,
+                      defining the voxel to world coordinate transformations.
+    
     ``labels``        A list of ``AtlasLabel`` objects, describing each
                       region / label in the atlas.
     ================= ======================================================
@@ -216,8 +250,9 @@ class AtlasDescription(object):
 
     .. note:: The ``x``, ``y`` and ``z`` label coordinates are pre-calculated
               centre-of-gravity coordinates, as listed in the atlas xml file.
-              They are in the coordinate system defined by the atlas image
-              transformation matrix (typically MNI152 space).
+              They are in the coordinate system defined by the transformation
+              matrix for the first image in the ``images`` list.(typically
+              MNI152 space).
     """
 
     
@@ -244,6 +279,9 @@ class AtlasDescription(object):
         images             = header.findall('images')
         self.images        = []
         self.summaryImages = []
+        self.pixdims       = []
+        self.xforms        = []
+        
 
         for image in images:
             imagefile        = image.find('imagefile')       .text
@@ -252,8 +290,12 @@ class AtlasDescription(object):
             imagefile        = op.join(ATLAS_DIR, '.' + imagefile)
             summaryimagefile = op.join(ATLAS_DIR, '.' + summaryimagefile)
 
+            i = fslimage.Image(imagefile, loadData=False)
+
             self.images       .append(imagefile)
             self.summaryImages.append(summaryimagefile)
+            self.pixdims      .append(i.pixdim[:3])
+            self.xforms       .append(i.voxToWorldMat)
 
         # A container object used for
         # storing atlas label information
@@ -286,8 +328,7 @@ class AtlasDescription(object):
         # Load the appropriate transformation matrix
         # and transform all those voxel coordinates
         # into world coordinates
-        xform  = fslimage.Image(self.images[0], loadData=False).voxToWorldMat
-        coords = transform.transform(coords, xform.T)
+        coords = transform.transform(coords, self.xforms[0].T)
 
         # Update the coordinates 
         # in our label objects
@@ -433,6 +474,12 @@ all atlases contained in ``$FSLDIR/data/atlases/``.
 """
 
 
+LOAD_ATLAS_LOCK = threading.Lock()
+"""This is used as a mutual-exclusion lock by the :func:`listAtlases`
+function, to make it thread-safe.
+"""
+
+
 def _setAtlasDir():
     """Called by the :func:`listAtlases`, :func:`getAtlasDescription` and
     :func:`loadAtlas` functions.