/usr/share/pyshared/brian/group.py is in python-brian 1.3.1-1build1.
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 | from brian import *
__all__ = ['Group', 'MultiGroup']
class Group(object):
'''
Generic fixed-length variable values container class
Used internally by Brian to store values associated with variables. Primary
use is for NeuronGroup to store a state matrix of values associated to the
different variables.
Each differential equation in ``equations`` is allocated an array of
length ``N`` in the attribute ``_S`` of the object. Unit consistency
checking is performed.
'''
def __init__(self, equations, N, level=0, unit_checking=True):
if isinstance(equations, str):
equations = Equations(equations, level=level + 1)
equations.prepare(check_units=unit_checking)
var_names = equations._diffeq_names
M = len(var_names)
self._S = zeros((M, N))
self.staticvars = dict([(name, equations._function[name]) for name in equations._eq_names])
self.var_index = dict(zip(var_names, range(M)))
self.var_index.update(zip(range(M), range(M))) # name integer i -> state variable i
for var1, var2 in equations._alias.iteritems():
self.var_index[var1] = self.var_index[var2]
def get_var_index(self, name):
'''
Returns the index of state variable "name".
'''
return self.var_index[name]
def __len__(self):
'''
Number of neurons in the group.
'''
return self._S.shape[1]
def num_states(self):
return self._S.shape[0]
def state_(self, name):
'''
Gets the state variable named "name" as a reference to the underlying array
'''
if isinstance(name, int):
return self._S[name]
if name in self.staticvars:
f = self.staticvars[name]
return f(*[self.state_(var) for var in f.func_code.co_varnames])
i = self.var_index[name]
return self._S[i]
state = state_
def __getattr__(self, name):
if name == 'var_index':
# this seems mad - the reason is that getattr is only called if the thing hasn't
# been found using the standard methods of finding attributes, which for var_index
# should have worked, this is important because the next line looks for var_index
# and if we haven't got a var_index we don't want to get stuck in an infinite
# loop
raise AttributeError
if not hasattr(self, 'var_index'):
# only provide lookup of variable names if we have some variable names, i.e.
# if the var_index attribute exists
raise AttributeError
try:
return self.state(name)
except KeyError:
if len(name) and name[-1] == '_':
try:
origname = name[:-1]
return self.state_(origname)
except KeyError:
raise AttributeError
raise AttributeError
def __setattr__(self, name, val):
origname = name
if len(name) and name[-1] == '_':
origname = name[:-1]
if not hasattr(self, 'var_index') or (name not in self.var_index and origname not in self.var_index):
object.__setattr__(self, name, val)
else:
if name in self.var_index:
self.state(name)[:] = val
else:
self.state_(origname)[:] = val
class MultiGroup(object):
'''
Generic variable-length variable values container class
Used internally by Brian to store values associated with variables.
See :class:`Group` for more details.
This class takes a list of groups or of ``(equations, N)`` pairs.
The ``state()`` and ``state_()`` methods work as if it were a
single :class:`Group` but return arrays of different lengths from
different state matrix structures depending on where the state
value is defined. Similarly for attribute access.
'''
def __init__(self, groups, level=0):
newgroups = []
self.var_index = dict()
for g in groups:
if not isinstance(g, Group):
eqs, N = g
g = Group(eqs, N, level=level + 1)
newgroups.append(g)
self.var_index.update(dict((k, g) for k in g.var_index.keys()))
self.var_index.update(dict((k, g) for k in g.staticvars.keys()))
self.groups = newgroups
def state_(self, name):
return self.var_index[name].state_(name)
state = state_
def __getattr__(self, name):
try:
return self.state(name)
except KeyError:
if len(name) and name[-1] == '_':
try:
origname = name[:-1]
return self.state_(origname)
except KeyError:
raise AttributeError
raise AttributeError
def __setattr__(self, name, val):
origname = name
if len(name) and name[-1] == '_':
origname = name[:-1]
if not hasattr(self, 'var_index') or (name not in self.var_index and origname not in self.var_index):
object.__setattr__(self, name, val)
else:
if name in self.var_index:
self.state(name)[:] = val
else:
self.state_(origname)[:] = val
if __name__ == '__main__':
if True:
eqs_A = Equations('''
dV/dt = -V/(1*second) : volt
W = V*V : volt2
x = V
''')
eqs_B = Equations('''
dVb/dt = -Vb/(1*second) : volt
Wb = Vb*Vb : volt2
xb = Vb
''')
g = MultiGroup(((eqs_A, 10), (eqs_B, 5)))
for h in g.groups:
h._S[:] = rand(*h._S.shape)
print g.V
print g.V ** 2
print g.W
print g.x
print g.Vb
print g.Vb ** 2
print g.Wb
print g.xb
if False:
eqs = Equations('''
dV/dt = -V/(1*second) : volt
W = V*V : volt2
x = V
''')
g = Group(eqs, 10)
print g._S
g._S[:] = rand(*g._S.shape)
print g._S
print g.V
print g.V ** 2
print g.W
print g.x
g.V = -1
print g.V
print g.W
print g.x
|