Package cells :: Module synapse
[hide private]
[frames] | no frames]

Source Code for Module cells.synapse

  1  # PyCells: Automatic dataflow management for Python 
  2  # Copyright (C) 2006, Ryan Forsythe 
  3   
  4  # This library is free software; you can redistribute it and/or 
  5  # modify it under the terms of the GNU Lesser General Public 
  6  # License as published by the Free Software Foundation; either 
  7  # version 2.1 of the License, or (at your option) any later version. 
  8  # See LICENSE for the full license text. 
  9   
 10  # This library is distributed in the hope that it will be useful, 
 11  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 12  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
 13  # Lesser General Public License for more details. 
 14   
 15  # You should have received a copy of the GNU Lesser General Public 
 16  # License along with this library; if not, write to the Free Software 
 17  # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA 
 18   
 19  """ 
 20  Synapses, cell variants which exist only within C{L{RuleCell}}s and 
 21  which mediate the propogation of another cell's value. For instance, a 
 22  cell C{a} could use cell C{b}'s value, but only if it had changed more 
 23  than 5% since the last time C{a} used it. 
 24   
 25  @var DEBUG: Turns on debugging messages for the synapse module. 
 26  """ 
 27   
 28  import cells, cell 
 29   
 30  DEBUG = False 
 31   
32 -def debug(*msgs):
33 msgs = list(msgs) 34 msgs.insert(0, "synapse".rjust(cells._DECO_OFFSET) + " > ") 35 if DEBUG or cells.DEBUG: 36 print " ".join(msgs)
37
38 -class Synapse(cell.Cell):
39 """ 40 A very specialized Cell variant. Synapses are filters for 41 Cells. They can be applied to any type of Cell, and they simply 42 process the cell to build a value which is provided to dependent 43 cells as the filtered cell's value. They live within the cell 44 which defines them, and as such are only referenceable in that 45 rule. 46 """ 47 initialized = False 48
49 - def __new__(cls, owner, name=None, **kwargs):
50 """ 51 Create a new synapse instance within the calling Cell, if 52 neccessary. 53 54 @param cls: Class this synapse is being called from. 55 56 @param owner: Model instance this synapse is being created in 57 / retrieved from 58 59 @param name: Name of the synapse to retrieve; used as a lookup 60 on the enclosing Cell's synapse space. 61 62 @param kwargs: standard C{L{Cell}} keyword arguments. 63 """ 64 # first, check to see if there's already a synapse with this name in 65 # the owner Cell 66 if not owner.synapse_space.has_key(name): # and if there isn't 67 # make one in the owner 68 debug("building new synapse '" + name + "' in", str(owner)) 69 owner.synapse_space[name] = cell.Cell.__new__(cls, owner, 70 name=name, **kwargs) 71 72 # finally, return the owner's synapse 73 return owner.synapse_space[name]
74
75 - def __init__(self, owner, name=None, **kwargs):
76 """ 77 Initialize the synapse Cell, if neccessary. 78 79 @param owner: The model instance to pass to this synapse's rule 80 81 @param name: This synapse's name 82 83 @param kwargs: Standard C{L{Cell}} keyword arguments 84 """ 85 # at this point we're guaranteed to have a Synapse in the 86 # owner, and self points at that Synapse. We don't know if 87 # it's been initialized, though. so: 88 if not self.initialized: 89 debug("(re)initializing", name) 90 cell.Cell.__init__(self, owner, name=name, **kwargs) 91 self.initialized = True
92
93 - def __call__(self):
94 """ 95 Run C{L{Cell.get}(self)} when a synapse is called as a function. 96 """ 97 return self.getvalue()
98
99 - def run(self):
100 """ 101 Slightly modified version of C{L{Cell.run}()}. 102 """ 103 debug(self.name, "running") 104 # call stack manipulation 105 oldcurr = cells.cellenv.curr 106 cells.cellenv.curr = self 107 108 # the rule run may rewrite the dep graph; prepare for that by nuking 109 # c-b links to this cell and calls links from this cell: 110 for cell in self.calls_list(): 111 debug(self.name, "removing c-b link from", cell.name) 112 cell.remove_cb(self) 113 self.reset_calls() 114 115 self.dp = cells.cellenv.dp # we're up-to-date 116 newvalue = self.rule(self.owner, self.value) # run the rule 117 self.bound = True 118 119 # restore old running cell 120 cells.cellenv.curr = oldcurr 121 122 # return changed status 123 if self.unchanged_if(self.value, newvalue): 124 debug(self.name, "unchanged.") 125 return False 126 else: 127 debug(self.name, "changed.") 128 self.last_value = self.value 129 self.value = newvalue 130 131 return True
132
133 - def rule(self, owner, oldvalue):
134 return None
135
136 -class ChangeSynapse(Synapse):
137 """A very simple filter. Only returns the new value when it's 138 changed by the passed delta 139 """
140 - def __init__(self, owner, name=None, read=None, delta=None, **kwargs):
141 debug("init'ing ChangeSynapse") 142 if not self.initialized: 143 self.readvar, self.delta = read, delta 144 Synapse.__init__(self, owner, name=name, **kwargs) 145 self.rule = self.synapse_rule
146
147 - def synapse_rule(self, owner, oldvalue):
148 debug("running ChangeSynapse rule") 149 newval = self.readvar.getvalue() 150 if not oldvalue or abs(newval - oldvalue) > self.delta: 151 debug("returning new value", str(newval)) 152 return newval 153 else: 154 debug("returning old value", str(oldvalue)) 155 return oldvalue
156