1
2
3
4
5
6
7
8
9 """Classes and functions to provide sense of distances between sample points"""
10
11 __docformat__ = 'restructuredtext'
12
13 import numpy as N
14
15 from mvpa.clfs.distance import cartesianDistance
16
18 """Abstract class for any finder.
19
20 Classes subclasses from this class show know about structure of
21 the data and thus be able to provide information about the
22 neighbors.
23 At least one of the methods (getNeighbors, getNeighbor) has to be
24 overriden in the derived class.
25 NOTE: derived #2 from derived class #1 has to override all methods
26 which were overrident in class #1
27 """
28
30 """Return the list of coordinates for the neighbors.
31
32 By default it simply constracts the list based on
33 the generator getNeighbor
34 """
35 return [ x for x in self.getNeighbor(*args, **kwargs) ]
36
37
39 """Generator to return coordinate of the neighbor.
40
41 Base class contains the simplest implementation, assuming that
42 getNeighbors returns iterative structure to spit out neighbors
43 1-by-1
44 """
45 for neighbor in self.getNeighbors(*args, **kwargs):
46 yield neighbor
47
48
49
51 """Find neighboring points in descretized space
52
53 If input space is descretized and all points fill in
54 N-dimensional cube, this finder returns list of neighboring
55 points for a given distance.
56
57 As input points it operates on discretized values, not absolute
58 coordinates (which are e.g. in mm)
59 """
60
64 """
65 Initialize the class provided @elementsize and @distance_function
66 """
67 Metric.__init__(self)
68 self.__filter_radius = None
69 self.__filter_coord = None
70 self.__distance_function = distance_function
71
72
73 self.__elementsize = N.array(elementsize, ndmin=1)
74 self.__Ndims = len(self.__elementsize)
75
76
78 """ (Re)Computer filter_coord based on given radius
79 """
80
81 elementradius_per_axis = float(radius) / self.__elementsize
82
83
84 filter_radiuses = N.array([int(N.ceil(abs(x)))
85 for x in elementradius_per_axis])
86 filter_center = filter_radiuses
87 filter_mask = N.ones( ( filter_radiuses * 2 ) + 1 )
88
89
90 f_coords = N.transpose( filter_mask.nonzero() )
91
92
93 for coord in f_coords:
94 dist = self.__distance_function(coord*self.__elementsize,
95 filter_center*self.__elementsize)
96
97 if radius < dist:
98
99 filter_mask[N.array(coord, ndmin=2).T.tolist()] = 0
100
101 self.__filter_coord = N.array( filter_mask.nonzero() ).T \
102 - filter_center
103 self.__filter_radius = radius
104
105
107 """Returns coordinates of the neighbors which are within
108 distance from coord
109
110 XXX radius might need to be not a scalar but a vector of
111 scalars to specify search distance in different dimensions
112 differently... but then may be it has to be a tensor to
113 specify orientation etc? :-) so it might not be necessary for
114 now
115 """
116 if len(origin) != self.__Ndims:
117 raise ValueError("Obtained coordinates [%s] which have different"
118 + " number of dimensions (%d) from known "
119 + " elementsize" % (`origin`, self.__Ndims))
120 if radius != self.__filter_radius:
121 self._computeFilter(radius)
122
123
124
125 return origin + self.__filter_coord
126
127
129 """Lets allow to specify some custom filter to use
130 """
131 self.__filter_coord = filter_coord
132
133
135 """Lets allow to specify some custom filter to use
136 """
137 return self.__filter_coord
138
139 filter_coord = property(fget=_getFilter, fset=_setFilter)
140 elementsize = property(fget=lambda self: self.__elementsize)
141
142
143
144
145
146
147
148
149
150