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 if name is not None:
115 if isinstance(name, basestring):
116 if name[0] == '_':
117 raise ValueError, \
118 "Collectable attribute name must not start " \
119 "with _. Got %s" % name
120 else:
121 raise ValueError, \
122 "Collectable attribute name must be a string. " \
123 "Got %s" % `name`
124 self.__name = name
125
126
127
128
129
130
131 value = property(_getVirtual, _setVirtual)
132 name = property(_getName, _setName)
133
139 """Container which also takes care about recomputing unique values
140
141 XXX may be we could better link original attribute to additional
142 attribute which actually stores the values (and do reverse there
143 as well).
144
145 Pros:
146 * don't need to mess with getattr since it would become just another
147 attribute
148
149 Cons:
150 * might be worse design in terms of comprehension
151 * take care about _set, since we shouldn't allow
152 change it externally
153
154 For now lets do it within a single class and tune up getattr
155 """
156
157 - def __init__(self, name=None, hasunique=True, doc="Attribute with unique"):
164
165
169
170
172 self._uniqueValues = None
173
174
175 - def _set(self, *args, **kwargs):
178
179
181 if self.value is None:
182 return None
183 if self._uniqueValues is None:
184
185
186
187
188 self._uniqueValues = N.unique(N.asanyarray(self.value))
189 return self._uniqueValues
190
191 uniqueValues = property(fget=_getUniqueValues)
192 hasunique = property(fget=lambda self:self._hasunique)
193
199
204
209
213 """Simple container intended to conditionally store the value
214 """
215
216 - def __init__(self, name=None, enabled=True, doc="State variable"):
223
224
229
230
231 - def _set(self, val):
232 if self.isEnabled:
233
234
235 CollectableAttribute._set(self, val)
236 elif __debug__:
237 debug("COL",
238 "Not setting disabled %(self)s to %(val)s ",
239 msgargs={'self':self, 'val':val})
240
241
246
247
248 @property
250 return self._isenabled
251
252
253 - def enable(self, value=False):
254 if self._isenabled == value:
255
256 return
257 if __debug__:
258 debug("STV", "%s %s" %
259 ({True: 'Enabling', False: 'Disabling'}[value], str(self)))
260 self._isenabled = value
261
262
268