1
2
3
4
5
6
7
8
9 """Module with some special objects to be used as magic attributes with
10 dedicated containers aka. `Collections`.
11 """
12
13 __docformat__ = 'restructuredtext'
14
15
16 from mvpa.misc.exceptions import UnknownStateError
17
18 if __debug__:
19 from mvpa.base import debug
27 """Base class for any custom behaving attribute intended to become
28 part of a collection.
29
30 Derived classes will have specific semantics:
31
32 * StateVariable: conditional storage
33 * AttributeWithUnique: easy access to a set of unique values
34 within a container
35 * Parameter: attribute with validity ranges.
36
37 - ClassifierParameter: specialization to become a part of
38 Classifier's params collection
39 - KernelParameter: --//-- to become a part of Kernel Classifier's
40 kernel_params collection
41
42 Those CollectableAttributes are to be groupped into corresponding
43 collections for each class by statecollector metaclass, ie it
44 would be done on a class creation (ie not per each object)
45 """
46
47 _instance_index = 0
48
49 - def __init__(self, name=None, doc=None, index=None):
62
63
64
67
68
71
72
75
76
77 - def _set(self, val):
78 if __debug__:
79
80
81
82 debug("COL",
83 "Setting %(self)s to %(val)s ",
84 msgargs={'self':self, 'val':val})
85 self._value = val
86 self._isset = True
87
88
89 @property
92
93
95 """Simply reset the flag"""
96 if __debug__ and self._isset:
97 debug("COL", "Reset %s to being non-modified" % self.name)
98 self._isset = False
99
100
101
103 res = "%s" % (self.name)
104 if self.isSet:
105 res += '*'
106 return res
107
108
111
112
114 """Set the name of parameter
115
116 .. note::
117 Should not be called for an attribute which is already assigned
118 to a collection
119 """
120 if name is not None:
121 if isinstance(name, basestring):
122 if name[0] == '_':
123 raise ValueError, \
124 "Collectable attribute name must not start " \
125 "with _. Got %s" % name
126 else:
127 raise ValueError, \
128 "Collectable attribute name must be a string. " \
129 "Got %s" % `name`
130 self.__name = name
131
132
133
134
135
136
137 value = property(_getVirtual, _setVirtual)
138 name = property(_getName)
139
145 """Container which also takes care about recomputing unique values
146
147 XXX may be we could better link original attribute to additional
148 attribute which actually stores the values (and do reverse there
149 as well).
150
151 Pros:
152 * don't need to mess with getattr since it would become just another
153 attribute
154
155 Cons:
156 * might be worse design in terms of comprehension
157 * take care about _set, since we shouldn't allow
158 change it externally
159
160 For now lets do it within a single class and tune up getattr
161 """
162
163 - def __init__(self, name=None, hasunique=True, doc="Attribute with unique"):
170
171
175
176
178 self._uniqueValues = None
179
180
181 - def _set(self, *args, **kwargs):
184
185
187 if self.value is None:
188 return None
189 if self._uniqueValues is None:
190
191
192
193
194 self._uniqueValues = N.unique(N.asanyarray(self.value))
195 return self._uniqueValues
196
197 uniqueValues = property(fget=_getUniqueValues)
198 hasunique = property(fget=lambda self:self._hasunique)
199
205
210
215
219 """Simple container intended to conditionally store the value
220 """
221
222 - def __init__(self, name=None, enabled=True, doc="State variable"):
233
234
239
240
241 - def _set(self, val):
242 if self.isEnabled:
243
244
245 CollectableAttribute._set(self, val)
246 elif __debug__:
247 debug("COL",
248 "Not setting disabled %(self)s to %(val)s ",
249 msgargs={'self':self, 'val':val})
250
251
256
257
258 @property
260 return self._isenabled
261
262
263 - def enable(self, value=False):
264 if self._isenabled == value:
265
266 return
267 if __debug__:
268 debug("STV", "%s %s" %
269 ({True: 'Enabling', False: 'Disabling'}[value], str(self)))
270 self._isenabled = value
271
272
278