root/trunk/examples/retina/retina.py

Revision 486, 12.0 KB (checked in by mpereira, 7 months ago)

major improvements of SpikeTrain.instantaneous_rate()

  • Property svn:keywords set to Id
Line 
1#!/usr/bin/env python
2# -*- coding: utf8 -*-
3"""
4
5retina.py
6=========
7
8The retina for 'benchmark one'. This should feed the 'Hyper-Column' (see
9https://facets.kip.uni-heidelberg.de/private/wiki/index.php/V1_hypercolumn )
10
11
12For this retina, it consists of 2 layers of neurons on a rectangular
13grid connected in a one to one fashion. Here, we more use primate  'Phasic'
14responses originate with morphologically larger ganglion cell types with fast
15optic nerve fiber conduction velocities (~4 m/s, Gouras, 1969). Microelectrodes
16staining of such cells shows that they are 'parasol' types (Dacey and Lee, 1994).
17ON types branch low in the inner plexiform layer (sublamina b), while OFF types
18branch high in the inner plexiform layer (sublamina a) following the classic
19branching pattern for ON and OFF center cells (Nelson et al, 1978; Dacey and Lee,
201994). Phasic cells are often referred to as the 'magnocellular' or 'M-cell'
21pathway because their fibers terminate in the magnocellular layer of the lateral
22geniculate nucleus of the thalamus. Near the fovea receptive fields of phasic
23cells are 2-3 times larger than those of tonic cells and may be 10 times larger
24in peripheral retina.
25
26The data times outputted by the model are the input to the LGN (
27http://en.wikipedia.org/wiki/Lateral_geniculate_nucleus ). Time for travelling
28through the retina being compensated :
29
30
31@article{Stanford87,
32    Author = {Stanford, L R},
33    Journal = {Science},
34    Month = {Oct},
35    Number = {4825},
36    Pages = {358-360},
37    Title = {Conduction velocity variations minimize conduction time differences
38    among retinal ganglion cell axons},
39    Volume = {238},
40    Year = {1987}}
41
42To remember (in the cat) 5° of visual angle ~ 1 mm of retina
43
44See :
45Data for parameters http://webvision.med.utah.edu/GCPHYS1.HTM (TODO LUP: define
46different sets for different animals (cat, monkey, human))
47Morphology : http://webvision.med.utah.edu/GC1.html
48Topics on CVonline http://homepages.inf.ed.ac.uk/cgi/rbf/CVONLINE/phase3entries.pl?TAG59
49
50TODO (LuP) : use Ringach 07 for setting the neurons centers
51TODO (LuP) : the grid is rectangular, but should be hexagonal / log-polar conformation
52/ define boudaries in biological coordinates
53
54from scipy.interpolate import interpolate
55from numpy.random import randn
56from numpy import *
57
58data = arange(16)
59data = data+1
60data = data.reshape(4,4)
61xrange = arange(4)
62yrange = arange(4)
63X,Y = meshgrid(xrange,yrange)
64
65outgrid = interpolate.interp2d(X,Y,data,kind='linear')
66xi = array([0,0.5,1,1.5,2,2.5,3])
67yi = xi
68
69z = outgrid(xi,yi)
70
71
72
73TODO (LuP) : allow the use of moving images /
74TODO (LuP) : justify or not SFA (since we are interested in synchrony effect, we should
75rather use a simpler model) / noise model
76TODO (LuP) : use real delays
77TODO (LuP) : get significative statistics to the retina into that file
78TODO (Lup) : use another cell type?
79
80TODO (Lup) : use  nest2 definitively
81
82$ Id $
83
84"""
85import datetime
86
87import pyNN.nest2 as sim
88from pyNN.utility import Timer
89from NeuroTools.signals import load_spikelist
90import os, tempfile
91import numpy
92from NeuroTools.parameters import ParameterSet
93
94
95class Retina(object):
96    """
97    Model class for the retina.
98
99    """
100    def __init__(self,N=1000):
101        """
102        Default parameters for the retina of size NxN.
103
104        Sets up parameters and the whole structure of the dictionary / HDF file in url.
105        It contains all relevant parameters and stores them to a dictionary for
106         clarity &future compatibility with XML exports.
107
108        """
109        #try :
110        #    url = "https://neuralensemble.org/svn/NeuroTools/trunk/examples/retina/retina.param"
111        #    self.params = ParameterSet(url)
112        #    print "Loaded parameters from SVN"
113        #except :
114        params = {} # a dictionary containing all parameters
115        # === Define parameters ========================================================
116        # LUP: get running file name and include script in HDF5?
117
118        params = {'description' : 'default retina',
119            'N': N, # integer;  square of total number of Ganglion Cells LUP: how do we include types and units in parameters? (or by default it is a float in ISO standards) TODO: go rectangular
120            'N_ret': .2, # float;  diameter of Ganglion Cell's RF (max: 1)
121            'K_ret': 4.0, # float; ratio of center vs. surround in DOG
122            'dt'         : 0.1,# discretization step in simulations (ms)
123            'simtime'    : 40000*0.1,      # float; (ms)
124            'syn_delay'  : 1.0,         # float; (ms)
125            'noise_std' : 5.0,       # (nA) standard deviation of the internal noise
126            'snr' : 2.0, # (nA) maximum signal
127            'weight'     : 1.0, #
128            #'threads' : 2, 'kernelseeds' : [43210987, 394780234],      # array with one element per thread
129            #'threads' : 1,
130            'kernelseed' : 4321097,       # array with one element per thread
131            # seed for random generator used when building connections
132            'connectseed' : 12345789,  # seed for random generator(s) used during simulation
133            'initialized' : datetime.datetime.now().isoformat() # the date in ISO 8601 format to avoid overriding old simulations
134        }
135
136        # retinal neurons parameters
137        params['parameters_gc'] = {'Theta':-57.0, 'Vreset': -70.0,'Vinit': -70.0,
138        'TauR': 0.5, 'gL':28.95,
139        'C':289.5, 'V_reversal_E': 0.0, 'V_reversal_I': -75.0, 'TauSyn_E':1.5,
140        'TauSyn_I': 10.0, 'V_reversal_sfa': -70.0, 'q_sfa': 0., #14.48,
141        'Tau_sfa':110.0, 'V_reversal_relref': -70.0, 'q_relref': 3214.0,
142        'Tau_relref': 1.97}#,'python':True}
143
144        ## default input image # TODO add start and stop time
145        # define the center of every neuron in normalized visual angle / retinal space
146
147        #X,Y = numpy.meshgrid(numpy.linspace(-N/2, N/2,N),numpy.linspace(-N/2,N/2,N))
148        X,Y = numpy.random.rand(N)*2-1, numpy.random.rand(N)*2 -1
149
150        # Generate a DOG excitation on the input layer of the GC
151        # Based on the assumptions of the DOG model (Enroth-Cugell and Robson, 1966) that ganglion cells linearly add signals from both center and surround mechanisms for all points in space
152        # this is the impulse response to a discrete dirac in the center to some specific luminance / excentricity value
153        #   easy : extend to input images (simply by convoluting the image with this kernel)
154        #   hard : extend to time varrying movies (not only a step)
155        params['position'] = [X,Y]
156        R2= X**2 + Y**2
157        N, N_ret, K_ret = params['N'], params['N_ret'], params['K_ret']
158        amplitude = (numpy.exp(-R2 / ( 2 * N_ret**2) )  - 1/K_ret**2 * numpy.exp(-R2 / ( 2 *  N_ret**2 * K_ret**2) )) / (1  - 1/K_ret**2)
159        #amplitude *=  params['noise_std'] # scaled by the noise variance
160        #file.setStructure({'amplitude' : amplitude }, "/build", createparents=True)
161        params['amplitude'] = amplitude
162
163        self.params =  ParameterSet(params)
164            #self.params.save('file://' + os.getcwd() + '/retina.param')
165
166
167    def run(self,params,verbose=True):
168        """
169        params are the parameters to use
170
171        """
172        tmpdir = tempfile.mkdtemp()
173        myTimer = Timer()
174        # === Build the network ========================================================
175        if verbose: print "Setting up simulation"
176        myTimer.start() # start timer on construction
177        sim.setup(timestep=params['dt'],max_delay=params['syn_delay'])
178        N = params['N']
179        #dc_generator
180        phr_ON = sim.Population((N,),'dc_generator')
181        phr_OFF  = sim.Population((N,),'dc_generator')
182
183
184        for factor, phr in [(-params['snr'],phr_OFF),(params['snr'],phr_ON)]:
185            phr.tset('amplitude', params['amplitude'] * factor )
186            phr.set({ 'start' : params['simtime']/4, 'stop' : params['simtime']/4*3})
187
188        # internal noise model (see benchmark_noise)
189        noise_ON = sim.Population((N,),'noise_generator',{'mean':0.,'std':params['noise_std']})
190        noise_OFF = sim.Population((N,),'noise_generator',{'mean':0.,'std':params['noise_std']})
191
192
193        # target ON and OFF populations (what about a tridimensional Population?)
194        out_ON = sim.Population((N,), sim.IF_curr_alpha)#'IF_cond_alpha) #iaf_sfa_neuron')# EIF_cond_alpha_isfa_ista, IF_cond_exp_gsfa_grr,sim.IF_cond_alpha)#'iaf_sfa_neuron',params['parameters_gc'])#'iaf_cond_neuron')# IF_cond_alpha) #
195        out_OFF = sim.Population((N,), sim.IF_curr_alpha)#'IF_cond_alpha) #IF_curr_alpha)#'iaf_sfa_neuron')#sim.IF_curr_alpha)#,params['parameters_gc'])
196
197
198        # initialize membrane potential TODO: and conductances?
199        from pyNN.random import RandomDistribution, NumpyRNG
200        rng = NumpyRNG(seed=params['kernelseed'])
201        vinit_distr = RandomDistribution(distribution='uniform',parameters=[-70,-55], rng=rng)
202        for out_ in [out_ON, out_OFF]:
203            out_.randomInit(vinit_distr)
204
205
206        retina_proj_ON = sim.Projection(phr_ON, out_ON, sim.OneToOneConnector())
207        retina_proj_ON.setWeights(params['weight'])
208        # TODO fix setWeight, add setDelays to 10 ms (relative to stimulus onset)
209        retina_proj_OFF = sim.Projection(phr_OFF, out_OFF, sim.OneToOneConnector())
210        retina_proj_OFF.setWeights(params['weight'])
211
212        noise_proj_ON = sim.Projection(noise_ON, out_ON, sim.OneToOneConnector())
213        noise_proj_ON.setWeights(params['weight'])
214        noise_proj_OFF = sim.Projection(noise_OFF, out_OFF, sim.OneToOneConnector()) # implication if ON and OFF have the same noise input?
215        noise_proj_OFF.setWeights(params['weight'])
216
217
218        out_ON.record()
219        out_OFF.record()
220
221        # reads out time used for building
222        buildCPUTime= myTimer.elapsedTime()
223
224        # === Run simulation ===========================================================
225        if verbose: print "Running simulation"
226
227        myTimer.reset() # start timer on construction
228        sim.run(params['simtime'])
229        simCPUTime = myTimer.elapsedTime()
230
231        myTimer.reset()  # start timer on construction
232        # TODO LUP use something like "for pop in [phr, out]" ?
233        out_ON_filename=os.path.join(tmpdir,'out_on.gdf')
234        out_OFF_filename=os.path.join(tmpdir,'out_off.gdf')
235        out_ON.printSpikes(out_ON_filename)#
236        out_OFF.printSpikes(out_OFF_filename)#
237
238        # TODO LUP  get out_ON_DATA on a 2D grid independantly of out_ON.cell.astype(int)
239        out_ON_DATA = load_spikelist(out_ON_filename,range(N),
240                                        t_start=0.0, t_stop=params['simtime'])
241        out_OFF_DATA = load_spikelist(out_OFF_filename,range(N),
242                                        t_start=0.0, t_stop=params['simtime'])
243
244        out = {'out_ON_DATA':out_ON_DATA,
245                'out_OFF_DATA':out_OFF_DATA}#,'out_ON_pos':out_ON}
246        # cleans up
247        os.remove(out_ON_filename)
248        os.remove(out_OFF_filename)
249        os.rmdir(tmpdir)
250        writeCPUTime = myTimer.elapsedTime()
251
252        if verbose:
253            print "\nRetina Network Simulation:"
254            print(params['description'])
255            print "Number of Neurons  : ", N
256            print "Output rate  (ON) : ", out_ON_DATA.mean_rate(), "Hz/neuron in ", params['simtime'], "ms"
257            print "Output rate (OFF)   : ", out_OFF_DATA.mean_rate(), "Hz/neuron in ",params['simtime'], "ms"
258            print("Build time             : %g s" % buildCPUTime) 
259            print("Simulation time        : %g s" % simCPUTime)
260            print("Writing time           : %g s" % writeCPUTime)
261
262        return out
263
264
265if __name__ == '__main__':
266
267    ret = Retina(100)
268    out = ret.run(ret.params)
269    # plotting
270    import pylab
271    fig = pylab.figure(1)
272    z = pylab.subplot(121)
273    out['out_ON_DATA'].raster_plot(display=z, id_list=range(20), kwargs={'color':'r'})
274    z = pylab.subplot(122)
275    out['out_OFF_DATA'].raster_plot(display=z, id_list=range(20), kwargs={'color':'b'})
276    fig = pylab.figure(2)
277    z = pylab.subplot(111)
278    out['out_ON_DATA'].firing_rate(ret.params.simtime/100, display=z, kwargs={'label':'ON','color':'r'})
279    out['out_OFF_DATA'].firing_rate(ret.params.simtime/100, display=z, kwargs={'label':'OFF','color':'b'})
280    pylab.legend()
281
Note: See TracBrowser for help on using the browser.