Package mvpa :: Package measures :: Module searchlight
[hide private]
[frames] | no frames]

Source Code for Module mvpa.measures.searchlight

  1  #emacs: -*- mode: python-mode; py-indent-offset: 4; indent-tabs-mode: nil -*- 
  2  #ex: set 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  """Implementation of the Searchlight algorithm""" 
 10   
 11  __docformat__ = 'restructuredtext' 
 12   
 13  if __debug__: 
 14      from mvpa.base import debug 
 15   
 16  from mvpa.datasets.mapped import MappedDataset 
 17  from mvpa.measures.base import DatasetMeasure 
 18  from mvpa.misc.state import StateVariable 
 19  from mvpa.base.dochelpers import enhancedDocString 
 20   
 21   
22 -class Searchlight(DatasetMeasure):
23 """Runs a scalar `DatasetMeasure` on all possible spheres of a certain size 24 within a dataset. 25 26 The idea for a searchlight algorithm stems from a paper by 27 :ref:`Kriegeskorte et al. (2006) <KGB06>`. 28 """ 29 30 spheresizes = StateVariable(enabled=False, 31 doc="Number of features in each sphere.") 32
33 - def __init__(self, datameasure, radius=1.0, center_ids=None, **kwargs):
34 """ 35 :Parameters: 36 datameasure: callable 37 Any object that takes a :class:`~mvpa.datasets.base.Dataset` 38 and returns some measure when called. 39 radius: float 40 All features within the radius around the center will be part 41 of a sphere. 42 center_ids: list(int) 43 List of feature ids (not coordinates) the shall serve as sphere 44 centers. By default all features will be used. 45 **kwargs 46 In additions this class supports all keyword arguments of its 47 base-class :class:`~mvpa.measures.base.DatasetMeasure`. 48 49 .. note:: 50 51 If `Searchlight` is used as `SensitivityAnalyzer` one has to make 52 sure that the specified scalar `DatasetMeasure` returns large 53 (absolute) values for high sensitivities and small (absolute) values 54 for low sensitivities. Especially when using error functions usually 55 low values imply high performance and therefore high sensitivity. 56 This would in turn result in sensitivity maps that have low 57 (absolute) values indicating high sensitivites and this conflicts 58 with the intended behavior of a `SensitivityAnalyzer`. 59 """ 60 DatasetMeasure.__init__(self, **(kwargs)) 61 62 self.__datameasure = datameasure 63 self.__radius = radius 64 self.__center_ids = center_ids
65 66 67 __doc__ = enhancedDocString('Searchlight', locals(), DatasetMeasure) 68 69
70 - def _call(self, dataset):
71 """Perform the spheresearch. 72 """ 73 if not isinstance(dataset, MappedDataset) \ 74 or dataset.mapper.metric is None: 75 raise ValueError, "Searchlight only works with MappedDatasets " \ 76 "that has metric assigned." 77 78 if self.states.isEnabled('spheresizes'): 79 self.spheresizes = [] 80 81 if __debug__: 82 nspheres = dataset.nfeatures 83 sphere_count = 0 84 85 # collect the results in a list -- you never know what you get 86 results = [] 87 88 # decide whether to run on all possible center coords or just a provided 89 # subset 90 if not self.__center_ids == None: 91 generator = self.__center_ids 92 else: 93 generator = xrange(dataset.nfeatures) 94 95 # put spheres around all features in the dataset and compute the 96 # measure within them 97 for f in generator: 98 sphere = dataset.selectFeatures( 99 dataset.mapper.getNeighbors(f, self.__radius), 100 plain=True) 101 102 # compute the datameasure and store in results 103 measure = self.__datameasure(sphere) 104 results.append(measure) 105 106 # store the size of the sphere dataset 107 if self.states.isEnabled('spheresizes'): 108 self.spheresizes.append(sphere.nfeatures) 109 110 if __debug__: 111 sphere_count += 1 112 debug('SLC', "Doing %i spheres: %i (%i features) [%i%%]" \ 113 % (nspheres, 114 sphere_count, 115 sphere.nfeatures, 116 float(sphere_count)/nspheres*100,), cr=True) 117 118 if __debug__: 119 debug('SLC', '') 120 121 # charge state 122 self.raw_results = results 123 124 # return raw results, base-class will take care of transformations 125 return results
126 127 128 129 130 #class OptimalSearchlight( object ): 131 # def __init__( self, 132 # searchlight, 133 # test_radii, 134 # verbose=False, 135 # **kwargs ): 136 # """ 137 # """ 138 # # results will end up here 139 # self.__perfmeans = [] 140 # self.__perfvars = [] 141 # self.__chisquares = [] 142 # self.__chanceprobs = [] 143 # self.__spheresizes = [] 144 # 145 # # run searchligh for all radii in the list 146 # for radius in test_radii: 147 # if verbose: 148 # print 'Using searchlight with radius:', radius 149 # # compute the results 150 # searchlight( radius, **(kwargs) ) 151 # 152 # self.__perfmeans.append( searchlight.perfmean ) 153 # self.__perfvars.append( searchlight.perfvar ) 154 # self.__chisquares.append( searchlight.chisquare ) 155 # self.__chanceprobs.append( searchlight.chanceprob ) 156 # self.__spheresizes.append( searchlight.spheresize ) 157 # 158 # 159 # # now determine the best classification accuracy 160 # best = N.array(self.__perfmeans).argmax( axis=0 ) 161 # 162 # # select the corresponding values of the best classification 163 # # in all data tables 164 # self.perfmean = best.choose(*(self.__perfmeans)) 165 # self.perfvar = best.choose(*(self.__perfvars)) 166 # self.chisquare = best.choose(*(self.__chisquares)) 167 # self.chanceprob = best.choose(*(self.__chanceprobs)) 168 # self.spheresize = best.choose(*(self.__spheresizes)) 169 # 170 # # store the best performing radius 171 # self.bestradius = N.zeros( self.perfmean.shape, dtype='uint' ) 172 # self.bestradius[searchlight.mask==True] = \ 173 # best.choose( test_radii )[searchlight.mask==True] 174 # 175 # 176 # 177 #def makeSphericalROIMask( mask, radius, elementsize=None ): 178 # """ 179 # """ 180 # # use default elementsize if none is supplied 181 # if not elementsize: 182 # elementsize = [ 1 for i in range( len(mask.shape) ) ] 183 # else: 184 # if len( elementsize ) != len( mask.shape ): 185 # raise ValueError, 'elementsize does not match mask dimensions.' 186 # 187 # # rois will be drawn into this mask 188 # roi_mask = N.zeros( mask.shape, dtype='int32' ) 189 # 190 # # while increase with every ROI 191 # roi_id_counter = 1 192 # 193 # # build spheres around every non-zero value in the mask 194 # for center, spheremask in \ 195 # algorithms.SpheresInMask( mask, 196 # radius, 197 # elementsize, 198 # forcesphere = True ): 199 # 200 # # set all elements that match the current spheremask to the 201 # # current ROI index value 202 # roi_mask[spheremask] = roi_id_counter 203 # 204 # # increase ROI counter 205 # roi_id_counter += 1 206 # 207 # return roi_mask 208