Changeset 353

Show
Ignore:
Timestamp:
06/11/08 17:27:36 (5 months ago)
Author:
apdavison
Message:

Added Jens's exercises and some scripts giving possible solutions for some of the exercises

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • doc/Freiburg2008/larger_networks.tex

    r350 r353  
    55\frametitle{Populations and Projections} 
    66 
    7 \begin{block}{Problems with creating very large networks using \texttt{create()} and \texttt{connect}} 
     7\begin{block}{Problems with creating very large networks using \texttt{create()} and \texttt{connect()}} 
    88\begin{itemize} 
    99\item involves writing a lot of repetitive code, which is the same or similar for every model: iterating over lists of cells and connections, creating common projection patterns, recording from all or a subset of neurons... 
     
    1414\end{block} 
    1515 
    16 For these reasons, PyNN provides the \verb|Population| object, representing a group of neurons all of the same type (although possibly with cell-to-cell variations in the values of parameters), and the \verb|Projection| object, repesenting the set of connections between two \verb|Population|s. 
    17 All the book-keeping code is contained within the object classes, which also provide functions ('methods') to perform commonly-used tasks, such as recording from a fixed number of cells within the population, chosen at random. 
    18  
    19 By using the \verb|Population| and \verb|Projection| classes, less code needs to be written to create a given simulation, which means fewer-bugs and easier-to-understand scripts, plus, because the code for the classes is used in many different projects, bugs will be found more reliably, and the internal implementation of the classes optimized for performance. 
    20 Of particular importance is that iterations over large numbers of cells or connections can be done in fast compiled code (within the simulator engines) rather than in comparatively slow Python code. 
    21  
     16\end{frame} 
     17 
     18 
     19\begin{frame}[fragile] % -------------------------------------------------------------------- 
     20\frametitle{Populations and Projections} 
     21 
     22For these reasons, PyNN provides: 
     23\begin{itemize}  
     24\item the \verb|Population| object, representing a group of neurons all of the same type (although possibly with cell-to-cell variations in the values of parameters) 
     25\item the \verb|Projection| object, repesenting the set of connections between two \verb|Population|s. 
     26\end{itemize} 
     27 
     28All the book-keeping code is contained within the object classes, which also provide methods to perform commonly-used tasks, such as recording from a fixed number of cells within the population, chosen at random. 
     29 
     30[Give a side by side example of the latter?] 
     31 
     32\end{frame} 
     33 
     34 
     35\begin{frame}[fragile] % -------------------------------------------------------------------- 
     36\frametitle{Populations and Projections} 
     37By using the \verb|Population| and \verb|Projection| classes: 
     38\begin{itemize} 
     39\item less code needs to be written to create a given simulation 
     40\item which means fewer-bugs and easier-to-understand scripts 
     41\item plus, because the code for the classes is used in many different projects, bugs will be found more reliably 
     42\item and the internal implementation of the classes optimized for performance, e.g. iterations over large numbers of cells or connections can be done in fast compiled code (within the simulator engines) rather than in comparatively slow Python code. 
     43\end{itemize} 
    2244\end{frame} 
    2345 
     
    2648\frametitle{Creating \texttt{Population}s} 
    2749 
    28 Some examples of creating a population of neurons (don't forget to call \verb|setup()| first). 
    29  
    30 This creates a 10 x 10 array of \verb|IF_curr_exp| neurons with default parameters: 
    31     \begin{verbatim} 
    32     >>> p1 = Population((10,10), IF_curr_exp) 
    33     \end{verbatim} 
    34 This creates a 1D array of 100 spike sources, and gives it a label: 
    35     \begin{verbatim} 
    36     >>> p2 = Population(100, SpikeSourceArray, label="Input Population") 
    37     \end{verbatim} 
    38 This illustrates all the possible arguments of the \verb|Population| constructor, with argument names. 
    39 It creates a 3D array of \verb|IF_cond_alpha| neurons, all with a spike threshold set to -55 mV and membrane time constant set to 10 ms: 
    40     \begin{verbatim} 
    41     >>> p3 = Population(dims=(3,4,5), cellclass=IF_cond_alpha, 
    42     ...                 cellparams={'v_thresh': -55.0, 'tau_m': 10.0}, 
    43     ...                 label="Column 1") 
    44     \end{verbatim}                     
     50Create a 10 x 10 array of \verb|IF_curr_exp| neurons with default parameters: 
     51    \begin{verbatim} 
     52 >>> p1 = Population((10,10), IF_curr_exp)\end{verbatim} 
     53Create a 1D array of 100 spike sources, and give it a label: 
     54    \begin{verbatim} 
     55 >>> p2 = Population(100, SpikeSourceArray,  
     56                     label="Input Population")\end{verbatim} 
     57Create a 3D array of \verb|IF_cond_alpha| neurons, all with a spike threshold set to -55 mV and membrane time constant set to 10 ms: 
     58\small 
     59    \begin{verbatim} 
     60 >>> p3 = Population(dims=(3,4,5), cellclass=IF_cond_alpha, 
     61 ...                 cellparams={'v_thresh': -55, 'tau_m': 10}, 
     62 ...                 label="Column 1") 
     63    \end{verbatim}    
     64     
     65\end{frame} 
     66 
     67 
     68\begin{frame}[fragile] % -------------------------------------------------------------------- 
     69\frametitle{Creating \texttt{Population}s}                  
    4570The population dimensions can be retrieved using the \verb|dim| attribute, e.g.: 
    4671    \begin{verbatim} 
     
    5782    100 100 60 
    5883    \end{verbatim}     
    59 The above examples all use PyNN standard cell models. It is also possible to use simulator-specific models, but in this case the \verb|cellclass| should be given as a string, e.g.: 
    60     \begin{verbatim} 
    61     >>> p4 = Population(20, 'iaf_neuron', cellparams={'Tau': 15.0, 'C': 0.001}) 
     84     
     85\end{frame} 
     86 
     87 
     88\begin{frame}[fragile] % -------------------------------------------------------------------- 
     89\frametitle{Creating \texttt{Population}s}      
     90The previous examples all use PyNN standard cell models. It is also possible to use simulator-specific models, but in this case the \verb|cellclass| should be given as a string, e.g.: 
     91    \begin{verbatim} 
     92 >>> p4 = Population(20, "iaf_neuron",  
     93                     cellparams={'Tau': 15.0, 'C': 0.001}) 
    6294    \end{verbatim}     
    6395This example will work with NEST but not with NEURON or PCSIM. 
     
    79111    168 
    80112    >>> p3[2,1,0] 
    81     246 
    82     \end{verbatim}     
     113    246\end{verbatim}     
    83114The return values are \verb|ID| objects, which behave in most cases as integers, but also 
    84 allow accessing the values of the cell parameters (see below). 
    85 The n-tuple of values within the square brackets is referred to as a neurons's *address*, while the return value is its *id*. 
     115allow accessing the values of the cell parameters. 
     116The n-tuple of values within the square brackets is referred to as a neurons's \textit{address}, while the return value is its \textit{id}. IDs may be different for different backends, while addresses are always consistent across simulators. 
     117 
     118\end{frame} 
     119 
     120 
     121\begin{frame}[fragile] % -------------------------------------------------------------------- 
     122\frametitle{Addressing individual neurons} 
    86123Trying to address a non-existent neuron will raise an Exception: 
    87124    \begin{verbatim} 
    88125    >>> p1[999,0] 
    89126    Traceback (most recent call last): 
    90       File "<stdin>", line 1, in ? 
    91       File "/usr/lib/python/site-packages/pyNN/nest1.py", line 457, in __getitem__ 
    92         id = self.cell[addr] 
    93     IndexError: index (999) out of range (0<=index<=10) in dimension 0 
    94     \end{verbatim} 
     127    . . . 
     128    IndexError: index (999) out of range (0<=index<=10) in dimension 0\end{verbatim} 
    95129as will giving the wrong number of dimensions in the address. 
     130 
     131\vspace{1ex} 
     132 
    96133It is equally possible to define the address as a tuple, and then pass the tuple within the square brackets, e.g.: 
    97134    \begin{verbatim} 
     
    101138    >>> p1[address] 
    102139    56 
    103     \end{verbatim}     
    104 Neuron addresses are used in setting parameter values, and in specifying which neurons to record from. 
    105 They may also be used together with the low-level \verb|connect()|, \verb|set()|, and \verb|record()| functions. 
     140    \end{verbatim} 
     141 
     142\end{frame} 
     143 
     144 
     145\begin{frame}[fragile] % -------------------------------------------------------------------- 
     146\frametitle{Addressing individual neurons} 
    106147 
    107148To obtain an address given the id, use \verb|locate()|, e.g.: 
     
    120161    >>> p3.index(60) 
    121162    Traceback (most recent call last): 
    122       File "<stdin>", line 1, in <module> 
    123       File "/home/andrew/dev/pyNN/neuron/__init__.py", line 759, in index 
    124         return self.fullgidlist[n] 
     163    . . . 
    125164    IndexError: index out of bounds 
    126165    \end{verbatim} 
     
    130169\begin{frame}[fragile] % -------------------------------------------------------------------- 
    131170\frametitle{Setting parameter values} 
    132  
    133  
    134 Setting the same value for the entire population 
    135 ------------------------------------------------ 
     171\framesubtitle{Setting the same value for the entire population} 
    136172 
    137173To set a parameter for all neurons in the population to the same value, use the \verb|set()| method, e.g.: 
    138174    \begin{verbatim} 
    139175    >>> p1.set("tau_m", 20.0) 
    140     >>> p1.set({'tau_m':20, 'v_rest':-65}) 
     176    >>> p1.set({"tau_m": 20, 'v_rest': -65}) 
    141177    \end{verbatim}     
    142178The first form can be used for setting a single parameter, the second form for setting multiple parameters at once. 
    143179 
    144 Setting random values 
    145 --------------------- 
    146  
    147 To set a parameter to values drawn from a random distribution, use the \verb|rset()| method with a \verb|RandomDistribution| object from the \verb|pyNN.random| module (see the chapter on random numbers for more details). 
    148 The following example sets the initial membrane potential of each neuron to a value drawn from a uniform distribution between -70 mV and -55 mV: 
    149     \begin{verbatim} 
    150     >>> from pyNN.random import RandomDistribution 
    151     >>> vinit_distr = RandomDistribution(distribution='uniform',parameters=[-70,-55]) 
    152     >>> p1.rset('v_init', vinit_distr) 
    153     \end{verbatim} 
    154 Note that positional arguments can also be used. The following produces the same result as the above: 
    155     \begin{verbatim} 
    156     >>> vinit_distr = RandomDistribution('uniform', [-70,-55]) 
    157     \end{verbatim}For the specific case of setting the initial membrane potential, there is a convenience method \verb|randomInit()|, e.g.: 
    158     \begin{verbatim} 
    159     >>> p1.randomInit(vinit_distr) 
    160     \end{verbatim} 
    161 \end{frame} 
    162  
    163  
    164 \begin{frame}[fragile] % -------------------------------------------------------------------- 
    165 \frametitle{Setting values according to an array} 
     180\end{frame} 
     181 
     182 
     183\begin{frame}[fragile] % -------------------------------------------------------------------- 
     184\frametitle{Setting parameter values} 
     185\framesubtitle{Setting random values} 
     186 
     187To set a parameter to values drawn from a random distribution, use the \verb|rset()| method with a \verb|RandomDistribution| object from the \verb|pyNN.random| module. 
     188 
     189\vspace{1ex} 
     190 
     191Sets the initial membrane potential of each neuron to a value drawn from a uniform distribution between -70 mV and -55 mV: 
     192    \begin{verbatim} 
     193 >>> from pyNN.random import RandomDistribution 
     194 >>> distr = RandomDistribution('uniform', [-70,-55]) 
     195 >>> p1.rset('v_init', distr) 
     196    \end{verbatim} 
     197For the specific case of setting the initial membrane potential, there is a convenience method \verb|randomInit()|, e.g.: 
     198    \begin{verbatim} 
     199    >>> p1.randomInit(distr) 
     200    \end{verbatim} 
     201\end{frame} 
     202 
     203 
     204\begin{frame}[fragile] % -------------------------------------------------------------------- 
     205\frametitle{Setting parameter values} 
     206\framesubtitle{Setting values according to an array} 
    166207 
    167208 
     
    174215    >>> p1.tset('i_offset', current_input) 
    175216    \end{verbatim} 
    176 Setting parameter values for individual neurons 
    177 ----------------------------------------------- 
     217     
     218     
     219\end{frame} 
     220 
     221 
     222\begin{frame}[fragile] % -------------------------------------------------------------------- 
     223\frametitle{Setting parameter values} 
     224\framesubtitle{Setting parameter values for individual neurons} 
    178225 
    179226To set the parameters of an individual neuron, you can use the low-level \verb|set()| function,: 
     
    192239 
    193240 
    194 To iterate over all the cells in a population, returning the neuron ids, use
    195     \begin{verbatim} 
    196     >>> for id in p1: #doctest: +ELLIPSIS 
     241To iterate over all the cells in a population, returning the neuron ids
     242    \begin{verbatim} 
     243    >>> for id in p1: 
    197244    ...   print id, id.tau_m 
    198245    ... 
     
    205252    ... 
    206253    \end{verbatim} 
    207 The \verb|Population.ids()| method produces the same result. To iterate over cells but return neuron addresses, use the \verb|addresses()| method: 
    208     \begin{verbatim} 
    209     >>> for addr in p1.addresses(): #doctest: +ELLIPSIS 
     254     
     255\end{frame} 
     256 
     257 
     258\begin{frame}[fragile] % -------------------------------------------------------------------- 
     259\frametitle{Iterating over all the neurons in a population} 
     260 
     261To iterate over cells but return neuron addresses: 
     262    \begin{verbatim} 
     263    >>> for addr in p1.addresses(): 
    210264    ...   print addr 
    211265    ... 
     
    227281 
    228282 
    229 Recording spike times is done with the method \verb|record()|. 
    230 Recording membrane potential is done with the method \verb|record_v()|. 
    231 Both methods have identical argument lists. 
    232 Some examples: 
    233     \begin{verbatim} 
    234     >>> p1.record()                            # record from all neurons in the population 
    235     >>> p1.record(10)                          # record from 10 neurons chosen at random 
    236     >>> p1.record([p1[0,0], p1[0,1], p1[0,2]]) # record from specific neurons 
    237     \end{verbatim} 
     283Recording spike times: \verb|record()| 
     284 
     285Recording membrane potential: \verb|record_v()| 
     286 
     287\vspace{1ex} 
     288 
     289Record from all neurons in the population 
     290    \begin{verbatim} 
     291 >>> p1.record()                             
     292 \end{verbatim} 
     293 Record from 10 neurons chosen at random 
     294 \begin{verbatim} 
     295 >>> p1.record(10)                           
     296 \end{verbatim} 
     297Record from specific neurons 
     298 \begin{verbatim} 
     299 >>> p1.record([p1[0,0], p1[0,1], p1[0,2]])  
     300    \end{verbatim} 
     301\end{frame} 
     302 
     303 
     304\begin{frame}[fragile] % -------------------------------------------------------------------- 
     305\frametitle{Recording} 
     306 
    238307Writing the recorded values to file is done with a second pair of methods, \verb|printSpikes()| and \verb|print_v()|, e.g.: 
    239308    \begin{verbatim} 
     
    241310    \end{verbatim} 
    242311By default, the output files are post-processed to reformat them from the native simulator format to a common format that is the same for all simulator engines. 
    243 This facilitates comparisons across simulators, but of course has some performace penalty. 
     312This facilitates comparisons across simulators, but of course has some performance penalty. 
    244313To get output in the native format of the simulator, add \verb|compatible_output=False| to the argument list. 
     314 
     315getSpikes()? 
     316 
     317\end{frame} 
     318 
     319 
     320\begin{frame}[fragile] % -------------------------------------------------------------------- 
     321\frametitle{Recording} 
     322\framesubtitle{Distributed simulations} 
    245323 
    246324When running a distributed simulation, each node records only those neurons that it simulates. 
     
    259337    >>> p1[1,0].position = (0.0, 0.1, 0.2) 
    260338    >>> p1[1,0].position 
    261     array([ 0. ,  0.1,  0.2]) 
    262     \end{verbatim}     
     339    array([ 0. ,  0.1,  0.2])\end{verbatim}     
    263340To obtain the positions of all neurons at once (as a numpy array), use the \verb|positions| attribute of the \verb|Population| object, e.g.: 
    264341    \begin{verbatim} 
    265     >>> p1.positions #doctest: +ELLIPSIS,+NORMALIZE_WHITESPACE 
    266     array([[...]]) 
    267     \end{verbatim}          
     342    >>> p1.positions 
     343    array([[...]])\end{verbatim}          
    268344To find the neuron that is closest to a particular point in space, use the \verb|nearest()| attribute: 
    269345    \begin{verbatim} 
     
    296372 
    297373 
    298 A \verb|Projection| object is a container for all the synaptic connections between neurons in two \verb|Population|s, together with methods for setting synaptic weights and delays. 
    299 A \verb|Projection| is created by specifying a pre-synaptic \verb|Population|, a post-synaptic \verb|Population| and a \verb|Connector| object, which determines 
    300 the algorithm used to wire up the neurons, e.g.: 
    301     \begin{verbatim} 
    302     >>> prj2_1 = Projection(p2, p1, method=AllToAllConnector()) 
    303     \end{verbatim}     
    304 This connects \verb|p2| (pre-synaptic) to \verb|p1| (post-synaptic), using an '\verb|AllToAllConnector|' object, which connects every neuron in the pre-synaptic population to every neuron in the post-synaptic population. 
    305 The currently available \verb|Connector| classes are explained below. It is fairly straightforward for a user to write a new \verb|Connector| class if they 
    306 wish to use a connection algorithm not already available in PyNN. 
    307  
     374A \verb|Projection| object is a container for all the synaptic connections of a given type between neurons in two \verb|Population|s, together with methods for setting synaptic weights and delays. 
     375 
     376A \verb|Projection| is created by specifying 
     377\begin{itemize} 
     378\item a pre-synaptic \verb|Population| 
     379\item a post-synaptic \verb|Population| 
     380\item a \verb|Connector| object, which determines the algorithm used to wire up the neurons,  
     381\end{itemize} 
     382 
     383    \begin{verbatim} 
     384 >>> prj = Projection(p2, p1, AllToAllConnector())\end{verbatim} 
     385       
     386This connects \verb|p2| (pre-synaptic) to \verb|p1| (post-synaptic), using an \verb|AllToAllConnector| object, which connects every neuron in the pre-synaptic population to every neuron in the post-synaptic population. 
    308387\end{frame} 
    309388 
     
    313392 
    314393 
    315 The \verb|AllToAllConnector'| constructor has one optional argument \verb|allow_self_connections|, for use when connecting a \verb|Population| to itself. 
     394The \verb|AllToAllConnector| constructor has one optional argument, \verb|allow_self_connections|, for use when connecting a \verb|Population| to itself. 
     395 
    316396By default it is \verb|True|, but if a neuron should not connect to itself, set it to \verb|False|, e.g.: 
    317397    \begin{verbatim} 
    318     >>> prj1_1 = Projection(p1, p1, AllToAllConnector(allow_self_connections=False)) 
     398 >>> prj = Projection(p1, p1,  
     399                      AllToAllConnector(allow_self_connections=False)) 
    319400    \end{verbatim} 
    320401\end{frame} 
     
    327408Use of the \verb|OneToOneConnector| requires that the pre- and post-synaptic populations have the same dimensions, e.g.: 
    328409    \begin{verbatim} 
    329     >>> prj1_1a = Projection(p1, p1, OneToOneConnector()) 
     410 >>> prj = Projection(p1, p1, OneToOneConnector()) 
    330411    \end{verbatim}     
    331412Trying to connect two \verb|Population|s with different dimensions will raise an Exception, e.g.: 
    332413    \begin{verbatim} 
    333     >>> invalid_prj = Projection(p2, p3, OneToOneConnector()) #doctest: +IGNORE_EXCEPTION_DETAIL 
    334     Traceback (most recent call last): 
    335       File "doctest.py", line 1212, in __run 
    336         compileflags, 1) in test.globs 
    337       File "<doctest highlevelapi.txt[49]>", line 1, in <module> 
    338         invalid_prj = Projection(p2, p3, OneToOneConnector()) 
    339       File "/home/andrew/dev/pyNN/neuron/__init__.py", line 1199, in __init__ 
    340         hoc_commands += method.connect(self) 
    341       File "/home/andrew/dev/pyNN/neuron/connectors.py", line 95, in connect 
    342         raise Exception("OneToOneConnector does not support presynaptic and postsynaptic Populations of different sizes.") 
    343     Exception: OneToOneConnector does not support presynaptic and postsynaptic Populations of different sizes. 
    344     \end{verbatim}     
    345      
     414 >>> prj = Projection(p2, p3, OneToOneConnector()) 
     415 Traceback (most recent call last): 
     416 . . .  
     417 Exception: OneToOneConnector does not support presynaptic and postsynaptic Populations of different sizes. 
     418    \end{verbatim}     
     419 
     420Planned extension: allow one-to-row, one-to-column connections, e.g. connecting a 3x5 Population to a 3x5x10 Population. 
     421 
    346422\end{frame} 
    347423 
     
    351427 
    352428 
    353 With the \verb|FixedProbabilityConnector| method, each possible connection between all pre-synaptic neurons and all post-synaptic neurons is created with probability \verb|p_connect|, e.g.: 
    354     \begin{verbatim} 
    355     >>> prj2_3 = Projection(p2, p3, FixedProbabilityConnector(p_connect=0.2)) 
     429With the \verb|FixedProbabilityConnector| method, each possible connection between all pre-synaptic neurons and all post-synaptic neurons is created with probability \verb|p_connect|: 
     430 
     431    \begin{verbatim} 
     432 >>> prj = Projection(p2, p3,  
     433                      FixedProbabilityConnector(0.2)) 
    356434    \end{verbatim}     
    357435The constructor also accepts an \verb|allow_self_connections| parameter, as above. 
     
    363441\frametitle{Connecting neurons with a distance-dependent probability} 
    364442 
    365  
    366 For each pair of pre-post cells, the connection probability depends on distance. 
    367 If positions in space have been specified using the \verb|positions()| method of the \verb|Population| class or the \verb|position| attributes of individual 
    368 neurons, these positions are used to calculate distances. 
    369 If not, the neuron addresses, i.e., the array coordinates, are used. 
    370  
    371 The constructor requires a string \verb|d_expression|, which should be the right-hand side of a valid python expression for probability (i.e. returning a value between 0 and 1), involving '\verb|d|', e.g.: 
    372     \begin{verbatim} 
    373     >>> prj1_1b = Projection(p1, p1, DistanceDependentProbabilityConnector("exp(-abs(d))")) 
    374     >>> prj3_3  = Projection(p3, p3, DistanceDependentProbabilityConnector("float(d<3)")) 
    375     \end{verbatim} 
    376 The first example connects neurons with an exponentially-decaying probability. 
    377 The second example connects each neuron to all its neighbours within a range of 3 units (distance is in $\mu$m if positions have been specified, in array coordinate distance otherwise). 
    378  
    379 The calculation of distance may be controlled by a number of further arguments. 
    380  
    381 By default, the 3D distance between cell positions is used, but the \verb|axes| argument may be used to change this, e.g.: 
    382     \begin{verbatim} 
    383     >>> connector = DistanceDependentProbabilityConnector("exp(-abs(d))", axes='xy') 
    384     \end{verbatim}     
     443For each pair of pre-post cells, the connection probability depends on distance (determined from the \verb|position| attributes of the neurons). 
     444 
     445The constructor requires a string \verb|d_expression|, which should be the right-hand side of a valid Python expression for probability (i.e. returning a value between 0 and 1), involving '\verb|d|'. 
     446 
     447\vspace{1ex} 
     448 
     449Connect neurons with an exponentially-decaying probability: 
     450\begin{small} 
     451    \begin{verbatim} 
     452 >>> DDPC = DistanceDependentProbabilityConnector 
     453 >>> prj = Projection(p1, p1,  
     454                      DDPC("exp(-abs(d))"))\end{verbatim} 
     455\end{small} 
     456Connect each neuron to all its neighbours within a range of 30 $\mu$m: 
     457\begin{small}       
     458    \begin{verbatim} 
     459 >>> prj  = Projection(p1, p1,  
     460                       DDPC("float(d<30)")) 
     461    \end{verbatim} 
     462\end{small} 
     463\end{frame} 
     464 
     465 
     466\begin{frame}[fragile] % -------------------------------------------------------------------- 
     467\frametitle{Connecting neurons with a distance-dependent probability} 
     468 
     469\begin{itemize} 
     470\item By default, the 3D distance between cell positions is used, but the \verb|axes| argument may be used to change this: 
     471\begin{small} 
     472     \begin{verbatim} 
     473 >>> connector = DDPC("exp(-abs(d))", axes='xy')\end{verbatim} 
     474\end{small} 
    385475will ignore the z-coordinate when calculating distance. 
    386476 
    387 Similarly, the origins of the coordinate systems of the two Populations and the relative scale of the two coordinate systems may be controlled using the \verb|offset| and \verb|scale_factor| arguments. This is useful when connecting brain regions that have very different sizes but that have a topographic mapping between them, e.g. retina to LGN to V1. 
    388  
    389 In more abstract models, it is often useful to be able to avoid edge effects by specifying periodic boundary conditions, e.g.: 
    390     \begin{verbatim} 
    391     >>> connector = DistanceDependentProbabilityConnector("exp(-abs(d))", periodic_boundaries=(500, 500, 0)) 
    392     \end{verbatim}     
     477\item The origins and relative scale of the coordinate systems of the two Populations may be controlled using the \verb|offset| and \verb|scale_factor| arguments. This is useful when connecting brain regions that have very different sizes but that have a topographic mapping between them, e.g. retina to LGN to V1. 
     478 
     479\item In more abstract models, it is often useful to be able to avoid edge effects by specifying periodic boundary conditions, e.g.: 
     480\begin{small} 
     481    \begin{verbatim} 
     482 >>> connector = DDPC("exp(-abs(d))",  
     483                      periodic_boundaries=(500, 500, 0))\end{verbatim}   
     484\end{small}   
    393485calculates distance on the surface of a torus of circumference 500 $\mu$m (wrap-around in the x- and y-dimensions but not z) 
    394 [really need to test this, and improve the docstrings] 
    395  
    396  
    397 \end{frame} 
    398  
    399  
    400 \begin{frame}[fragile] % -------------------------------------------------------------------- 
    401 \frametitle{Divergent/fan-out connections} 
     486\end{itemize} 
     487 
     488\end{frame} 
     489 
     490 
     491\begin{frame}[fragile] % -------------------------------------------------------------------- 
     492\frametitle{Divergent/fan-out and Convergent/fan-in connections} 
    402493 
    403494 
    404495The \verb|FixedNumberPostConnector| connects each pre-synaptic neuron to exactly \verb|n| post-synaptic neurons chosen at random: 
    405496    \begin{verbatim} 
    406     >>> prj2_1a = Projection(p2, p1, FixedNumberPostConnector(n=30)) 
     497 >>> prj = Projection(p2, p1,  
     498                      FixedNumberPostConnector(n=30)) 
    407499    \end{verbatim}     
    408500As a refinement to this, the number of post-synaptic neurons can be chosen at random from a \verb|RandomDistribution| object, e.g.: 
    409501    \begin{verbatim} 
    410     >>> distr_npost = RandomDistribution(distribution='binomial', parameters=[100,0.3]) 
    411     >>> prj2_1b = Projection(p2, p1, FixedNumberPostConector(n=distr_npost)) 
    412     \end{verbatim}     
    413  
    414 \end{frame} 
    415  
    416  
    417 \begin{frame}[fragile] % -------------------------------------------------------------------- 
    418 \frametitle{Convergent/fan-in connections} 
    419  
    420  
    421 The \verb|FixedNumberPreConnector| has the same arguments as \verb|FixedNumberPostConnector|, but of course it connects each *post*-synaptic neuron to \verb|n| *pre*-synaptic neurons, e.g.: 
    422     \begin{verbatim} 
    423     >>> prj2_1c = Projection(p2, p1, FixedNumberPreConnector(5)) 
    424     >>> distr_npre = RandomDistribution(distribution='poisson', parameters=[5]) 
    425     >>> prj2_1d = Projection(p2, p1, FixedNumberPreConnector(distr_npre)) 
    426     \end{verbatim} 
    427  
    428 \end{frame} 
     502 >>> distr = RandomDistribution('binomial', [100,0.3]) 
     503 >>> prj = Projection(p2, p1,  
     504                      FixedNumberPostConector(n=distr)) 
     505    \end{verbatim}     
     506 
     507The \verb|FixedNumberPreConnector| behaves in an analogous manner. 
     508 
     509\end{frame} 
     510 
    429511 
    430512 
     
    435517Connection patterns can be written to a file using \verb|saveConnections()|, e.g.: 
    436518    \begin{verbatim} 
    437     >>> prj1_1a.saveConnections("prj1_1a.conn") 
     519 >>> prj.saveConnections("prj.conn") 
    438520    \end{verbatim}     
    439521These files can then be read back in to create a new \verb|Projection| object using a \verb|FromFileConnector| object, e.g.: 
    440522    \begin{verbatim} 
    441     >>> prj1_1c = Projection(p1, p1, FromFileConnector("prj1_1a.conn")) 
    442     \end{verbatim} 
    443 \end{frame} 
     523 >>> prj = Projection(p1, p1,  
     524                      FromFileConnector("prj.conn")) 
     525    \end{verbatim} 
     526     
     527The format is consistent between backends, so you can save a connection pattern in NEST and then load it into NEURON, for example. 
     528\end{frame} 
     529 
    444530 
    445531 
     
    451537(Note that the weights and delays should be optional, but currently are not). Example: 
    452538    \begin{verbatim} 
    453     >>> conn_list = [ 
    454     ...   ((0,0), (0,0,0), 0.0, 0.1), 
    455     ...   ((0,0), (0,0,1), 0.0, 0.1), 
    456     ...   ((0,0), (0,0,2), 0.0, 0.1), 
    457     ...   ((0,1), (1,3,0), 0.0, 0.1) 
    458     ... ] 
    459     >>> prj1_3d = Projection(p1, p3, FromListConnector(conn_list)) 
     539 >>> conn_list = [ 
     540 ...   ((0,0), (0,0,0), 0.0, 0.1), 
     541 ...   ((0,0), (0,0,1), 0.0, 0.1), 
     542 ...   ((0,0), (0,0,2), 0.0, 0.1), 
     543 ...   ((0,1), (1,3,0), 0.0, 0.1) 
     544 ... ] 
     545 >>> prj1_3d = Projection(p1, p3,  
     546                          FromListConnector(conn_list)) 
    460547    \end{verbatim} 
    461548 
     
    467554 
    468555 
    469 If you wish to use a specific connection/wiring algorithm not covered by the PyNN built-in ones, the simplest option is to construct a list of connections and use the \verb|FromListConnector| class. By looking at the code for the built-in \verb|Connector|s, it should also be quite straightforward to write your own \verb|Connector| class, although this must be done separately for each simulator you wish to use. In a future release, we plan to make writing new simulator-independent \verb|Connector|s much simpler. 
    470  
     556If you wish to use a specific connection/wiring algorithm not covered by the PyNN built-in ones, the simplest option is to construct a list of connections and use the \verb|FromListConnector| class.  
     557 
     558\vspace{1ex} 
     559 
     560However, by looking at the code for the built-in \verb|Connector|s, it should also be quite straightforward to write your own \verb|Connector| class, although this must be done separately for each simulator you wish to use. In a future release, we plan to make writing new simulator-independent \verb|Connector|s much simpler. 
     561 
     562[give an example here?] 
    471563 
    472564\end{frame} 
     
    475567\begin{frame}[fragile] % -------------------------------------------------------------------- 
    476568\frametitle{Setting synaptic weights and delays} 
    477  
    478  
    479 Synaptic weights and delays may be set either when creating the \verb|Projection|, as arguments to the \verb|Connector| object, or afterwards using the \verb|setWeights()| and \verb|setDelays()| methods \verb|Projection|. 
    480  
    481 All \verb|Connector| objects accept \verb|weights| and \verb|delays| arguments to their constructors. Some examples: 
     569\framesubtitle{when creating the \texttt{Projection}} 
    482570 
    483571To set all weights to the same value: 
    484572    \begin{verbatim} 
    485     >>> connector = AllToAllConnector(weights=0.7) 
    486     >>> prj1_3e = Projection(p1, p3, connector) 
    487     \end{verbatim}     
     573 >>> connector = AllToAllConnector(weights=0.7) 
     574 >>> prj = Projection(p1, p3, connector)\end{verbatim}     
    488575To set delays to random values taken from a specific distribution: 
    489576    \begin{verbatim} 
    490     >>> delay_distr = RandomDistribution(distribution='gamma',parameters=[1,0.1]) 
    491     >>> connector = FixedNumberPostConnector(n=20, delays=delay_distr) 
    492     >>> prj2_1e = Projection(p2, p1, connector) 
    493     \end{verbatim} 
     577 >>> distr = RandomDistribution('gamma', [1,0.1]) 
     578 >>> conn = FixedNumberPostConnector(n=20, delays=distr) 
     579 >>> prj = Projection(p2, p1, conn)\end{verbatim} 
    494580To set individual weights and delays to specific values: 
    495581    \begin{verbatim} 
    496     >>> weights = numpy.arange(1.1, 2.0, 0.9/60) 
    497     >>> delays = 2*weights 
    498     >>> connector = OneToOneConnector(weights=weights, delays=delays) 
    499     >>> prj1_1d = Projection(p1, p1, connector) 
    500     \end{verbatim} 
    501 After creating the \verb|Projection|, to set the weights of all synaptic connections in a \verb|Projection| to a single value, use the \verb|setWeights()| method: 
    502     \begin{verbatim} 
    503     >>> prj1_1.setWeights(0.2) 
    504     \end{verbatim}     
    505 [Note: synaptic weights in PyNN are in nA for current-based synapses and µS for conductance-based synapses)]. 
    506  
    507 To set different weights to different values, use \verb|setWeights()| with a list or 1D numpy array argument, where the length of the list/array is equal to the number of synapses, e.g.: 
    508     \begin{verbatim} 
    509     >>> weight_list = 0.1*numpy.ones(len(prj2_1)) 
    510     >>> weight_list[0:5] = 0.2 
    511     >>> prj2_1.setWeights(weight_list) 
    512     \end{verbatim}     
    513 To set weights to random values, use the \verb|randomizeWeights()| method: 
    514     \begin{verbatim} 
    515     >>> weight_distr = RandomDistribution(distribution='gamma',parameters=[1,0.1]) 
    516     >>> prj1_1.randomizeWeights(weight_distr) 
    517     \end{verbatim}     
    518 Setting delays works similarly: 
    519     \begin{verbatim} 
    520     >>> prj1_1.setDelays(0.6) 
    521     >>> delay_list = 0.3*numpy.ones(len(prj2_1)) 
    522     >>> delay_list[0:5] = 0.4 
    523     >>> prj2_1.setDelays(delay_list) 
    524     >>> delay_distr = RandomDistribution(distribution='gamma',parameters=[2,0.2]) 
    525     >>> prj1_1.randomizeDelays(delay_distr) 
    526     \end{verbatim} 
     582 >>> weights = numpy.arange(1.1, 2.0, 0.9/len(p1)) 
     583 >>> delays = 2*weights 
     584 >>> connector = OneToOneConnector(weights=weights,  
     585                                   delays=delays) 
     586 >>> prj = Projection(p1, p1, connector) 
     587    \end{verbatim} 
     588     
     589\end{frame} 
     590 
     591 
     592\begin{frame}[fragile] % -------------------------------------------------------------------- 
     593\frametitle{Setting synaptic weights and delays} 
     594\framesubtitle{for an existing \texttt{Projection}} 
     595 
     596Set the weights of all synaptic connections in a \verb|Projection| to a single value:    \begin{verbatim} 
     597 >>> prj.setWeights(0.2)\end{verbatim}     
     598{\footnotesize[Units: nA for current-based synapses and µS for conductance-based synapses.]} 
     599 
     600Set different weights to different values: 
     601    \begin{verbatim} 
     602 >>> weight_list = 0.1*numpy.ones(len(prj)) 
     603 >>> weight_list[0:5] = 0.2 
     604 >>> prj.setWeights(weight_list)\end{verbatim}     
     605     
     606Set weights to random values: 
     607    \begin{verbatim} 
     608 >>> weight_distr = RandomDistribution('gamma', [1,0.1]) 
     609 >>> prj.randomizeWeights(weight_distr)\end{verbatim}  
     610        
     611Setting delays works similarly {\small(\verb|setDelays()|, \verb|randomizeDelays()|)}. 
    527612 
    528613\end{frame} 
     
    538623connections): 
    539624    \begin{verbatim} 
    540     >>> prj2_1e.getWeights(format='list') 
    541     fsgs 
    542     >>> prj2_1e.getWeights(format='array') 
    543     fdsg 
     625 >>> prj2_1.getWeights(format='list')[3:7] 
     626 [0.20000000000000001, 0.20000000000000001, 0.10000000000000001, 0.10000000000000001] 
     627 >>> prj2_1.getWeights(format='array')[:3,:3] 
     628 array([[ 0.2,  0.2,  0.2], 
     629        [ 0.1,  0.1,  0.1], 
     630        [ 0.1,  0.1,  0.1]]) 
    544631    \end{verbatim} 
    545632\verb|getDelays()| is analogous. \verb|printWeights()| writes the weights to a file.