Source code for topo.sheet.composer

"""
A Sheet class for composing activity from different sheets into a
single activity matrix.  Primarily a simple example of how to make
a sheet class, but can also be useful.
"""
import numpy as np

from topo.base.sheet import Sheet
from topo.misc.util import Struct, NxN

[docs]class Composer(Sheet): """ A Sheet that combines the activity of 2 or more other sheets into a single activity matrix. When connecting a sheet to a composer, you can specify the location at which that sheet's input will be mapped into the composer by adding the 'origin' argument to the connect() call e.g.: sim.connect(input_sheet.name,composer.name,delay=1, origin=(0.25,0.25)) will cause (0,0) on input sheet's activity to map to (0.25,0.25) on composer's activity. """ dest_ports=None # Allows connections to come in on any port def __init__(self,**params): super(Composer,self).__init__(**params) self.inputs = {} self.__dirty = False
[docs] def port_configure(self,port,**config): """ Configure a specific input port. origin = (default (0,0)) The offset in the output matrix where this port's input should be placed. """ if not port in self.ports: self.ports[port] = {} for k,v in config.items(): self.ports[port][k] = v
def _dest_connect(self,proj,origin=(0,0)): super(Composer,self)._dest_connect(proj) self.inputs[(proj.src.name,proj.src_port)] = Struct(origin=origin) def process_current_time(self): if self.__dirty: self.send_output(data=self.activity) self.activity = np.zeros(self.activity.shape)+0.0 self.__dirty=False def input_event(self,conn,data): self.verbose("Received %s input from %s.", NxN(data.shape), conn.src) self.__dirty = True in_rows, in_cols = data.shape # compute the correct position of the input in the buffer start_row,start_col = self.sheet2matrixidx(*self.inputs[(conn.src.name,conn.src_port)].origin) row_adj,col_adj = conn.src.sheet2matrixidx(0,0) self.debug("origin (row,col) = "+`(start_row,start_col)`) self.debug("adjust (row,col) = "+`(row_adj,col_adj)`) start_row -= row_adj start_col -= col_adj # the maximum bounds max_row,max_col = self.activity.shape self.debug("max_row = %d, max_col = %d" % (max_row,max_col)) self.debug("in_rows = %d, in_cols = %d" % (in_rows,in_cols)) end_row = start_row+in_rows end_col = start_col+in_cols # if the input goes outside the activity, clip it left_clip = -min(start_col,0) top_clip = -min(start_row,0) right_clip = max(end_col,max_col) - max_col bottom_clip = max(end_row,max_row) - max_row start_col += left_clip start_row += top_clip end_col -= right_clip end_row -= bottom_clip self.debug("start_row = %d,start_col = %d" % (start_row,start_col)) self.debug("end_row = %d,end_col = %d" % (end_row,end_col)) self.debug("left_clip = %d" % left_clip) self.debug("right_clip = %d" % right_clip) self.debug("top_clip = %d" % top_clip) self.debug("bottom_clip = %d" % bottom_clip) self.debug("activity shape = %s" % NxN(self.activity.shape)) self.activity[start_row:end_row, start_col:end_col] += data[top_clip:in_rows-bottom_clip, left_clip:in_cols-right_clip]
__all__ = [ "Composer", ]