er, i think i attached the wrong patch. fracking git commit --amend :-) here, use this one instead.
V- * Valentin Haenel <[email protected]> [090424]: > Hi, > > i am working with FIR betas. Thus i have 8 timebins for which i need to rerun > the searchlight. This should result in 8 accuracy maps, one for each timebin. > > Although i could just iterate over datasets with the searchlight call, however > in that case the searchlight indexes would be recomputed for each timebin. > > I modified the Searchlight to operate also on lists of datasets, whereby the > searchlight indexes are stored and used again for each timebin after the first > this works for my particular use case, and reduces the computing time > somewhat. > > I patched the code such that the API remains backward compatible, and existing > code should not break. > > I do not know how else the Searchlight is used, so i am not sure if my > modifications break something, and unfortunately the unit tests are still > segfaulting on this end, and i'm not sure how to run only the unit test for > the > Searchlight. > > Also i ran the code through pylint, and it complained mainly about functions > prefixed with __. > > I would also like to check that the datasets are of the same brain, not sure > how > to do that though, maybe check equality of the masks? > > Furthermore i think there is a bug on line 84, where it says FIXME, however if > this is the case i would probably send a separate patch for that. > > Please have a look at the code. > > cheers > > V- > > From 11e4fc5ad0f70a428ccb3eac67360e32bb5cf30c Mon Sep 17 00:00:00 2001 > From: Valentin Haenel <[email protected]> > Date: Wed, 22 Apr 2009 16:13:08 +0200 > Subject: [PATCH] modifying searchlight to work with lists of datasets > > --- > mvpa/measures/searchlight.py | 107 ++++++++++++++++++++++++++++++++--------- > 1 files changed, 83 insertions(+), 24 deletions(-) > > diff --git a/mvpa/measures/searchlight.py b/mvpa/measures/searchlight.py > index 5171dda..803e49b 100644 > --- a/mvpa/measures/searchlight.py > +++ b/mvpa/measures/searchlight.py > @@ -64,62 +64,121 @@ class Searchlight(DatasetMeasure): > self.__datameasure = datameasure > self.__radius = radius > self.__center_ids = center_ids > - > + self.__searchlight_indexes = dict() > > __doc__ = enhancedDocString('Searchlight', locals(), DatasetMeasure) > > - > - def _call(self, dataset): > - """Perform the spheresearch. > - """ > + def __check_dataset_type(self, dataset): > + """ check that the dataset is mapped and has a metric """ > if not isinstance(dataset, MappedDataset) \ > or dataset.mapper.metric is None: > raise ValueError, "Searchlight only works with MappedDatasets " \ > "that has metric assigned." > > + > + > + def __setup_housekeeping(self, dataset): > + """ setup house keeping for state monitoring and debugging """ > if self.states.isEnabled('spheresizes'): > self.spheresizes = [] > > if __debug__: > - nspheres = dataset.nfeatures > - sphere_count = 0 > - > - # collect the results in a list -- you never know what you get > - results = [] > + self.nspheres = dataset.nfeatures > + self.sphere_count = 0 > > # decide whether to run on all possible center coords or just a > provided > # subset > if not self.__center_ids == None: > - generator = self.__center_ids > + self.generator = self.__center_ids > else: > - generator = xrange(dataset.nfeatures) > + self.generator = xrange(dataset.nfeatures) > + > + > + > + def __get_searchlight_indexes(self,voxel_id, dataset): > + """ lazily compute searchlight indexes """ > + # if the indexes for this voxel exist already return them > + if self.__searchlight_indexes.has_key(voxel_id): > + return self.__searchlight_indexes.get(voxel_id) > + # otherwise compute it now, and store for later > + else: > + indexes = dataset.mapper.getNeighbors(voxel_id, self.__radius) > + self.__searchlight_indexes[voxel_id] = indexes > + > + # store the size of the sphere dataset > + if self.states.isEnabled('spheresizes'): > + self.spheresizes.append(indexes.nfeatures) > + > + return indexes > + > + > + > + def __single_dataset(self, dataset): > + """ perform the searchlight on a single dataset """ > + self.__check_dataset_type(dataset) > + > + self.__setup_housekeeping(dataset) > + > + # collect the results in a list -- you never know what you get > + results = [] > > # put spheres around all features in the dataset and compute the > # measure within them > - for f in generator: > - sphere = dataset.selectFeatures( > - dataset.mapper.getNeighbors(f, self.__radius), > - plain=True) > + for f in self.generator: > + sphere = dataset.selectFeatures(self.__get_searchlight_indexes(f, > + dataset), plain=True) > > # compute the datameasure and store in results > measure = self.__datameasure(sphere) > results.append(measure) > > - # store the size of the sphere dataset > - if self.states.isEnabled('spheresizes'): > - self.spheresizes.append(sphere.nfeatures) > - > if __debug__: > - sphere_count += 1 > + self.sphere_count += 1 > debug('SLC', "Doing %i spheres: %i (%i features) [%i%%]" \ > - % (nspheres, > - sphere_count, > + % (self.nspheres, > + self.sphere_count, > sphere.nfeatures, > - float(sphere_count)/nspheres*100,), cr=True) > + float(self.sphere_count)/self.nspheres*100,), cr=True) > > if __debug__: > debug('SLC', '') > > + return results > + > + > + > + def __multiple_datasets(self, datasets): > + """ perform the searchlight on multiple datasets, reusing the voxel > + indices of the searchlights """ > + > + # check the correct dataset type for all datasets, > + # since we don't want it to crach halfway through > + for d in datasets: > + self.__check_dataset_type(d) > + > + self.__setup_housekeeping(datasets[0]) > + > + # preallocate enough results lists > + results = [] > + > + # now do the actual analysis > + > + if __debug__: > + debug('SLC', "found %i datasets", (len(datasets))) > + for (i, d) in enumerate(datasets): > + results.append(self.__single_dataset(d)) > + > + return results > + > + > + > + def _call(self, dataset): > + """Perform the spheresearch. """ > + if isinstance(dataset,list): > + results = self.__multiple_datasets(dataset) > + else: > + results = self.__single_dataset(dataset) > + > # charge state > self.raw_results = results > > -- > 1.5.6.5 > > _______________________________________________ > Pkg-ExpPsy-PyMVPA mailing list > [email protected] > http://lists.alioth.debian.org/mailman/listinfo/pkg-exppsy-pymvpa
>From db6cbb52e3821aeabb466fffe103535ba0b7e85f Mon Sep 17 00:00:00 2001 From: Valentin Haenel <[email protected]> Date: Wed, 22 Apr 2009 16:13:08 +0200 Subject: [PATCH] modifying searchlight to work with lists of datasets --- mvpa/measures/searchlight.py | 88 +++++++++++++++++++++++++++++------------- 1 files changed, 61 insertions(+), 27 deletions(-) diff --git a/mvpa/measures/searchlight.py b/mvpa/measures/searchlight.py index 5171dda..85e996b 100644 --- a/mvpa/measures/searchlight.py +++ b/mvpa/measures/searchlight.py @@ -64,71 +64,105 @@ class Searchlight(DatasetMeasure): self.__datameasure = datameasure self.__radius = radius self.__center_ids = center_ids - + self.__searchlight_indexes = dict() __doc__ = enhancedDocString('Searchlight', locals(), DatasetMeasure) - - def _call(self, dataset): - """Perform the spheresearch. - """ + def __check_dataset_type(self, dataset): + """ check that the dataset is mapped and has a metric """ if not isinstance(dataset, MappedDataset) \ or dataset.mapper.metric is None: raise ValueError, "Searchlight only works with MappedDatasets " \ "that has metric assigned." + def __setup_housekeeping(self, dataset): + """ setup house keeping for state monitoring and debugging """ if self.states.isEnabled('spheresizes'): self.spheresizes = [] if __debug__: - nspheres = dataset.nfeatures - sphere_count = 0 - - # collect the results in a list -- you never know what you get - results = [] + # FIXME what if __center_ids is set, in that case the number of + # spheres should be len(self.__center_ids) + self.nspheres = dataset.nfeatures + self.sphere_count = 0 # decide whether to run on all possible center coords or just a provided # subset if not self.__center_ids == None: - generator = self.__center_ids + self.generator = self.__center_ids + else: + self.generator = xrange(dataset.nfeatures) + + def __get_searchlight_indexes(self, voxel_id, dataset): + """ lazily compute searchlight indexes """ + # if the indexes for this voxel exist already return them + if self.__searchlight_indexes.has_key(voxel_id): + return self.__searchlight_indexes.get(voxel_id) + # otherwise compute it now, and store for later else: - generator = xrange(dataset.nfeatures) + indexes = dataset.mapper.getNeighbors(voxel_id, self.__radius) + self.__searchlight_indexes[voxel_id] = indexes + + # store the size of the sphere dataset + if self.states.isEnabled('spheresizes'): + self.spheresizes.append(indexes.nfeatures) + + return indexes + + def __single_dataset(self, dataset): + """ perform the searchlight on a single dataset """ + # collect the results in a list -- you never know what you get + results = [] # put spheres around all features in the dataset and compute the # measure within them - for f in generator: - sphere = dataset.selectFeatures( - dataset.mapper.getNeighbors(f, self.__radius), - plain=True) + for f in self.generator: + sphere = dataset.selectFeatures(self.__get_searchlight_indexes(f, + dataset), plain=True) # compute the datameasure and store in results measure = self.__datameasure(sphere) results.append(measure) - # store the size of the sphere dataset - if self.states.isEnabled('spheresizes'): - self.spheresizes.append(sphere.nfeatures) - if __debug__: - sphere_count += 1 + self.sphere_count += 1 debug('SLC', "Doing %i spheres: %i (%i features) [%i%%]" \ - % (nspheres, - sphere_count, + % (self.nspheres, + self.sphere_count, sphere.nfeatures, - float(sphere_count)/nspheres*100,), cr=True) + float(self.sphere_count)/self.nspheres*100, ), cr=True) if __debug__: debug('SLC', '') + return results + + def __multiple_datasets(self, datasets): + """ perform the searchlight on multiple datasets, reusing the voxel + indices of the searchlights """ + if __debug__: + debug('SLC', "Found %i datasets" % (len(datasets))) + + return [self.__single_dataset(d) for d in datasets] + + def _call(self, dataset): + """Perform the spheresearch. """ + if isinstance(dataset, list): + # dataset is actually datasets + [self.__check_dataset_type(d) for d in dataset] + self.__setup_housekeeping(dataset[0]) + results = self.__multiple_datasets(dataset) + else: + self.__check_dataset_type(dataset) + self.__setup_housekeeping(dataset) + results = self.__single_dataset(dataset) + # charge state self.raw_results = results # return raw results, base-class will take care of transformations return results - - - #class OptimalSearchlight( object ): # def __init__( self, # searchlight, -- 1.5.6.5
_______________________________________________ Pkg-ExpPsy-PyMVPA mailing list [email protected] http://lists.alioth.debian.org/mailman/listinfo/pkg-exppsy-pymvpa

