1
2
3
4
5
6
7
8
9 """Implementation of the Searchlight algorithm"""
10
11 __docformat__ = 'restructuredtext'
12
13 if __debug__:
14 from mvpa.misc import debug
15
16 from mvpa.datasets.mappeddataset import MappedDataset
17 from mvpa.mappers.metric import MetricMapper
18 from mvpa.measures.base import DatasetMeasure
19 from mvpa.misc.state import StateVariable
20 from mvpa.base.dochelpers import enhancedDocString
21
22
24 """Runs a scalar `DatasetMeasure` on all possible spheres of a certain size
25 within a dataset.
26
27 The idea for a searchlight algorithm stems from this paper:
28
29 Kriegeskorte, N., Goebel, R. & Bandettini, P. (2006).
30 'Information-based functional brain mapping.' Proceedings of the
31 National Academy of Sciences of the United States of America 103,
32 3863-3868.
33 """
34
35 spheresizes = StateVariable(enabled=False,
36 doc="Number of features in each sphere.")
37
38 - def __init__(self, datameasure, radius=1.0, center_ids=None, **kwargs):
39 """Initialize Searchlight to compute `datameasure` for each sphere with
40 a certain `radius` in a given dataset.
41
42 :Parameters:
43 datameasure: callable
44 Any object that takes a `Dataset` and returns some measure when
45 called.
46 radius: float
47 All features within the radius around the center will be part
48 of a sphere.
49 center_ids: list(int)
50 List of feature ids (not coordinates) the shall serve as sphere
51 centers. By default all features will be used.
52 **kwargs:
53 In additions this class supports all keyword arguments of its
54 base-class `DatasetMeasure`.
55
56 ATTENTION: If `Searchlight` is used as `SensitivityAnalyzer` one has to
57 make sure that the specified scalar `DatasetMeasure` returns large
58 (absolute) values for high sensitivities and small (absolute) values
59 for low sensitivities. Especially when using error functions usually
60 low values imply high performance and therefore high sensitivity. This
61 would in turn result in sensitivity maps that have low (absolute)
62 values indicating high sensitivites and this conflicts with the
63 intended behavior of a `SensitivityAnalyzer`.
64 """
65 DatasetMeasure.__init__(self, **(kwargs))
66
67 self.__datameasure = datameasure
68 self.__radius = radius
69 self.__center_ids = center_ids
70
71
72 __doc__ = enhancedDocString('Searchlight', locals(), DatasetMeasure)
73
74
75 - def _call(self, dataset):
76 """Perform the spheresearch.
77 """
78 if not isinstance(dataset, MappedDataset) \
79 or not isinstance(dataset.mapper, MetricMapper):
80 raise ValueError, "Searchlight only works with MappedDatasets " \
81 "that make use of a mapper with information " \
82 "about the dataspace metrics."
83
84 if self.states.isEnabled('spheresizes'):
85 self.spheresizes = []
86
87 if __debug__:
88 nspheres = dataset.nfeatures
89 sphere_count = 0
90
91
92 results = []
93
94
95
96 if not self.__center_ids == None:
97 generator = self.__center_ids
98 else:
99 generator = xrange(dataset.nfeatures)
100
101
102
103 for f in generator:
104 sphere = dataset.selectFeatures(
105 dataset.mapper.getNeighbors(f, self.__radius),
106 plain=True)
107
108
109 measure = self.__datameasure(sphere)
110 results.append(measure)
111
112
113 if self.states.isEnabled('spheresizes'):
114 self.spheresizes.append(sphere.nfeatures)
115
116 if __debug__:
117 sphere_count += 1
118 debug('SLC', "Doing %i spheres: %i (%i features) [%i%%]" \
119 % (nspheres,
120 sphere_count,
121 sphere.nfeatures,
122 float(sphere_count)/nspheres*100,), cr=True)
123
124 if __debug__:
125 debug('SLC', '')
126
127
128 self.raw_results = results
129
130
131 return results
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214