/usr/share/pyshared/mvpa/misc/attributes.py is in python-mvpa 0.4.8-3.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 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 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 | # emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*-
# vi: set ft=python sts=4 ts=4 sw=4 et:
### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##
#
# See COPYING file distributed along with the PyMVPA package for the
# copyright and license terms.
#
### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##
"""Module with some special objects to be used as magic attributes with
dedicated containers aka. `Collections`.
"""
__docformat__ = 'restructuredtext'
from mvpa.misc.exceptions import UnknownStateError
if __debug__:
from mvpa.base import debug
##################################################################
# Various attributes which will be collected into collections
#
class CollectableAttribute(object):
"""Base class for any custom behaving attribute intended to become
part of a collection.
Derived classes will have specific semantics:
* StateVariable: conditional storage
* AttributeWithUnique: easy access to a set of unique values
within a container
* Parameter: attribute with validity ranges.
- ClassifierParameter: specialization to become a part of
Classifier's params collection
- KernelParameter: --//-- to become a part of Kernel Classifier's
kernel_params collection
Those CollectableAttributes are to be groupped into corresponding
collections for each class by statecollector metaclass, ie it
would be done on a class creation (ie not per each object)
"""
_instance_index = 0
def __init__(self, name=None, doc=None, index=None):
if index is None:
CollectableAttribute._instance_index += 1
index = CollectableAttribute._instance_index
self._instance_index = index
self.__doc__ = doc
self.__name = name
self._value = None
self._isset = False
self.reset()
if __debug__:
debug("COL",
"Initialized new collectable #%d:%s" % (index,name) + `self`)
# Instead of going for VProperty lets make use of virtual method
def _getVirtual(self):
return self._get()
def _setVirtual(self, value):
return self._set(value)
def _get(self):
return self._value
def _set(self, val):
if __debug__:
# Since this call is quite often, don't convert
# values to strings here, rely on passing them
# withing msgargs
debug("COL",
"Setting %(self)s to %(val)s ",
msgargs={'self':self, 'val':val})
self._value = val
self._isset = True
@property
def isSet(self):
return self._isset
def reset(self):
"""Simply reset the flag"""
if __debug__ and self._isset:
debug("COL", "Reset %s to being non-modified" % self.name)
self._isset = False
# TODO XXX unify all bloody __str__
def __str__(self):
res = "%s" % (self.name)
if self.isSet:
res += '*' # so we have the value already
return res
def _getName(self):
return self.__name
def _setName(self, name):
"""Set the name of parameter
.. note::
Should not be called for an attribute which is already assigned
to a collection
"""
if name is not None:
if isinstance(name, basestring):
if name[0] == '_':
raise ValueError, \
"Collectable attribute name must not start " \
"with _. Got %s" % name
else:
raise ValueError, \
"Collectable attribute name must be a string. " \
"Got %s" % `name`
self.__name = name
# XXX should become vproperty?
# YYY yoh: not sure... someone has to do performance testing
# to see which is more effective. My wild guess is that
# _[gs]etVirtual would be faster
value = property(_getVirtual, _setVirtual)
name = property(_getName) #, _setName)
# XXX think that may be discard hasunique and just devise top
# class DatasetAttribute
class AttributeWithUnique(CollectableAttribute):
"""Container which also takes care about recomputing unique values
XXX may be we could better link original attribute to additional
attribute which actually stores the values (and do reverse there
as well).
Pros:
* don't need to mess with getattr since it would become just another
attribute
Cons:
* might be worse design in terms of comprehension
* take care about _set, since we shouldn't allow
change it externally
For now lets do it within a single class and tune up getattr
"""
def __init__(self, name=None, hasunique=True, doc="Attribute with unique"):
CollectableAttribute.__init__(self, name, doc)
self._hasunique = hasunique
self._resetUnique()
if __debug__:
debug("UATTR",
"Initialized new AttributeWithUnique %s " % name + `self`)
def reset(self):
super(AttributeWithUnique, self).reset()
self._resetUnique()
def _resetUnique(self):
self._uniqueValues = None
def _set(self, *args, **kwargs):
self._resetUnique()
CollectableAttribute._set(self, *args, **kwargs)
def _getUniqueValues(self):
if self.value is None:
return None
if self._uniqueValues is None:
# XXX we might better use Set, but yoh recalls that
# N.unique was more efficient. May be we should check
# on the the class and use Set only if we are not
# dealing with ndarray (or lists/tuples)
self._uniqueValues = N.unique(N.asanyarray(self.value))
return self._uniqueValues
uniqueValues = property(fget=_getUniqueValues)
hasunique = property(fget=lambda self:self._hasunique)
# Hooks for comprehendable semantics and automatic collection generation
class SampleAttribute(AttributeWithUnique):
pass
class FeatureAttribute(AttributeWithUnique):
pass
class DatasetAttribute(AttributeWithUnique):
pass
class StateVariable(CollectableAttribute):
"""Simple container intended to conditionally store the value
"""
def __init__(self, name=None, enabled=True, doc="State variable"):
# Force enabled state regardless of the input
# to facilitate testing
if __debug__ and 'ENFORCE_STATES_ENABLED' in debug.active:
enabled = True
CollectableAttribute.__init__(self, name, doc)
self._isenabled = enabled
self._defaultenabled = enabled
if __debug__:
debug("STV",
"Initialized new state variable %s " % name + `self`)
def _get(self):
if not self.isSet:
raise UnknownStateError("Unknown yet value of %s" % (self.name))
return CollectableAttribute._get(self)
def _set(self, val):
if self.isEnabled:
# XXX may be should have left simple assignment
# self._value = val
CollectableAttribute._set(self, val)
elif __debug__:
debug("COL",
"Not setting disabled %(self)s to %(val)s ",
msgargs={'self':self, 'val':val})
def reset(self):
"""Simply detach the value, and reset the flag"""
CollectableAttribute.reset(self)
self._value = None
@property
def isEnabled(self):
return self._isenabled
def enable(self, value=False):
if self._isenabled == value:
# Do nothing since it is already in proper state
return
if __debug__:
debug("STV", "%s %s" %
({True: 'Enabling', False: 'Disabling'}[value], str(self)))
self._isenabled = value
def __str__(self):
res = CollectableAttribute.__str__(self)
if self.isEnabled:
res += '+' # it is enabled but no value is assigned yet
return res
|