Advertisement
Guest User

Neural Network Simulator for Blender2.5

a guest
Jul 11th, 2010
506
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 26.98 KB | None | 0 0
  1. #!/usr/bin/python
  2. ## RPython Neural Network - 0.2b
  3. ## by Brett Hartshorn goatman.py@gmail.com
  4. ## License GNU GPL3
  5.  
  6. ## user defined options ##
  7. BLENDER_DIR = '../Desktop/blender25/blender'
  8. ## number of neurons, be careful with large numbers!
  9. COLUMNS = 24
  10. LAYERS = 3
  11. STEM = 4
  12.  
  13. '''
  14. Getting Started:
  15.  
  16.     Tested with Ubuntu Lucid and PyPy 1.3
  17.     (in theory works on Windows, but installing the PyPy toolchain and SDL headers would be a serious pain)
  18.     Why PyPy?  Because Python is too slow to run a simulation with any modest number of neurons.
  19.  
  20.     1. Download PyPy source code - see http://pypy.org
  21.  
  22.     2. Install GCC and SDL headers if you haven't already
  23.         apt-get install build-essential libsdl-dev
  24.  
  25.     3. Make this file executable: "chmod +x rAI.py"
  26.  
  27.     4. Modify the line above BLENDER_DIR to point to your blender25 installation
  28.  
  29.     5. Copy this file to your pypy root directory and run "./rAI.py"
  30.         (you can test just pypy compilation with "./rAI.py --pypy --subprocess")
  31.  
  32. How It Works:
  33.     This program is actually three programs in a single Python script,
  34.     some trickery with command line arguments is used to divide the programs.
  35.     When you run "./rAI.py" the top level begins, opening a GTK window,
  36.     When the drawing-area in the GTK window is realized it calls itself using the
  37.     subprocess module and passing "--pypy --subprocess" on the command line,
  38.     when the script is run this way it imports pypy and translates the simulator
  39.     into C, the SDL_WINDOWID environment variable is used to tell the PyPy
  40.     subprocess to draw into that xwindow ID.
  41.     After the simulation has run, you can dump it to Blender25 by clicking "view model"
  42.     When you do this blender is called with the -P argument pointing to itself (this script)
  43.     The script knows its being run from blender and creates the BlenderExport class
  44.     that handles converting the data.
  45.  
  46. Unfinished Work:
  47.  
  48.     For Blender visualization it would be nice to see which dendrites are polarized.
  49.  
  50.     Realtime Brain Input/Output: a brain sim without any input or output is pretty boring,
  51.         to input spikes into the network provide a function that writes a command to the pipe,
  52.         ( see "spike-all" and "spike-one" )
  53.         for example you could modify this program to open a socket, and then from the
  54.         Blender Game Engine your actuator sends a signal to the socket when something it touched,
  55.         depending on whats touched, the toplevel app will write a command to the pipe that
  56.         the PyPy subprocess is reading.
  57.         Getting output from the network is done the same way, pipe/socket -> client - do something.
  58.         ( note that single neuron spiking gives little information - its better you FFT the spikes into a
  59.         useable pattern that can drive some action )
  60.  
  61.     Skeleton code for learning/training the network, needs alot of work.
  62.  
  63.  
  64.  
  65. -----------------------------------------------------------
  66. PyPy Tips for Coders:
  67.  
  68. math.radians    not available
  69. random.uniform  not available
  70.  
  71. incorrect:
  72.     string.strip()  will not work without an arg
  73.     list.sort()     not available
  74.  
  75. correct:
  76.     string.strip(' ').strip('\n').strip('\t')       #strips all white space
  77.     list = sortd( list )                        # but the JIT prefers TimSort
  78.     list.pop( index )                       # no list.pop() with end as default
  79.  
  80. '''
  81.  
  82.  
  83. import os, sys, time, pickle
  84. import math             # math.radians is missing in pypy?
  85.  
  86. degToRad = math.pi / 180.0
  87. def radians(x):
  88.     """radians(x) -> converts angle x from degrees to radians
  89.     """
  90.     return x * degToRad
  91.  
  92. if '--blender' not in sys.argv:
  93.     from pypy.rlib import streamio
  94.     from pypy.rlib import rpoll
  95.     # apt-get install libsdl-dev
  96.     from pypy.rlib.rsdl import RSDL, RSDL_helper
  97.     from pypy.rlib.rarithmetic import r_uint
  98.     from pypy.rpython.lltypesystem import lltype, rffi
  99.     from pypy.rlib.listsort import TimSort
  100.     from pypy.rlib.jit import hint, we_are_jitted, JitDriver, purefunction_promote
  101.  
  102. #random.randrange(0, up)        # not a replacement for random.uniform
  103. #Choose a random item from range(start, stop[, step]).  
  104. #This fixes the problem with randint() which includes the
  105. #endpoint; in Python this is usually not what you want.
  106.  
  107.  
  108. if '--pypy' in sys.argv:        # random.random works in pypy, but random.uniform is missing?
  109.     from pypy.rlib import rrandom
  110.     RAND = rrandom.Random()
  111.     RAND.init_by_array([1, 2, 3, 4])
  112.     def random(): return RAND.random()
  113.     def uniform(start,end): return ( RAND.random() * (end-start) ) - start
  114. else:
  115.     from random import *
  116.  
  117. def distance( v1, v2 ):
  118.     dx = v1[0] - v2[0]
  119.     dy = v1[1] - v2[1]
  120.     dz = v1[2] - v2[2]
  121.     t = dx*dx + dy*dy + dz*dz
  122.     return math.sqrt( float(t) )
  123.  
  124. if '--blender' not in sys.argv:
  125.     Njitdriver = JitDriver(
  126.         greens = 'cur train times branes last_spike spikers temporal thresh triggers self abs_refactory abs_refactory_value'.split(),
  127.         reds = 'i t a b c bias neuron'.split()
  128.     )
  129. class RecurrentSpikingModel(object):
  130.     '''
  131.     Model runs in realtime and lossy - stores recent
  132.     spikes in a list for realtime learning.
  133.     Uses spike train, with time delay based on distance,        Spikes will trigger absolute refactory period.
  134.     Membrane has simple linear falloff.
  135.  
  136.         notes:
  137.             log(1.0) = 0.0
  138.             log(1.5) = 0.40546510810816438
  139.             log(2.0) = 0.69314718055994529
  140.             log(2.7) = 0.99325177301028345
  141.             log(3.0) = 1.0986122886681098
  142.  
  143.     '''
  144.     def iterate( self ):
  145.         now = float( time.time() )
  146.         self._state_dirty = True; train = self._train
  147.         brane = self._brane; rest = self._rest
  148.         branes = self._branes; temporal = self._temporal
  149.         abs_refactory = self._abs_refactory
  150.         abs_refactory_value = self._abs_refactory_value
  151.         fps = self._fps
  152.         elapsed = now - self._lasttime
  153.         clip = self._clip
  154.         cur = self._lasttime
  155.         last_spike = self._last_spike
  156.         spikers = self._spikers
  157.         thresh = self._thresh
  158.         triggers = self._triggers
  159.  
  160.         ## times of incomming spikes ##
  161.         times = train.keys()
  162.         ## To do, if seziure, lower all connection strengths
  163.         TimSort(times).sort()       # pypy note - list have no .sort(), and JIT dislikes builtin sorted(list)
  164.  
  165.         if not times:
  166.             a = now - self._lasttime
  167.             if a > 0.1: brane = rest
  168.             else:
  169.                 b = a * 10  # 0.0-1.0
  170.                 brane += (rest - brane) * b
  171.             branes.append( (brane,now) )
  172.  
  173.         i = 0
  174.         t = a = b = c = bias = .0
  175.         neuron = self
  176.         ntrain = len(train)
  177.         while train:        #the JIT does only properly support a while loop as the main dispatch loop
  178.             Njitdriver.can_enter_jit(
  179.                 cur=cur, train=train, times=times, branes=branes, last_spike=last_spike, spikers=spikers,
  180.                 temporal=temporal, thresh=thresh, triggers=triggers, self=self,
  181.                 abs_refactory=abs_refactory, abs_refactory_value=abs_refactory_value,
  182.                 i=i, t=t, a=a, b=b, c=c,
  183.                 neuron=neuron, bias=bias
  184.             )
  185.             Njitdriver.jit_merge_point(
  186.                 cur=cur, train=train, times=times, branes=branes, last_spike=last_spike, spikers=spikers,
  187.                 temporal=temporal, thresh=thresh, triggers=triggers, self=self,
  188.                 abs_refactory=abs_refactory, abs_refactory_value=abs_refactory_value,
  189.                 i=i, t=t, a=a, b=b, c=c,
  190.                 neuron=neuron, bias=bias
  191.             )
  192.             ##bias, neuron = train.pop( t ) ## not pypy
  193.             t = times[i]; i += 1
  194.             bias,neuron = train[t]
  195.             del train[t]
  196.  
  197.  
  198.             if t <= cur:
  199.                 #print 'time error'
  200.                 pass
  201.             else:
  202.                 a = t - cur
  203.                 cur += a
  204.                 #print 'delay', a
  205.                 if cur - last_spike < abs_refactory:
  206.                     brane = abs_refactory_value
  207.                     branes.append( (brane,cur) )
  208.                 else:
  209.                     spikers.append( neuron )
  210.                     if a > 0.1:
  211.                         brane = rest + bias
  212.                         branes.append( (brane,cur) )
  213.                     else:
  214.                         b = a * 10  # 0.0-1.0
  215.                         brane += (rest - brane) * b
  216.                         c = b * temporal
  217.                         bias *= math.log( (temporal-c)+2.8 )
  218.                         brane += bias
  219.                         branes.append( (brane,cur) )
  220.  
  221.                         if brane > thresh:
  222.                             triggers.append( neuron )
  223.                             self.spike( cur )
  224.                             brane = abs_refactory_value
  225.                             #fps *= 0.25        # was this to play catch up?
  226.                             break # this is efficient!
  227.  
  228.         #self._train = {}
  229.         self._brane = brane
  230.         #for lst in [branes, spikers, triggers]:    # not allowed in pypy
  231.         while len(branes) > 512: branes.pop(0)      # Adjust this if you run out of memory
  232.         while len(spikers) > clip: spikers.pop(0)
  233.         while len(triggers) > clip: triggers.pop(0)
  234.  
  235.         self._lasttime = end = float(time.time())
  236.         #print ntrain, end-now
  237.  
  238.  
  239.     def detach( self ):
  240.         self._inputs = {}       # time:neuron
  241.         self._outputs = []  # children (neurons)
  242.         self._train = {}
  243.         self._branes = []
  244.         self._spikers = []  # last spikers
  245.         self._triggers = [] # last spikers to cause a spike
  246.  
  247.     def __init__( self, name='neuron', x=.0,y=.0,z=.0, column=0, layer=0, fps=12, thresh=100.0, dendrite_bias=35.0, dendrite_noise=1.0, temporal=1.0, distance_factor=0.1, red=.0, green=.0, blue=.0 ):
  248.         self._name = name
  249.         self._fps = fps     # active fps 10?
  250.         self._thresh = thresh
  251.         self._column = column
  252.         self._layer = layer
  253.         self._brane = self._rest = -65.0
  254.         self._abs_refactory = 0.05
  255.         self._abs_refactory_value = -200.0
  256.         self._spike_value = 200.0
  257.         self._temporal = temporal   # ranges 1.0 - inf
  258.         self._distance_factor = distance_factor
  259.         self._dendrite_bias = dendrite_bias
  260.         self._dendrite_noise = dendrite_noise
  261.         self._clip = 128
  262.         self._learning = False
  263.         self._learning_rate = 0.1
  264.  
  265.         ## the spike train of incomming spikes
  266.         self._train = {}
  267.  
  268.         ## list of tuples, (brane value, abs time)
  269.         ## use this list to render wave timeline ##
  270.         self._branes = []
  271.  
  272.         self._spikers = []  # last spikers
  273.         self._triggers = [] # last spikers to cause a spike
  274.         self._lasttime = time.time()
  275.         self._last_spike = 0
  276.         self._inputs = {}       # time:neuron
  277.         self._outputs = []  # children (neurons)
  278.  
  279.         self._color = [ red, green, blue ]
  280.         #x = uniform( 0.2, 0.8 )
  281.         #y = random()   #uniform( 0.2, 0.8 )
  282.         #z = random()   #uniform( 0.2, 0.8 )
  283.         self._pos = [ x,y,z ]
  284.         self._spike_callback = None
  285.         self._state_dirty = False
  286.         self._active = False
  287.         self._cached_distances = {}
  288.         self._clipped_spikes = 0    # for debugging
  289.  
  290.         self._draw_spike = False
  291.         #self._braneRect = self._spikeRect = None
  292.  
  293.     def randomize( self ):
  294.         for n in self._inputs:
  295.             bias = self._dendrite_bias + uniform( -self._dendrite_noise, self._dendrite_noise )
  296.             self._inputs[ n ] = bias
  297.  
  298.  
  299.     def mutate( self, v ):
  300.         for n in self._spikers:
  301.             self._inputs[ n ] += uniform(-v*2,v*2)
  302.         for n in self._triggers:
  303.             self._inputs[ n ] += uniform(-v,v)
  304.  
  305.         if not self._spikes or not self._triggers:
  306.             for n in self._inputs:
  307.                 self._inputs[ n ] += uniform(-v,v)
  308.  
  309.  
  310.     def reward( self, v ):
  311.         if not self._spikers: print( 'no spikers to reward' )
  312.         for n in self._spikers:
  313.             bias = self._inputs[ n ]
  314.             if abs(bias) < 100:
  315.                 if bias > 15:
  316.                     self._inputs[ n ] += v
  317.                 else:
  318.                     self._inputs[ n ] -= v
  319.            
  320.  
  321.     def punish( self, v ):
  322.         for n in self._inputs:
  323.             self._inputs[n] *= 0.9
  324.            
  325.         for n in self._spikers:
  326.             self._inputs[ n ] += uniform( -v, v )
  327.  
  328.  
  329.  
  330.     def attach_dendrite( self, neuron ):
  331.         bias = self._dendrite_bias + uniform( -self._dendrite_noise, self._dendrite_noise )
  332.         if random()*random() > 0.5: bias = -bias
  333.         # add neuron to input list
  334.         if neuron not in self._inputs:
  335.             self._inputs[ neuron ] = bias
  336.             #print 'attached neuron', neuron, bias
  337.         if self not in neuron._outputs:
  338.             neuron._outputs.append( self )
  339.             neuron.update_distances()
  340.         return bias
  341.  
  342.     def update_distances( self ):
  343.         for child in self._outputs:
  344.             dist = distance( self._pos, child._pos )
  345.             self._cached_distances[ child ] = dist
  346.  
  347.     def spike( self, t ):
  348.         #print 'spike', t
  349.         self._draw_spike = True
  350.         self._last_spike = t
  351.         self._branes.append( (self._spike_value,t) )
  352.         self._brane = self._abs_refactory_value
  353.         self._branes.append( (self._brane,t) )
  354.         if self._learning and self._triggers:
  355.             #print 'learning'
  356.             n = self._triggers[-1]
  357.             bias = self._inputs[ n ]
  358.             if bias > 0: self._inputs[n] += self._learning_rate
  359.             else: self._inputs[n] -= self._learning_rate
  360.  
  361.         if self._spike_callback:
  362.             self._spike_callback( t )
  363.  
  364.         for child in self._outputs:
  365.             #print 'spike to', child
  366.             bias = child._inputs[ self ]
  367.             #dist = distance( self._pos, child._pos )
  368.             dist = self._cached_distances[ child ]
  369.             dist *= self._distance_factor
  370.             child._train[ t+dist ] = (bias,self)
  371.  
  372.     def stop( self ):
  373.         self._active = False
  374.         print( 'clipped spikes', self._clipped_spikes )
  375.     def start( self ):
  376.         self._active = True
  377.         self.iterate()
  378.  
  379.     def setup_draw( self, format, braneRect, groupRect, spikeRect, colors ):
  380.         self._braneRect = braneRect
  381.         self._groupRect = groupRect
  382.         self._spikeRect = spikeRect
  383.         self._sdl_colors = colors
  384.         r,g,b = self._color
  385.         self._group_color = RSDL.MapRGB(format, int(r*255), int(g*255), int(b*255))
  386.  
  387.     def draw( self, surf ):
  388.         #if self._braneRect:
  389.         fmt = surf.c_format
  390.         b = int(self._brane * 6)
  391.         if b > 255: b = 255
  392.         elif b < 0: b = 0
  393.         color = RSDL.MapRGB(fmt, 0, 0, b)
  394.         RSDL.FillRect(surf, self._braneRect, color)
  395.         RSDL.FillRect(surf, self._groupRect, self._group_color)
  396.         if self._draw_spike:
  397.             RSDL.FillRect(surf, self._spikeRect, self._sdl_colors['white'])
  398.         else:
  399.             RSDL.FillRect(surf, self._spikeRect, color )#self._sdl_colors['black'])
  400.         self._draw_spike = False
  401.  
  402.     def dump_model( self, brain ):
  403.         #a = ''
  404.         x,y,z = self._pos
  405.         a = '{ "pos" : (%s, %s, %s,), ' %(x,y,z)        # self._pos  not allowed in pypy, unpack tuple first
  406.         b = ''
  407.         for brane,seconds in self._branes: b += '(%s,%s),' %(brane,seconds)
  408.         a += ' "anim" : ( %s ), ' %b
  409.         b = ''
  410.         for n in self._outputs:
  411.             idx = brain.get_neuron_index( n )
  412.             b += '%s,' %idx
  413.         a += ' "outputs" : ( %s ) }' %b
  414.         return a
  415.  
  416.  
  417.  
  418. class Brain( object ):
  419.     def loop( self ):
  420.         self._active = True
  421.         fmt = self.screen.c_format
  422.         RSDL.FillRect(self.screen, lltype.nullptr(RSDL.Rect), self.ColorGrey)
  423.         layers = self._layers
  424.         neurons = self._neurons
  425.         pulse_layers = self._pulse_layers
  426.         screen = self.screen
  427.         loops = 0  
  428.         now = start = float( time.time() )
  429.         while self._active:
  430.             #Bjitdriver.can_enter_jit( layers=layers, neurons=neurons, pulse_layers=pulse_layers, loops=loops )
  431.             #Bjitdriver.jit_merge_point( layers=layers, neurons=neurons, pulse_layers=pulse_layers, loops=loops)
  432.             now = float( time.time() )
  433.             self._fps = loops / float(now-start)
  434.             for i,lay in enumerate(self._layers):
  435.                 if self._pulse_layers[i] and False:
  436.                     #print 'pulse layer: %s neurons: %s ' %(i, len(lay))
  437.                     for n in lay:
  438.                         if random()*random() > 0.8:
  439.                             n.spike( now )
  440.             for i,col in enumerate(self._columns):
  441.                 if self._pulse_columns[i]:
  442.                     for n in col: n.spike(now)
  443.             for n in self._neurons:
  444.                 n.iterate()
  445.                 n.draw(self.screen)
  446.             #r,w,x = rpoll.select( [self._stdin], [], [], 1 )   # wait
  447.             rl,wl,xl = rpoll.select( [0], [], [], 0.000001 )    # wait
  448.             if rl:
  449.                 cmd = self._stdin.readline().strip('\n').strip(' ')
  450.                 self.do_command( cmd )
  451.             loops += 1
  452.             self._iterations = loops
  453.             #print loops        # can not always print in mainloop, then select can never read from stdin
  454.             RSDL.Flip(self.screen)
  455.             #self._fps = float(time.time()) - now
  456.         #return loops
  457.         return 0
  458.  
  459.     def __init__(self):
  460.         start = float(time.time())
  461.         self._neurons = []
  462.         self._columns = []
  463.         self._layers = [ [] ] * LAYERS
  464.         self._pulse_layers = [0] * LAYERS
  465.         self._pulse_layers[ 0 ] = 1
  466.  
  467.         self._pulse_columns = [0] * COLUMNS
  468.         self._pulse_columns[ 0 ] = 1
  469.         self._pulse_columns[ 1 ] = 1
  470.         self._pulse_columns[ 2 ] = 1
  471.         self._pulse_columns[ 3 ] = 1
  472.  
  473.  
  474.         inc = 360.0 / COLUMNS
  475.         scale = float( LAYERS )
  476.         expansion = 1.333
  477.         linc = scale / LAYERS
  478.         for column in range(COLUMNS):
  479.             colNeurons = []
  480.             self._columns.append( colNeurons )
  481.             X = math.sin( radians(column*inc) )
  482.             Y = math.cos( radians(column*inc) )
  483.             expanding = STEM
  484.             width = 1.0 / scale
  485.             for layer in range(LAYERS):
  486.                 Z = layer * linc
  487.                 r = random() * random()
  488.                 g = 0.2
  489.                 b = 0.2
  490.                 for i in range(int(expanding)):
  491.                     x = uniform( -width, width )
  492.                     rr = random()*random()      # DJ's trick
  493.                     y = uniform( -width*rr, width*rr ) + X
  494.                     z = Z + Y
  495.                     # create 50/50 exitatory/inhibitory
  496.                     n = RecurrentSpikingModel(x=x, y=y, z=z, column=column, layer=layer, red=r, green=g, blue=b )
  497.                     self._neurons.append( n )
  498.                     colNeurons.append( n )
  499.                     self._layers[ layer ].append( n )
  500.  
  501.                 expanding *= expansion
  502.                 width *= expansion
  503.  
  504.         dendrites = 0
  505.         interlayer = 0
  506.         for lay in self._layers:
  507.             for a in lay:
  508.                 for b in lay:
  509.                     if a is not b and a._column == b._column:
  510.                         a.attach_dendrite( b )
  511.                         dendrites += 1
  512.                         interlayer += 1
  513.  
  514.         intercol = 0
  515.         for col in self._columns:
  516.             for a in col:
  517.                 for b in col:
  518.                     if a is not b and random()*random() > 0.75:
  519.                         a.attach_dendrite( b )
  520.                         intercol += 1
  521.                         dendrites += 1
  522.  
  523.         intercore = 0
  524.         core = self._layers[-1]
  525.         for a in core:
  526.             for b in core:
  527.                 if a is not b and random()*random() > 0.85:
  528.                     a.attach_dendrite( b )
  529.                     intercore += 1
  530.                     dendrites += 1
  531.  
  532.         print( 'brain creation time (seconds)', float(time.time())-start )
  533.         print( 'neurons per column', len(self._columns[0]) )
  534.         print( 'inter-layer dendrites', interlayer )
  535.         print( 'inter-column dendrites', intercol )
  536.         print( 'inter-neocoretex dendrites', intercore )
  537.         print( 'total dendrites', dendrites )
  538.         print( 'total neurons', len(self._neurons) )
  539.         for i,lay in enumerate(self._layers):
  540.             print( 'layer: %s   neurons: %s' %(i,len(lay)) )
  541.         for i,col in enumerate(self._columns):
  542.             print( 'column: %s  neurons: %s' %(i,len(col)) )
  543.  
  544.  
  545.  
  546.         self._stdin = streamio.fdopen_as_stream(0, 'r', 1)
  547.         #self._stdout = streamio.fdopen_as_stream(1, 'w', 1)
  548.         #self._stderr = streamio.fdopen_as_stream(2, 'w', 1)
  549.  
  550.         self._width = 640; self._height = 480
  551.         assert RSDL.Init(RSDL.INIT_VIDEO) >= 0
  552.         self.screen = RSDL.SetVideoMode(self._width, self._height, 32, 0)
  553.         assert self.screen
  554.         fmt = self.screen.c_format
  555.         self.ColorWhite = white = RSDL.MapRGB(fmt, 255, 255, 255)
  556.         self.ColorGrey = grey = RSDL.MapRGB(fmt, 128, 128, 128)
  557.         self.ColorBlack = black = RSDL.MapRGB(fmt, 0, 0, 0)
  558.         self.ColorBlue = blue = RSDL.MapRGB(fmt, 0, 0, 200)
  559.  
  560.         colors = {'white':white, 'grey':grey, 'black':black, 'blue':blue}
  561.  
  562.         x = 1; y = 1
  563.         for i,n in enumerate(self._neurons):
  564.             braneRect = RSDL_helper.mallocrect(x, y, 12, 12)
  565.             groupRect = RSDL_helper.mallocrect(x, y, 12, 2)
  566.             spikeRect = RSDL_helper.mallocrect(x+4, y+4, 4, 4)
  567.             n.setup_draw( self.screen.c_format, braneRect, groupRect, spikeRect, colors )
  568.             x += 13
  569.             if x >= self._width-14:
  570.                 x = 1
  571.                 y += 13
  572.  
  573.     def do_command( self, cmd ):
  574.         if cmd == 'spike-all':
  575.             t = float(time.time())
  576.             for n in self._neurons: n.spike(t)
  577.         elif cmd == 'spike-one':
  578.             t = float(time.time())
  579.             self._neurons[0].spike(t)
  580.         elif cmd == 'spike-column':
  581.             t = float(time.time())
  582.             for n in self._columns[0]:
  583.                 n.spike(t)
  584.         elif cmd == 'info':
  585.             info = self.info()
  586.             #sys.stderr.write( info )
  587.             #sys.stderr.flush()
  588.             print( info )
  589.         elif cmd == 'view-model':
  590.             a = ''
  591.             for n in self._neurons: a += n.dump_model( self ) + ','
  592.             print( '<view_model> ( %s )' %a )
  593.  
  594.     def info(self):
  595.         r = ' "num-layers": %s,' %len(self._layers)
  596.         r += ' "num-neurons": %s,' %len(self._neurons)
  597.         r += ' "fps" : %s, ' %self._fps
  598.         r += ' "iterations" : %s, ' %self._iterations
  599.         return '<load_info> { %s }' %r
  600.  
  601.     def get_neuron_index( self, n ): return self._neurons.index( n )
  602.  
  603.  
  604.  
  605.  
  606. import subprocess, select, time
  607. if '--blender' not in sys.argv: import gtk, glib
  608.  
  609. class App:
  610.     def load_info( self, arg ): print( arg )
  611.     def view_model( self, arg ):
  612.         pickle.dump( arg, open('/tmp/brain.data','wb'), -1 )
  613.         os.system( '%s -P rAI.py --blender' %BLENDER_DIR )
  614.  
  615.     def __init__(self):
  616.         self._commands = cmds = []
  617.         self.win = gtk.Window()
  618.         self.win.connect('destroy', lambda w: gtk.main_quit())
  619.         self.root = gtk.VBox(False,10); self.win.add( self.root )
  620.         self.root.set_border_width(20)
  621.         self.header = header = gtk.HBox()
  622.         self.root.pack_start( header, expand=False )
  623.         b = gtk.Button('spike all neurons')
  624.         b.connect('clicked', lambda b,s: s._commands.append('spike-all'), self )
  625.         self.header.pack_start( b, expand=False )
  626.  
  627.         b = gtk.Button('spike one neuron')
  628.         b.connect('clicked', lambda b,s: s._commands.append('spike-one'), self )
  629.         self.header.pack_start( b, expand=False )
  630.  
  631.         b = gtk.Button('spike column 1')
  632.         b.connect('clicked', lambda b,s: s._commands.append('spike-column'), self )
  633.         self.header.pack_start( b, expand=False )
  634.  
  635.         b = gtk.Button('view model')
  636.         b.connect('clicked', lambda b,s: s._commands.append('view-model'), self )
  637.         self.header.pack_start( b, expand=False )
  638.  
  639.         self.header.pack_start( gtk.SeparatorMenuItem() )
  640.  
  641.         b = gtk.Button('debug')
  642.         b.connect('clicked', lambda b,s: s._commands.append('info'), self )
  643.         self.header.pack_start( b, expand=False )
  644.  
  645.         da = gtk.DrawingArea()
  646.         da.set_size_request( 640,480 )
  647.         da.connect('realize', self.realize)
  648.         self.root.pack_start( da )
  649.  
  650.         self._read = None
  651.         glib.timeout_add( 33, self.loop )
  652.         self.win.show_all()
  653.  
  654.  
  655.     def realize(self, da ):
  656.         print( 'gtk drawing area realize' )
  657.         xid = da.window.xid
  658.         self._process = process = subprocess.Popen( 'python rAI.py --pypy --subprocess %s' %xid, stdin=subprocess.PIPE, stdout=subprocess.PIPE, bufsize=32, shell=True )
  659.         self._write = write = process.stdin
  660.         self._read = read = process.stdout
  661.         print( 'read pipe', read )
  662.         print( 'read write', write )
  663.  
  664.     def loop( self ):
  665.         if self._read:
  666.             rlist,wlist,xlist = select.select( [self._read], [], [], 0.001 )
  667.             while self._commands:
  668.                 cmd = self._commands.pop()
  669.                 print( 'sending cmd ->', cmd )
  670.                 self._write.write( '%s\n'%cmd )
  671.                 self._write.flush()
  672.             if rlist:
  673.                 a = self._read.readline().strip()
  674.                 if a:
  675.                     print( a )
  676.                     if a.startswith('<'):
  677.                         func = a[ 1 : a.index('>') ]
  678.                         arg = a[ a.index('>')+1 : ].strip()
  679.                         func = getattr(self, func)
  680.                         func( eval(arg) )
  681.         return True
  682.  
  683. class BlenderExport(object):
  684.     #bpy.ops.anim.change_frame( i )     # can not be used from the command line, invalid context
  685.     #mat.diffuse_color.r = 0.1
  686.     #mat.keyframe_insert('diffuse_color')
  687.  
  688.     def animate_material( self, mat, anim ):
  689.         mat.keyframe_insert('emit')
  690.         start = anim[0][1]
  691.         ecurve = mat.animation_data.action.fcurves[0]
  692.         i = 0
  693.         for brane,seconds in anim:
  694.             t = seconds-start
  695.             t *= 100
  696.             if brane < 99: v = (brane+80) * .01
  697.             else: v = 50
  698.             bez = ecurve.keyframe_points.add( frame=t, value=v )
  699.             i += 1
  700.            
  701.     def create_taper_curve( self, thickness=20.0, steps=3 ):
  702.         # the Y+ defines the tappering
  703.         data = bpy.data.curves.new(name='dendriteTaper', type='CURVE')
  704.         spline = data.splines.new('BEZIER')
  705.         #spline.bezier_points.add()     # new spline always has one bez
  706.         x = .0; y=0.5 * thickness; z = .0
  707.         bez = spline.bezier_points[-1]
  708.         bez.co.x = x; bez.co.y = y; bez.co.z = z
  709.         bez.handle1.x = x + 0.1
  710.         bez.handle1.y = y / 2
  711.         bez.handle1.z = z
  712.         bez.handle2.x = x + 0.1
  713.         bez.handle2.y = y / 2
  714.         bez.handle2.z = z
  715.  
  716.         if 0:
  717.             inc = 1.0 / steps
  718.             x = inc
  719.             for i in range(steps):
  720.                 spline.bezier_points.add()
  721.                 y= (0.1 * thickness) + uniform(.0,0.01)
  722.                 bez = spline.bezier_points[-1]
  723.                 bez.co.x = x; bez.co.y = y; bez.co.z = z
  724.                 bez.handle1.x = x
  725.                 bez.handle1.y = y
  726.                 bez.handle1.z = z
  727.                 bez.handle2.x = x + inc
  728.                 bez.handle2.y = y
  729.                 bez.handle2.z = z
  730.                 x += inc
  731.  
  732.         spline.bezier_points.add()
  733.         x = 1.0; y=0.05 * thickness
  734.         bez = spline.bezier_points[-1]
  735.         bez.co.x = x; bez.co.y = y; bez.co.z = z
  736.         bez.handle1.x = x - 0.5
  737.         bez.handle1.y = y
  738.         bez.handle1.z = z
  739.         bez.handle2.x = x - 0.5
  740.         bez.handle2.y = y
  741.         bez.handle2.z = z
  742.  
  743.         obj = bpy.data.objects.new(name='dendriteTaper', object_data=data)
  744.         bpy.context.scene.objects.link(obj)
  745.         return obj
  746.  
  747.     def __init__(self):
  748.         brain = pickle.load( open('/tmp/brain.data','rb') )
  749.         steps = 5
  750.         self._neuron_cell_bodies = ncb = []
  751.         self._neuron_materials = mats = []
  752.  
  753.         for i,n in enumerate(brain):
  754.             print (len(brain)-i)
  755.  
  756.             data = bpy.data.curves.new(name='brain', type='CURVE')
  757.             data.taper_object = self.create_taper_curve()
  758.             data.dimensions = '3D'
  759.             data.resolution_u = 3       # 6
  760.             data.bevel_depth = 0.001
  761.             data.front = False; data.back = False
  762.             obj = bpy.data.objects.new(name='dendrites', object_data=data)
  763.             bpy.context.scene.objects.link(obj)
  764.  
  765.             mat = bpy.data.materials.new('neuronMat')
  766.             mat.diffuse_color.r = uniform( 0.6,1.0 )
  767.             mat.diffuse_color.g = uniform( 0.6,1.0 )
  768.             mat.diffuse_color.b = uniform( 0.6,1.0 )
  769.  
  770.             obj.active_material = mat
  771.             mats.append( mat )
  772.             self.animate_material( mat, n['anim'] )
  773.             #print( dir(data) )
  774.             #data.materials.add( mat )
  775.             #print (len(data.materials))
  776.             x,y,z = n['pos']
  777.             bpy.ops.mesh.primitive_ico_sphere_add() # does not return mesh
  778.             for ob in bpy.data.objects:
  779.                 if ob.name.startswith('Icosphere') and ob not in ncb:
  780.                     ncb.append( ob )
  781.                     ob.location.x = x
  782.                     ob.location.y = y
  783.                     ob.location.z = z
  784.                     ob.scale.x = ob.scale.y = ob.scale.z = .03
  785.                     ob.selected = True
  786.                     bpy.ops.object.shade_smooth()
  787.                     ob.data.add_material( mat )
  788.  
  789.                     for vert in ob.data.verts:
  790.                         if random() > 0.3:
  791.                             p = uniform(1.0,1.5)
  792.                             vert.co.x *= p
  793.                             vert.co.y *= p
  794.                             vert.co.z *= p
  795.                     break
  796.             for dendrite in n['outputs']:
  797.  
  798.                 spline = data.splines.new('BEZIER')
  799.                 #spline.bezier_points.add()     # new spline always has one bez
  800.                 bez = spline.bezier_points[-1]
  801.                 bez.co.x = x; bez.co.y = y; bez.co.z = z
  802.                 bez.handle1.x = x
  803.                 bez.handle1.y = y
  804.                 bez.handle1.z = z
  805.                 bez.handle2.x = x + uniform(-.1,.1)
  806.                 bez.handle2.y = y + uniform(-.1,.1)
  807.                 bez.handle2.z = z + uniform(-.1,.1)
  808.                
  809.                 dx,dy,dz = brain[ dendrite ]['pos']
  810.                 inc = 1.0 / steps
  811.                 m = inc
  812.                 a = 0.05
  813.                 for step in range(steps):
  814.                     mx = x + ((dx-x)*uniform(m-a,m+a))
  815.                     my = y + ((dy-y)*uniform(m-a,m+a))
  816.                     mz = z + ((dz-z)*uniform(m-a,m+a))
  817.                     spline.bezier_points.add()
  818.                     bez = spline.bezier_points[-1]
  819.                     bez.co.x = mx; bez.co.y = my; bez.co.z = mz
  820.                     bez.handle1.x = mx + uniform(-.1,.1)
  821.                     bez.handle1.y = my + uniform(-.1,.1)
  822.                     bez.handle1.z = mz + uniform(-.1,.1)
  823.                     bez.handle2.x = mx + uniform(-.1,.1)
  824.                     bez.handle2.y = my + uniform(-.1,.1)
  825.                     bez.handle2.z = mz + uniform(-.1,.1)
  826.                     m += inc
  827.  
  828.                 spline.bezier_points.add()
  829.                 bez = spline.bezier_points[-1]
  830.                 bez.co.x = dx; bez.co.y = dy; bez.co.z = dz
  831.                 bez.handle1.x = dx
  832.                 bez.handle1.y = dy
  833.                 bez.handle1.z = dz
  834.                 bez.handle2.x = dx + uniform(-.1,.1)
  835.                 bez.handle2.y = dy + uniform(-.1,.1)
  836.                 bez.handle2.z = dz + uniform(-.1,.1)
  837.  
  838.  
  839.  
  840. if '--subprocess' in sys.argv:
  841.     os.putenv('SDL_WINDOWID', sys.argv[-1])
  842.     def pypy_entry_point():
  843.         #def jitpolicy(*args):
  844.         #   from pypy.jit.metainterp.policy import JitPolicy
  845.         #   return JitPolicy()
  846.  
  847.         brain = Brain()
  848.         brain.loop()
  849.     if '--pypy' in sys.argv:
  850.         from pypy.translator.interactive import Translation
  851.         t = Translation( pypy_entry_point )
  852.         ## NotImplementedError: --gcrootfinder=asmgcc requires standalone ##
  853.         #t.config.translation.suggest(jit=True, jit_debug='steps', jit_backend='x86', gc='boehm')
  854.         t.annotate()
  855.         t.rtype()
  856.         f = t.compile_c()
  857.         f()
  858.     else:
  859.         pypy_entry_point()
  860.  
  861. else:
  862.     if '--blender' in sys.argv:
  863.         import bpy
  864.         BlenderExport()
  865.  
  866.     else:
  867.         a = App()
  868.         gtk.main()
  869.         print( '-------------------exit toplevel-----------------' )
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement