Package mvpa :: Package atlases :: Module transformation

[hide private]
[frames] | no frames]

# Source Code for Module mvpa.atlases.transformation

      1  # emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*-
      2  # vi: set ft=python sts=4 ts=4 sw=4 et:
      3  ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##
      4  #
      5  #   See COPYING file distributed along with the PyMVPA package for the
      6  #   copyright and license terms.
      7  #
      8  ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##
      9  """Coordinate transformations"""
     10
     11  import numpy as N
     12
     13  if __debug__:
     14      from mvpa.base import debug
     15
     16 -class TypeProxy:
     17      """
     18      Simple class to convert from and then back to original type
     19      working with list, tuple, ndarray and having
     20
     21      XXX Obsolete functionality ??
     22      """
     23 -    def __init__(self, value, toType=N.array):
     24          if   isinstance(value, list): self.__type = list
     25          elif isinstance(value, tuple): self.__type = tuple
     26          elif isinstance(value, N.ndarray): self.__type = N.array
     27          else:
     28              raise IndexError("Not understood format of coordinates '%s' for the transformation" % `coord`)
     29
     30 -    def __call__(self, value):    return self.__type(value)
     31  #   def __getitem__(self, value): return self.__type(value)
     32
     33
     34 -class TransformationBase:
     35      """
     36      Basic class to describe a transformation. Pretty much an interface
     37      """
     38
     39 -    def __init__(self, previous=None):
     40          self.previous = previous
     41
     42 -    def __getitem__(self, icoord):
     43          """
     44          Obtain coordinates, apply the transformation and spit out in the same
     45          format (list, tuple, numpy.array)
     46          """
     47
     48          # remember original type
     49          #speed origType = TypeProxy(coord)
     50
     51          # just in case it is not an ndarray, and to provide a copy to manipulate with
     52          coord = N.array(icoord)
     53
     54          # apply previous transformation if such defined
     55          if self.previous:
     56              # if __debug__: debug('ATL__', "Applying previous transformation on `%s`" % `coord`)
     57              coord = self.previous[coord]
     58
     59          #speed if __debug__: debug('ATL__', "Applying main transformation on `%s`" % `coord`)
     60          # apply transformation
     61          coord_out = self.apply(coord)
     62          #speed if __debug__: debug('ATL__', "Applied and got `%s`" % `coord_out`)
     63
     64          #speed return origType(coord_out)
     65          return coord_out
     66
     67 -    def __call__(self, coord):
     68          return self[coord]
     69
     70 -    def apply(self, coord):
     71          return coord
     72
     73
     74 -class SpaceTransformation(TransformationBase):
     75      """
     76      To perform transformation from Voxel into Real Space.
     77      Simple one -- would subtract the origin and multiply by voxelSize.
     78      if toRealSpace is True then on call/getitem converts to RealSpace
     79      """
     80 -    def __init__(self, voxelSize=None, origin=None, toRealSpace=True,
     81                   *args, **kwargs):
     82
     83          TransformationBase.__init__(self, *args, **kwargs)
     84
     85          if not voxelSize is None: self.voxelSize = N.asarray(voxelSize)
     86          else: self.voxelSize = 1
     87
     88          if not origin is None: self.origin = N.asarray(origin)
     89          else: self.origin = 0
     90
     91          if toRealSpace:
     92              self.apply = self.toRealSpace
     93          else:
     94              self.apply = self.toVoxelSpace
     95
     96 -    def toRealSpace(self, coord):
     97          #speed if not self.origin is None:
     98          coord -= self.origin
     99          #speed if not self.voxelSize is None:
    100          coord *= self.voxelSize
    101          return coord
    102
    103 -    def toVoxelSpace(self, coord):
    104          #speed if not self.voxelSize is None:
    105          coord /= self.voxelSize
    106          #speed if not self.origin is None:
    107          coord += self.origin
    108          return map(lambda x:int(round(x)), coord)
    109
    110
    111 -class Linear(TransformationBase):
    112      """
    113      Simple linear transformation defined by a matrix
    114      """
    115 -    def __init__(self, transf=N.eye(4), **kwargs):
    116          transf = N.asarray(transf)  # assure that we have arrays not matrices
    117          prev = kwargs.get('previous', None)
    118          if prev is not None and isinstance(prev, Linear):
    119              if prev.N == transf.shape[0] -1:
    120                  if __debug__: debug('ATL__', "Colliding 2 linear transformations into 1")
    121                  transf = N.dot(transf, prev.M)
    122                  # reassign previous transformation to the current one
    123                  kwargs['previous'] = prev.previous
    124          TransformationBase.__init__(self, **kwargs)
    125          self.M = transf
    126          self.N = self.M.shape[0] - 1
    127
    128 -    def apply(self, coord):
    129          #speed if len(coord) != self.__N:
    130          #speed  raise ValueError("Transformation operates on %dD coordinates" \
    131          #speed                   % self.__N )
    132          #speed if __debug__: debug('ATL__', "Applying linear coord transformation + %s" % self.__M)
    133          # Might better come up with a linear transformation
    134          coord_ = N.r_[coord, [1.0]]
    135          result = N.dot(self.M, coord_)
    136          return result[0:-1]
    137
    138
    139 -class MNI2Tal_MatthewBrett(TransformationBase):
    140      """
    141      Transformation to bring MNI coordinates into MNI space
    142
    143      Apparently it is due to Matthew Brett
    144      http://imaging.mrc-cbu.cam.ac.uk/imaging/MniTalairach
    145      """
    146
    147 -    def __init__(self, *args, **kwargs):
    148          TransformationBase.__init__(self, *args, **kwargs)
    149          self.__upper = Linear( N.array([ [0.9900, 0, 0, 0 ],
    150                                            [0, 0.9688, 0.0460, 0 ],
    151                                            [0,-0.0485, 0.9189, 0 ],
    152                                            [0, 0, 0, 1.0000] ] ) )
    153
    154          self.__lower = Linear(N.array( [ [0.9900, 0, 0, 0 ],
    155                                            [0, 0.9688, 0.0420, 0 ],
    156                                            [0,-0.0485, 0.8390, 0 ],
    157                                            [0, 0, 0, 1.0000] ] ) )
    158
    159 -    def apply(self, coord):
    160          return {True: self.__upper,
    161                  False: self.__lower}[coord[2]>=0][coord]
    162
    163
    164 -def MNI2Tal_MeyerLindenberg98 (*args, **kwargs):
    165      """
    166      Due to Andreas Meyer-Lindenberg
    167      Taken from
    168      http://imaging.mrc-cbu.cam.ac.uk/imaging/MniTalairach
    169      """
    170
    171      return Linear( N.array([
    172          [    0.88,   0,  0,  -0.8],
    173          [    0,   0.97,  0,  -3.32],
    174          [    0,   0.05,  0.88,   -0.44],
    175          [    0.00000,   0.00000,   0.00000,   1.00000] ]), *args, **kwargs )
    176
    177
    178 -def MNI2Tal_YOHflirt (*args, **kwargs):
    179      """Transformations obtained using flirt from Talairach to Standard
    180
    181      Transformations were obtained by registration of
    182      grey/white matter image from talairach atlas to FSL's standard
    183      volume. Following sequence of commands was used:
    184
    185      fslroi /usr/share/rumba/atlases/data/talairach_atlas.nii.gz talairach_graywhite.nii.gz 3 1
    186      flirt -in talairach_graywhite.nii.gz \
    187       -ref /usr/apps/fsl.4.1/data/standard/MNI152_T1_1mm_brain.nii.gz \
    188       -out talairach2mni.nii.gz -omat talairach2mni.mat \
    189       -searchrx -20 20 -searchry -20 20 -searchrz -20 20 -coarsesearch 10 -finesearch 6 -v
    190      flirt -datatype float -in talairach_graywhite.nii.gz -init talairach2mni.mat \
    191       -ref /usr/apps/fsl.4.1/data/standard/MNI152_T1_1mm_brain.nii.gz \
    192       -out talairach2mni_fine1.nii.gz -omat talairach2mni_fine1.mat \
    193       -searchrx -10 10 -searchry -10 10 -searchrz -10 10 -coarsesearch 5 -finesearch 1 -v
    194      convert_xfm -inverse -omat mni2talairach.mat talairach2mni_fine1.mat
    195      """
    196      return Linear(
    197          t=N.array([
    198          [ 1.00448,  -0.00629625,  0.00741359,  0.70565,  ],
    199          [ 0.0130797,  0.978238,  0.0731315,  -3.8354,  ],
    200          [ 0.000248407,  -0.0374777,  0.838311,  18.6202,  ],
    201          [ 0,  0,  0,  1,  ],
    202          ])
    203                     , *args, **kwargs )
    204
    205
    206 -def Tal2MNI_YOHflirt (*args, **kwargs):
    207      """See MNI2Tal_YOHflirt doc
    208      """
    209      return Linear( N.array([
    210          [    1.00452,    0.00441281,  -0.011011,  -0.943886],
    211          [   -0.0141149,  1.00867,     -0.169177,  14.7016],
    212          [    0.00250222, 0.0920984,    1.18656,  -33.922],
    213          [    0.00000,   0.00000,   0.00000,   1.00000] ]), *args, **kwargs )
    214
    215
    216
    217 -def MNI2Tal_Lancaster07FSL (*args, **kwargs):
    218      return Linear( N.array([
    219          [  0.9464, 0.0034, -0.0026, -1.0680],
    220          [ -0.0083, 0.9479, -0.0580, -1.0239],
    221          [  0.0053, 0.0617,  0.9010,  3.1883],
    222          [  0.0000, 0.0000,  0.0000,  1.0000] ]), *args, **kwargs )
    223
    224
    225 -def Tal2MNI_Lancaster07FSL (*args, **kwargs):
    226      return Linear( N.array([
    227          [ 1.056585, -0.003972,  0.002793,  1.115461],
    228          [ 0.008834,  1.050528,  0.067651,  0.869379],
    229          [-0.00682 , -0.071916,  1.105229, -3.60472 ],
    230          [ 0.      ,  0.      ,  0.      ,  1.      ]]), *args, **kwargs )
    231
    232
    233 -def MNI2Tal_Lancaster07pooled (*args, **kwargs):
    234      return Linear( N.array([
    235          [    0.93570,   0.00290,  -0.00720,  -1.04230],
    236          [   -0.00650,   0.93960,  -0.07260,  -1.39400],
    237          [    0.01030,   0.07520,   0.89670,   3.64750],
    238          [    0.00000,   0.00000,   0.00000,   1.00000] ]), *args, **kwargs )
    239
    240
    241 -def Tal2MNI_Lancaster07pooled (*args, **kwargs):
    242      return Linear( N.array([
    243          [  1.06860,  -0.00396,   0.00826,   1.07816],
    244          [  0.00640,   1.05741,   0.08566,   1.16824],
    245          [ -0.01281,  -0.08863,   1.10792,  -4.17805],
    246          [  0.00000,   0.00000,   0.00000,   1.00000] ]), *args, **kwargs )
    247
    248
    249  if __name__ == '__main__':
    250      #t = Tal2Mni
    251      tl = Tal2MNI_Lancaster07FSL()
    252      tli = MNI2Tal_Lancaster07FSL()
    253      tml = MNI2Tal_MeyerLindenberg98()
    254      #print t[1,3,2]
    255      print tl[(1,3,2)]
    256      print tli[[1,3,2]]
    257      print tml[[1,3,2]]
    258  #   print t[(1,3,2,2)]
    259