1 """
2 Neural sheet objects and associated functions.
3
4 The Sheet class is the base class for EventProcessors that simulate
5 topographically mapped sheets of units (neurons or columns). A Sheet
6 is an EventProcessor that maintains a rectangular array of activity
7 values, and sends the contents of this array as the data element in
8 events.
9
10 The Sheet itself is a SheetCoordinateSystem, so that units may be
11 accessed by sheet or matrix coordinates. In general, however, sheets
12 should be thought of as having arbitrary density and sheet coordinates
13 should be used wherever possible, except when the code needs direct
14 access to a specific unit. By adhering to this convention, one should
15 be able to write and debug a simulation at a low density, and then
16 scale it up to run at higher densities (or down for lower densities)
17 simply by changing e.g. Sheet.nominal_density.
18
19 $Id: sheet.py 11248 2010-07-18 20:40:37Z ceball $
20 """
21
22 __version__ = '$Revision: 11248 $'
23
24
25 from numpy import zeros,array,arange,meshgrid
26 from numpy import float64
27
28 import param
29
30 from simulation import EventProcessor
31 from sheetcoords import SheetCoordinateSystem
32 from boundingregion import BoundingBox, BoundingRegionParameter
33 from functionfamily import TransferFn
34
35
36 activity_type = float64
37
38
39 -class Sheet(EventProcessor,SheetCoordinateSystem):
40 """
41 The generic base class for neural sheets.
42
43 See SheetCoordinateSystem for how Sheet represents space, and
44 EventProcessor for how Sheet handles time.
45
46 output_fns are functions that take an activity matrix and produce
47 an identically shaped output matrix. The default is having no
48 output_fns.
49 """
50 __abstract = True
51
52 nominal_bounds = BoundingRegionParameter(BoundingBox(radius=0.5),constant=True,doc="""
53 User-specified BoundingBox of the Sheet coordinate area
54 covered by this Sheet. The left and right bounds--if
55 specified--will always be observed, but the top and bottom
56 bounds may be adjusted to ensure the density in the y
57 direction is the same as the density in the x direction.
58 In such a case, the top and bottom bounds are adjusted
59 so that the center y point remains the same, and each
60 bound is as close as possible to its specified value. The
61 actual value of this Parameter is not adjusted, but the
62 true bounds may be found from the 'bounds' attribute
63 of this object.
64 """)
65
66 nominal_density = param.Number(default=10,constant=True,doc="""
67 User-specified number of processing units per 1.0 distance
68 horizontally or vertically in Sheet coordinates. The actual
69 number may be different because of discretization; the matrix
70 needs to tile the plane exactly, and for that to work the
71 density might need to be adjusted. For instance, an area of 3x2
72 cannot have a density of 2 in each direction. The true density
73 may be obtained from either the xdensity or ydensity attribute
74 (since these are identical for a Sheet).
75 """)
76
77 plastic = param.Boolean(True,doc="""
78 Setting this to False tells the Sheet not to change its
79 permanent state (e.g. any connection weights) based on
80 incoming events.
81 """)
82
83 precedence = param.Number(default = 0.1, softbounds=(0.0,1.0),doc="""
84 Allows a sorting order for Sheets, e.g. in the GUI.""")
85
86 row_precedence = param.Number(default = 0.5, softbounds=(0.0,1.0),doc="""
87 Allows grouping of Sheets before sorting precedence is
88 applied, e.g. for two-dimensional plots in the GUI.""")
89
90 layout_location = param.NumericTuple(default = (-1,-1),precedence=-1,doc="""
91 Location for this Sheet in an arbitrary pixel-based space
92 in which Sheets can be laid out for visualization.""")
93
94 output_fns = param.HookList(default=[],class_=TransferFn,
95 doc="Output function(s) to apply (if apply_output_fns is true) to this Sheet's activity.")
96
97 apply_output_fns=param.Boolean(default=True,
98 doc="Whether to apply the output_fn after computing an Activity matrix.")
99
100
103
104 density = property(_get_density,doc="""The sheet's true density (i.e. the xdensity, which is equal to the ydensity for a Sheet.)""")
105
107 """
108 Initialize this object as an EventProcessor, then also as
109 a SheetCoordinateSystem with equal xdensity and ydensity.
110
111 sheet_views is a dictionary that stores SheetViews,
112 i.e. representations of the sheet for use by analysis or plotting
113 code.
114 """
115 EventProcessor.__init__(self,**params)
116
117
118
119 SheetCoordinateSystem.__init__(self,self.nominal_bounds,self.nominal_density)
120
121 n_units = round((self.lbrt[2]-self.lbrt[0])*self.xdensity,0)
122 if n_units<1: raise ValueError(
123 "Sheet bounds and density must be specified such that the "+ \
124 "sheet has at least one unit in each direction; " \
125 +self.name+ " does not.")
126
127
128 self.activity = zeros(self.shape,activity_type)
129
130
131 self.__saved_activity = []
132 self._plasticity_setting_stack = []
133 self.sheet_views = {}
134
135
136
137
138
139
140
142 """
143 Delete the dictionary entry with key entry 'view_name' to save
144 memory.
145 """
146 if self.sheet_views.has_key(view_name):
147 del self.sheet_views[view_name]
148
149
150
152 """
153 Return an array of x-coordinates and an array of y-coordinates
154 corresponding to the activity matrix of the sheet.
155 """
156 nrows,ncols=self.activity.shape
157
158 C,R = meshgrid(arange(ncols),
159 arange(nrows))
160
161 X,Y = self.matrixidx2sheet(R,C)
162 return X,Y
163
164
165
167 """
168 Return an array of Y-coordinates corresponding to the rows of
169 the activity matrix of the sheet, and an array of
170 X-coordinates corresponding to the columns.
171 """
172
173
174 nrows,ncols = self.activity.shape
175 return self.matrixidx2sheet(arange(nrows-1,-1,-1),arange(ncols))[::-1]
176
177
178
179
184
185
186
187
188
190 """
191 Collect activity from each projection, combine it to calculate
192 the activity for this sheet, and send the result out.
193
194 Subclasses will need to override this method to whatever it
195 means to calculate activity in that subclass.
196 """
197 if self.apply_output_fns:
198 for of in self.output_fns:
199 of(self.activity)
200
201 self.send_output(src_port='Activity',data=self.activity)
202
203
205 """
206 Save the current state of this sheet to an internal stack.
207
208 This method is used by operations that need to test the
209 response of the sheet without permanently altering its state,
210 e.g. for measuring maps or probing the current behavior
211 non-invasively. By default, only the activity pattern of this
212 sheet is saved, but subclasses should add saving for any
213 additional state that they maintain, or strange bugs are
214 likely to occur. The state can be restored using state_pop().
215
216 Note that Sheets that do learning need not save the
217 values of all connection weights, if any, because
218 plasticity can be turned off explicitly. Thus this method
219 is intended only for shorter-term state.
220 """
221 self.__saved_activity.append(array(self.activity))
222 EventProcessor.state_push(self)
223 for of in self.output_fns:
224 if hasattr(of,'state_push'):
225 of.state_push()
226
227
229 """
230 Pop the most recently saved state off the stack.
231
232 See state_push() for more details.
233 """
234 self.activity = self.__saved_activity.pop()
235 EventProcessor.state_pop(self)
236 for of in self.output_fns:
237 if hasattr(of,'state_pop'):
238 of.state_pop()
239
240
242 """Return the number of items that have been saved by state_push()."""
243 return len(self.__saved_activity)
244
245
247 """
248 Temporarily override plasticity of medium and long term internal state.
249
250 This function should be implemented by all subclasses so that
251 it preserves the ability of the Sheet to compute activity,
252 i.e. to operate over a short time scale, while preventing any
253 lasting changes to the state (if new_plasticity_state=False).
254
255 Any operation that does not have any lasting state, such as
256 those affecting only the current activity level, should not
257 be affected by this call.
258
259 By default, simply saves a copy of the plastic flag to an
260 internal stack (so that it can be restored by
261 restore_plasticity_state()), and then sets plastic to
262 new_plasticity_state.
263 """
264 self._plasticity_setting_stack.append(self.plastic)
265 self.plastic=new_plasticity_state
266
267
269 """
270 Restores plasticity of medium and long term internal state after
271 a override_plasticity_state call.
272
273 This function should be implemented by all subclasses to
274 remove the effect of the most recent override_plasticity_state call,
275 i.e. to restore plasticity of any type that was overridden.
276 """
277 self.plastic = self._plasticity_setting_stack.pop()
278
279
281 """
282 Return a lower bound for the memory taken by this sheet, in bytes.
283
284 Typically, this number will include the activity array and any
285 similar arrays, plus any other significant data owned (in some
286 sense) by this Sheet. It will not usually include memory
287 taken by the Python dictionary or various "housekeeping"
288 attributes, which usually contribute only a small amount to
289 the memory requirements.
290
291 Subclasses should reimplement this method if they store a
292 significant amount of data other than in the activity array.
293 """
294 return self.activity.nbytes
295