├── src
└── pyNCS
│ ├── changes
│ ├── api
│ ├── __init__.py
│ ├── loopbackAPI.py
│ ├── BaseConfAPI.py
│ ├── ComAPI.py
│ ├── BaseComAPI.py
│ ├── IFSLWTA_brian_model.py
│ ├── paramTranslation.py
│ ├── BrianAPI.py
│ └── ConfAPI.py
│ ├── pyST
│ ├── pyST_globals.py
│ ├── __init__.py
│ └── STsl.py
│ ├── data
│ ├── setuptype.dtd
│ └── setup.dtd
│ ├── __init__.py
│ ├── connection.py
│ └── experimentTools.py
├── docs
├── general
│ ├── api.txt
│ ├── modules.txt
│ ├── new_hardware.txt
│ ├── pytune_xml_file_template.txt
│ ├── pytune_plugin.txt
│ ├── pyNCS.AerViewer.txt
│ ├── pyNCS.pyST.txt
│ ├── pyNCS.txt
│ ├── experiments.txt
│ ├── hardware_setup.txt
│ ├── pyst.txt
│ ├── aex_reprogramming.txt
│ ├── learning.txt
│ ├── pyosc.txt
│ ├── pytune_python_file_template.txt
│ ├── introduction.txt
│ ├── spcm.txt
│ ├── tutorial.txt
│ └── installation.txt
├── images
│ ├── fig1.png
│ ├── pytune.png
│ ├── raw_data.png
│ ├── software.jpg
│ ├── software.png
│ ├── mapping_2d.png
│ ├── mapping_all.png
│ ├── amda_and_aex.jpg
│ ├── decorated_data.png
│ ├── zenzero_setup.png
│ ├── raster_tutorial.png
│ ├── meanrate_tutorial.png
│ └── normalized_data_zoomed.png
├── examples
│ ├── examples.txt
│ └── reservoir.txt
├── index.txt
├── Makefile
└── conf.py
├── .gitmodules
├── test
├── pyST_testbed.py
├── pyNCS_testbed.py
├── chipfiles
│ ├── linear.xml
│ ├── tmpdiff64.csv
│ ├── linear.csv
│ ├── ifmem.xml
│ ├── tmpdiff64.xml
│ ├── sac.xml
│ ├── sac.csv
│ ├── ifmem.csv
│ ├── if2dwta.xml
│ ├── if2dwta.csv
│ └── ifslwta.csv
├── setupfiles
│ ├── test.xml
│ ├── test_performance.xml
│ └── test_setuptype.xml
├── testComAPI.py
├── biases
│ ├── defaultBiases_if2dwta
│ └── defaultBiases_ifslwta
├── test_performance.py
├── expSetup.py
└── pyNCS_unittest.py
├── README.md
├── .gitignore
├── .project
├── .pydevproject
└── setup.py
/src/pyNCS/changes:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/general/api.txt:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/images/fig1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/inincs/pyNCS/HEAD/docs/images/fig1.png
--------------------------------------------------------------------------------
/docs/images/pytune.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/inincs/pyNCS/HEAD/docs/images/pytune.png
--------------------------------------------------------------------------------
/docs/images/raw_data.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/inincs/pyNCS/HEAD/docs/images/raw_data.png
--------------------------------------------------------------------------------
/docs/images/software.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/inincs/pyNCS/HEAD/docs/images/software.jpg
--------------------------------------------------------------------------------
/docs/images/software.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/inincs/pyNCS/HEAD/docs/images/software.png
--------------------------------------------------------------------------------
/docs/images/mapping_2d.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/inincs/pyNCS/HEAD/docs/images/mapping_2d.png
--------------------------------------------------------------------------------
/docs/images/mapping_all.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/inincs/pyNCS/HEAD/docs/images/mapping_all.png
--------------------------------------------------------------------------------
/docs/general/modules.txt:
--------------------------------------------------------------------------------
1 | pyNCS
2 | =====
3 |
4 | .. toctree::
5 | :maxdepth: 4
6 |
7 | pyNCS
8 |
--------------------------------------------------------------------------------
/docs/images/amda_and_aex.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/inincs/pyNCS/HEAD/docs/images/amda_and_aex.jpg
--------------------------------------------------------------------------------
/docs/images/decorated_data.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/inincs/pyNCS/HEAD/docs/images/decorated_data.png
--------------------------------------------------------------------------------
/docs/images/zenzero_setup.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/inincs/pyNCS/HEAD/docs/images/zenzero_setup.png
--------------------------------------------------------------------------------
/docs/images/raster_tutorial.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/inincs/pyNCS/HEAD/docs/images/raster_tutorial.png
--------------------------------------------------------------------------------
/docs/images/meanrate_tutorial.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/inincs/pyNCS/HEAD/docs/images/meanrate_tutorial.png
--------------------------------------------------------------------------------
/src/pyNCS/api/__init__.py:
--------------------------------------------------------------------------------
1 | #import BrianAPI
2 | from __future__ import absolute_import
3 | from . import ComAPI,ConfAPI
4 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "src/pyNCS/data/NHML"]
2 | path = src/pyNCS/data/NHML
3 | url = https://github.com/inincs/NHML.git
4 |
--------------------------------------------------------------------------------
/docs/images/normalized_data_zoomed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/inincs/pyNCS/HEAD/docs/images/normalized_data_zoomed.png
--------------------------------------------------------------------------------
/test/pyST_testbed.py:
--------------------------------------------------------------------------------
1 | import pyST_unittest
2 |
3 | test=pyST_unittest.TestSequenceFunctions(methodName='setUp')
4 | test.setUp()
5 |
--------------------------------------------------------------------------------
/test/pyNCS_testbed.py:
--------------------------------------------------------------------------------
1 | import pyNCS_unittest
2 |
3 | test=pyNCS_unittest.TestSequenceFunctions(methodName='setUp')
4 | test.setUp()
5 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | pyNCS
2 | =====
3 |
4 | pyNCS is a python library that allows easy access to Neuromorphic Chips and Setups
5 |
6 | Documentation is available at [http://inincs.github.com/pyNCS/]
7 |
8 | The Wiki page is at [https://github.com/inincs/pyNCS/wiki]
9 |
10 | Requires:
11 | Python >= 2.6
12 |
13 | Does NOT require:
14 | traits-gui
15 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.py[co]
2 | .*.sw[a-z]
3 |
4 | # Packages
5 | *.egg
6 | *.egg-info
7 | dist
8 | build
9 | _build
10 | eggs
11 | parts
12 | bin
13 | var
14 | sdist
15 | develop-eggs
16 | .installed.cfg
17 |
18 | # Installer logs
19 | pip-log.txt
20 |
21 | # Unit test / coverage reports
22 | .coverage
23 | .tox
24 |
25 | #Translations
26 | *.mo
27 |
28 | #Mr Developer
29 | .mr.developer.cfg
30 |
--------------------------------------------------------------------------------
/test/chipfiles/linear.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | pyNCS
4 |
5 |
6 |
7 |
8 |
9 | org.python.pydev.PyDevBuilder
10 |
11 |
12 |
13 |
14 |
15 | org.python.pydev.pythonNature
16 |
17 |
18 |
--------------------------------------------------------------------------------
/docs/general/new_hardware.txt:
--------------------------------------------------------------------------------
1 | Controlling new hardware with pyNCS
2 | ===================================
3 |
4 | Neuromorphic chips
5 | ------------------
6 |
7 | In order to use new chips with the existing software, a bunch of files need to
8 | be written.
9 |
10 | - csv
11 | - xml
12 |
13 | ...
14 |
15 | New oscillocope
16 | ---------------
17 |
18 | - how to import drivers into pyOsc
19 |
20 | New anything else
21 | -----------------
22 |
--------------------------------------------------------------------------------
/src/pyNCS/pyST/pyST_globals.py:
--------------------------------------------------------------------------------
1 | #-----------------------------------------------------------------------------
2 | # Purpose:
3 | #
4 | # Author: Emre Neftci
5 | #
6 | # Copyright : University of Zurich, Giacomo Indiveri, Emre Neftci, Sadique Sheik, Fabio Stefanini
7 | # Licence : GPLv2
8 | #-----------------------------------------------------------------------------
9 |
10 |
11 | DefaultMonChannelAddress = None
12 | DefaultSeqChannelAddress = None
13 |
14 |
15 |
--------------------------------------------------------------------------------
/docs/general/pytune_xml_file_template.txt:
--------------------------------------------------------------------------------
1 | ::
2 |
3 |
4 |
5 | inf
6 | 0
7 | Hz
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/.pydevproject:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | python 2.7
6 | Default
7 |
8 | /pyNCS/src
9 | /pyNCS/test
10 |
11 |
12 |
--------------------------------------------------------------------------------
/docs/general/pytune_plugin.txt:
--------------------------------------------------------------------------------
1 | pyTune plugins explained
2 | ========================
3 |
4 | pyTune controls neuromorphic system by means of plugins. A plugin basically
5 | translates pyTune informations (classes, methods, attributes, keywords, ...)
6 | into system-specific ones. For example, the pyNCS plugin for pyTune contains
7 | methods for setting the biases of the chips when calling ``set`` functions.
8 | Once a new plugin is implemented, all the features of pyTune should be
9 | available right away.
10 |
11 |
--------------------------------------------------------------------------------
/test/chipfiles/tmpdiff64.csv:
--------------------------------------------------------------------------------
1 | "chipclass" "TMPDIFF64"
2 |
3 | "aerOut"
4 | "id" "x" "range" "range(2**6)" "type" "1" func "X"
5 | "id" "y" "range" "range(2**6)" "type" "1" func "Y>>1"
6 | "id" "p" "range" "range(2)" "type" "-1" func "Y&1"
7 |
8 |
9 | pinid X func x
10 | pinid Y func (y<<1)+p
11 | "pinlayout" "X4 X3 X2 X1 X0 X5 Y6 Y5 Y4 Y3 Y2 Y1 Y0"
12 |
13 | "Count" "Pad#" "Pin#" "Circuit Block" "Signal Name" "FET" "BIAS type" "PAD type" "Range" "Simulation value" "Description" "Channel#"
14 |
15 |
--------------------------------------------------------------------------------
/test/setupfiles/test.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/test/setupfiles/test_performance.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/test/chipfiles/linear.csv:
--------------------------------------------------------------------------------
1 | "chipclass" "LINEAR"
2 |
3 | "aerIn"
4 | "id" "x" "range" "range(2**12)" "type" "1" "f" "X"
5 | "id" "s" "range" "range(1)" "type" "-1" "f" "Y"
6 |
7 |
8 | "pinid" "X" "f" "x"
9 | "pinid" "Y" "f" "s"
10 | "pinlayout" "X11 X10 X9 X8 X7 X6 X5 X4 X3 X2 X1 X0 Y0"
11 |
12 | "aerOut"
13 | "id" "x" "range" "range(2**12)" "type" "'1'" "f" "X"
14 |
15 |
16 | "pinid" "X" "f" "x"
17 | "pinlayout" "X11 X10 X9 X8 X7 X6 X5 X4 X3 X2 X1 X0"
18 |
19 | Count PIN PKG CircuitBlock SignalName FET BiasType PadType Range SimulationValue Description Channel Shared with
20 |
--------------------------------------------------------------------------------
/test/testComAPI.py:
--------------------------------------------------------------------------------
1 | #!/bin/python
2 | #-----------------------------------------------------------------------------
3 | # File Name : testComAPI.py
4 | # Purpose:
5 | #
6 | # Author: Emre Neftci
7 | #
8 | # Creation Date : 05-06-2013
9 | # Last Modified : Wed 05 Jun 2013 06:47:18 PM PDT
10 | #
11 | # Copyright : (c)
12 | # Licence : GPLv2
13 | #-----------------------------------------------------------------------------
14 |
15 | from pyNCS.ComAPI import *
16 |
17 | class Communicator(BatchCommunicatorBase):
18 | def run(self, stimulus=None, duration=None, context_manager=None):
19 | return stimulus
20 |
21 |
--------------------------------------------------------------------------------
/docs/examples/examples.txt:
--------------------------------------------------------------------------------
1 | Examples
2 | ========
3 |
4 | Contents:
5 |
6 | .. :toctree:
7 | :maxdepth: 2
8 |
9 | reservoir.txt
10 |
11 | Hello world
12 | -----------
13 |
14 | Feed-forward network: Antennal Lobe of insects
15 | ----------------------------------------------
16 |
17 | Recurrent network: Winner-Take-All
18 | ----------------------------------
19 |
20 | Recurrent network: reservoir
21 | ----------------------------
22 |
23 | Learning: attractors
24 | --------------------
25 |
26 | Learning: perceptron
27 | --------------------
28 |
29 | Learning: thalamo-cortical model
30 | --------------------------------
31 |
--------------------------------------------------------------------------------
/src/pyNCS/data/setuptype.dtd:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/test/setupfiles/test_setuptype.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/test/chipfiles/ifmem.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from distutils.core import setup
3 | import os
4 |
5 | setup(name='pythonNCS',
6 | version='20170129',
7 | description='Python Neurormophic Chips and Systems',
8 | author='Sadique Sheik, Emre Neftci, Fabio Stefanini, Giacomo Indiveri',
9 | author_email='sadique@ini.phys.ethz.ch, eneftci@uci.edu, giacomo@ini.phys.ethz.ch, fabios@ini.phys.ethz.ch',
10 | url='https://github.com/inincs/pyNCS',
11 | download_url='https://github.com/inincs/pyNCS/tarball/stable_20170129',
12 | packages = ['pyNCS', 'pyNCS.pyST', 'pyNCS.api'],
13 | package_dir={'pyNCS' : 'src/pyNCS'},
14 | package_data={'pyNCS' : ['data/*.dtd',
15 | 'data/chipfiles/*.csv',
16 | 'data/chipfiles/*.nhml',
17 | 'data/chipfiles/*.xml']},
18 | )
19 |
--------------------------------------------------------------------------------
/test/biases/defaultBiases_if2dwta:
--------------------------------------------------------------------------------
1 | Aepd 0.6
2 | req_puY 2
3 | req_puX 2
4 | selpu 2.5
5 | selx0 0
6 | selx1 0
7 | selx2 0
8 | selx3 0
9 | selx4 0
10 | selx5 0
11 | sely0 0
12 | sely1 0
13 | sely2 0
14 | sely3 0
15 | sely4 0
16 | muxx0 0
17 | muxx1 0
18 | muxx2 0
19 | muxy0 0
20 | muxy1 0
21 | ringonoff 3.3
22 | nadap 0
23 | nlk 0.17
24 | nlkadap 0.30001
25 | nrf 0.25
26 | nsf 0.6
27 | inj 3.3
28 | nsynlocplswdt 0.45
29 | nsynlocselfw 0
30 | nsynlocselfth 2.75
31 | psynlocselftau 2.4
32 | nsynlocth 2.9
33 | psynloctau 3.05
34 | nsynloclat1 0.0
35 | nsynlocvert1 0
36 | nsynlocvert2 0
37 | nsynaerinhplswdt 0.14
38 | psynaerinhth 0.3
39 | nsynaerinhtau 0.05
40 | psynaerinhw 3.3
41 | nsynaerexcplswdt 0.45
42 | nsynaerexcth0 2.95
43 | psynaerexcw0 0
44 | nsynaerexcwd0 0
45 | psynaerexctau0 3.05
46 | nsynaerexcth1 2.95
47 | psynaerexcw1 0
48 | nsynaerexcwd1 0
49 | psynaerexctau1 3.05
50 | FollBias 0.5
51 | llGnd 0.3
52 |
--------------------------------------------------------------------------------
/test/test_performance.py:
--------------------------------------------------------------------------------
1 | from expSetup import *
2 | import time
3 | #stas=STcsMon[0]
4 | #addrPhysicalExtractDecode(stas,[3073]*10000000);
5 | #
6 | #ad=np.random.randint(0, 10000, 10000000)
7 | #tm=np.random.ranf(10000000)
8 | #t=np.column_stack([ad, tm])
9 | #st=SpikeList(t, range(0,20000))
10 | #
11 |
12 | nsetup = build_setup(setupfile = 'test_performance.xml')
13 |
14 | seq_pop = pyNCS.Population('default', 'Default Population')
15 | seq_pop.populate_all(nsetup, 'seq', 'excitatory')
16 |
17 | fps = 1
18 | stim = seq_pop.soma.spiketrains_poisson(rate=100, duration=1000/fps)
19 | t0 = time.time()
20 | for i in range(max(fps,0)):
21 | out = nsetup.run(stim)
22 | out[0]
23 |
24 | t1 = time.time()-t0
25 | print t1
26 |
27 | print 'Performance is {0} events per second'.format(float(stim[0].raw_data().__len__())/t1*fps)
28 |
29 |
30 | #2**15 neurons, 100 Hz, 1s. Coding, Decoding. 298682 events/second
31 |
32 |
33 |
--------------------------------------------------------------------------------
/docs/general/pyNCS.AerViewer.txt:
--------------------------------------------------------------------------------
1 | AerViewer Package
2 | =================
3 |
4 | :mod:`AerViewer` Package
5 | ------------------------
6 |
7 | .. automodule:: pyNCS.AerViewer
8 | :members:
9 | :undoc-members:
10 | :show-inheritance:
11 |
12 | :mod:`Aer1DViewer` Module
13 | -------------------------
14 |
15 | .. automodule:: pyNCS.AerViewer.Aer1DViewer
16 | :members:
17 | :undoc-members:
18 | :show-inheritance:
19 |
20 | :mod:`Aer2DViewer` Module
21 | -------------------------
22 |
23 | .. automodule:: pyNCS.AerViewer.Aer2DViewer
24 | :members:
25 | :undoc-members:
26 | :show-inheritance:
27 |
28 | :mod:`Updater1D` Module
29 | -----------------------
30 |
31 | .. automodule:: pyNCS.AerViewer.Updater1D
32 | :members:
33 | :undoc-members:
34 | :show-inheritance:
35 |
36 | :mod:`Updater2D` Module
37 | -----------------------
38 |
39 | .. automodule:: pyNCS.AerViewer.Updater2D
40 | :members:
41 | :undoc-members:
42 | :show-inheritance:
43 |
44 |
--------------------------------------------------------------------------------
/src/pyNCS/data/setup.dtd:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/test/chipfiles/tmpdiff64.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/docs/general/pyNCS.pyST.txt:
--------------------------------------------------------------------------------
1 | pyST Package
2 | ============
3 |
4 | :mod:`pyST` Package
5 | -------------------
6 |
7 | .. automodule:: pyNCS.pyST
8 | :members:
9 | :undoc-members:
10 | :show-inheritance:
11 |
12 | :mod:`STas` Module
13 | ------------------
14 |
15 | .. automodule:: pyNCS.pyST.STas
16 | :members:
17 | :undoc-members:
18 | :show-inheritance:
19 |
20 | :mod:`STsl` Module
21 | ------------------
22 |
23 | .. automodule:: pyNCS.pyST.STsl
24 | :members:
25 | :undoc-members:
26 | :show-inheritance:
27 |
28 | :mod:`pyST_globals` Module
29 | --------------------------
30 |
31 | .. automodule:: pyNCS.pyST.pyST_globals
32 | :members:
33 | :undoc-members:
34 | :show-inheritance:
35 |
36 | :mod:`spikes` Module
37 | --------------------
38 |
39 | .. automodule:: pyNCS.pyST.spikes
40 | :members:
41 | :undoc-members:
42 | :show-inheritance:
43 |
44 | :mod:`stgen` Module
45 | -------------------
46 |
47 | .. automodule:: pyNCS.pyST.stgen
48 | :members:
49 | :undoc-members:
50 | :show-inheritance:
51 |
52 |
--------------------------------------------------------------------------------
/src/pyNCS/pyST/__init__.py:
--------------------------------------------------------------------------------
1 | #-----------------------------------------------------------------------------
2 | # Purpose:
3 | #
4 | # Author: Emre Neftci
5 | #
6 | # Copyright : University of Zurich, Giacomo Indiveri, Emre Neftci, Sadique Sheik, Fabio Stefanini
7 | # Licence : GPLv2
8 | #-----------------------------------------------------------------------------
9 | from __future__ import absolute_import
10 | from .STas import events, channelEvents, RawOutput, channelAddressing, addrSpec
11 | from .STas import setDefaultMonChannelAddress, setDefaultSeqChannelAddress,\
12 | getDefaultMonChannelAddress, getDefaultSeqChannelAddress
13 | from .STsl import STCreate
14 | from .spikes import SpikeList, SpikeTrain, merge, merge_spikelists, \
15 | merge_sequencers
16 | from . import pyST_globals
17 | import numpy as np
18 |
19 |
20 | def loadtxt(filename, comments, format='t'):
21 | data = np.loadtxt(filename, comments=comments)
22 | if format == 't':
23 | data = np.fliplr(data)
24 | ev = events(data, atype='l')
25 | id_list = np.unique(ev.get_ad())
26 | return SpikeList(ev.get_adtmev(), id_list)
27 |
--------------------------------------------------------------------------------
/test/chipfiles/sac.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/test/biases/defaultBiases_ifslwta:
--------------------------------------------------------------------------------
1 | psynaerinhw 2.5
2 | nbuf 0.5
3 | psynlocinhth 0.
4 | nsynloclat1 0.
5 | nwta 1.00004577706569009e-01
6 | thmem 0.00000000000000000e+00
7 | pbuf 2.50001373311970676e+00
8 | synaerlo 0.00000000000000000e+00
9 | nsf 0.75
10 | thk1 3.29999999999999982e+00
11 | llGnd 5.99926756694895813e-01
12 | nlpfth 2.99993591210803379e+00
13 | thk2 2.99993591210803379e+00
14 | mux1 0.00000000000000000e+00
15 | nsynaerinhtau 0.1
16 | pinj2 3.3
17 | pinj3 3.3
18 | nlk 0.02
19 | pinj1 3.3
20 | nsynlocinhtau 0.06
21 | pinj4 3.3
22 | nadap 0.0
23 | pinj 3.3
24 | nsynaerpls 0.4
25 | Aepd 6.99981689173723942e-01
26 | nsynstdwd0 0.0
27 | ScanPD 5.99926756694895813e-01
28 | nsynloclat2 0.0
29 | llVdd 3.2
30 | nLearnW 0.00000000000000000e+00
31 | FollBias 3.99967956054016915e-01
32 | psynstdtau 3.08
33 | mux2 0.00000000000000000e+00
34 | mux0 0.00000000000000000e+00
35 | nsynlocth 2.98
36 | nsynaerth 2.85
37 | nplsloc 0.4
38 | nsynexcinh 0.
39 | synaerth 0.00000000000000000e+00
40 | nrf 0.5
41 | thk3 2.79992675669489577e+00
42 | plpftau 2.39995880064087874e+00
43 | nlpfw 0.00000000000000000e+00
44 | psynaertau 2.99993591210803379e+00
45 | synaerhi 1.99999084458686172e+00
46 | nsynstdw1 0.
47 | nsynstdw0 0.
48 | SynPU 2.39995880064087874e+00
49 | nsynaerinhpls 0.14
50 | nsynlocginh 0.5
51 | psynloctau 3.11
52 | pcmp 2.89998168917372379e+00
53 | nplslocinh 0.14
54 | ring1 0.00000000000000000e+00
55 | psynaerlk 3.09999084458686180e+00
56 | nsynlocself 0.00000000000000000e+00
57 | nsynstdwd1 0.00000000000000000e+00
58 | nlkadap 4.99972533760585869e-01
59 | psynaernmda 2.39995880064087874e+00
60 | psynlocinhw 3.3
61 | nsynstdth 2.85
62 |
--------------------------------------------------------------------------------
/docs/index.txt:
--------------------------------------------------------------------------------
1 | .. NCS documentation master file, created by
2 | sphinx-quickstart on Mon Nov 23 16:07:25 2009.
3 | You can adapt this file completely to your liking, but it should at least
4 | contain the root `toctree` directive.
5 |
6 | pyNCS documentation
7 | ===================
8 |
9 |
10 | General
11 | -------
12 |
13 | .. toctree::
14 | :maxdepth: 2
15 |
16 | general/introduction.txt
17 | general/installation.txt
18 | general/tutorial.txt
19 | general/experiments.txt
20 |
21 | Technical
22 | ---------
23 |
24 | .. toctree::
25 | :maxdepth: 2
26 |
27 | general/new_hardware.txt
28 |
29 |
30 | Examples
31 | --------
32 |
33 | .. toctree::
34 | :maxdepth: 1
35 |
36 | examples/attractor.txt
37 | examples/reservoir.txt
38 |
39 | API reference
40 | -------------
41 |
42 | .. toctree::
43 | :maxdepth: 99
44 |
45 | general/modules.txt
46 |
47 |
48 | .. Indices and tables
49 | .. ==================
50 | ..
51 | .. * :ref:`genindex`
52 | .. * :ref:`modindex`
53 | .. * :ref:`search`
54 |
55 |
56 | NCS specific documentation
57 | ==========================
58 |
59 | Please refer to http://ncs.ethz.ch/ncs for more information.
60 |
61 | Measurement and tuning
62 | ----------------------
63 |
64 | .. toctree::
65 | :maxdepth: 2
66 |
67 | general/pyosc.txt
68 | general/pytune.txt
69 |
70 |
71 | Plasticity on hardware
72 | ----------------------
73 |
74 | .. toctree::
75 | :maxdepth: 2
76 |
77 | general/learning.txt
78 |
79 | Technical
80 | ---------
81 |
82 | .. toctree::
83 | :maxdepth: 2
84 |
85 | general/hardware_setup.txt
86 | general/spcm.txt
87 | general/troubleshooting.txt
88 |
--------------------------------------------------------------------------------
/docs/general/pyNCS.txt:
--------------------------------------------------------------------------------
1 | pyNCS Package
2 | =============
3 |
4 | :mod:`pyNCS` Package
5 | --------------------
6 |
7 | .. automodule:: pyNCS.__init__
8 | :members:
9 | :undoc-members:
10 | :show-inheritance:
11 |
12 | :mod:`ComAPI` Module
13 | --------------------
14 |
15 | .. automodule:: pyNCS.api.ComAPI
16 | :members:
17 | :undoc-members:
18 | :show-inheritance:
19 |
20 | :mod:`ConfAPI` Module
21 | ---------------------
22 |
23 | .. automodule:: pyNCS.api.ConfAPI
24 | :members:
25 | :undoc-members:
26 | :show-inheritance:
27 |
28 | :mod:`chip_v2` Module
29 | ---------------------
30 |
31 | .. automodule:: pyNCS.chip_v2
32 | :members:
33 | :undoc-members:
34 | :show-inheritance:
35 |
36 | :mod:`connection` Module
37 | ------------------------
38 |
39 | .. automodule:: pyNCS.connection
40 | :members:
41 | :undoc-members:
42 | :show-inheritance:
43 |
44 | :mod:`experimentTools` Module
45 | -----------------------------
46 |
47 | .. automodule:: pyNCS.experimentTools
48 | :members:
49 | :undoc-members:
50 | :show-inheritance:
51 |
52 | :mod:`group` Module
53 | -------------------
54 |
55 | .. automodule:: pyNCS.group
56 | :members:
57 | :undoc-members:
58 | :show-inheritance:
59 |
60 | :mod:`mapping` Module
61 | ---------------------
62 |
63 | .. automodule:: pyNCS.mapping
64 | :members:
65 | :undoc-members:
66 | :show-inheritance:
67 |
68 | :mod:`monitors` Module
69 | ----------------------
70 |
71 | .. automodule:: pyNCS.monitors
72 | :members:
73 | :undoc-members:
74 | :show-inheritance:
75 |
76 | :mod:`neurosetup` Module
77 | ------------------------
78 |
79 | .. automodule:: pyNCS.neurosetup
80 | :members:
81 | :undoc-members:
82 | :show-inheritance:
83 |
84 | :mod:`population` Module
85 | ------------------------
86 |
87 | .. automodule:: pyNCS.population
88 | :members:
89 | :undoc-members:
90 | :show-inheritance:
91 |
92 | Subpackages
93 | -----------
94 |
95 | .. toctree::
96 |
97 | pyNCS.pyST
98 |
99 |
--------------------------------------------------------------------------------
/test/chipfiles/sac.csv:
--------------------------------------------------------------------------------
1 | "chipclass" "SAC"
2 |
3 | "aerIn"
4 | "id" "x" "range" "range(32)" "type" "1" "f" "X"
5 | "id" "y" "range" "range(32)" "type" "1" "f" "Y"
6 | "id" "s" "range" "range(1)" "type" "-1" "f" "0*X"
7 |
8 |
9 | "pinid" "X" "f" "x"
10 | "pinid" "Y" "f" "y"
11 | "pinlayout" "X4 X3 X2 X1 X0 Y4 Y3 Y2 Y1 Y0"
12 |
13 | "aerOut"
14 | "id" "x" "range" "range(2**5)" "type" "1" "f" "X"
15 | "id" "y" "range" "range(2**5)" "type" "1" "f" "Y"
16 |
17 |
18 | "pinid" "X" "f" "x"
19 | "pinid" "Y" "f" "y
20 | "pinlayout" "X4 X3 X2 X1 X0 Y4 Y3 Y2 Y1 Y0"
21 |
22 | Count PIN # PKG # Circuit Block Signal Name FET Bias Type Pad Type Range Simulation value Description Channel Shared with
23 | 1 50 aer ReqpuX dac 2.2 58
24 | 2 49 aer ReqpuY dac 2.2 59
25 | 3 66 aer AERpd dac 0.483 56
26 | 4 2 aer PIXpd dac 0.6 94
27 | 5 1 aer PIXpu dac 2.6 95
28 | 6 23 scanner SX0 dac 0.0 88
29 | 7 22 scanner SX1 dac 0.0 89
30 | 8 21 scanner SX2 dac 0.0 90
31 | 9 20 scanner SX3 dac 0.0 91
32 | 10 19 scanner SX4 dac 0.0 92
33 | 11 101 scanner SY0 dac 0.0 7
34 | 12 102 scanner SY1 dac 0.0 8
35 | 13 103 scanner SY2 dac 0.0 9
36 | 14 104 scanner SY3 dac 0.0 10
37 | 15 105 scanner SY4 dac 0.0 11
38 | 16 82 aer NETpu dac 2.79 0
39 | 17 31 wta ADAP dac 3.3 79
40 | 18 33 wta LK dac 0.194 77
41 | 19 32 wta LKCA dac 0.0 78
42 | 20 29 wta RF dac 0.285 82
43 | 21 30 wta SF dac 0.598 80
44 | 22 39 wta THRinh dac 0.3 67
45 | 23 40 wta Winh dac 2.253 66
46 | 24 41 wta TAUinh dac 0.2 65
47 | 25 44 wta W0exc dac 2.38 86
48 | 26 46 aer SYNpu dac 2.9 60
49 | 27 45 wta Wstd dac 0.369 62
50 | 28 43 wta THR dac 2.9 63
51 | 29 42 wta TAU dac 3.0 64
52 | 30 35 wta WTAbias dac 0.405 74
53 | 31 34 wta exc_wta dac 0.0 76
54 | 32 36 wta inh_wta dac 3.3 72
55 | 33 37 wta LIM dac 2.635 70
56 | 34 38 wta HYST dac 2.55 68
57 | 35 28 aer FollowBias dac 0.616 84
58 | 36 84 wta STIM dac 3.3 1
59 | 37 98 test pen dac 0.0 6
60 | 38 97 test pep dac 3.3 5
61 | 39 93 test gthr dac 3.3 4
62 | 40 92 test nmdathr dac 3.3 3
63 | 41 121 wta ref dac 3.3 2
64 |
--------------------------------------------------------------------------------
/test/chipfiles/ifmem.csv:
--------------------------------------------------------------------------------
1 | "chipclass" "ifmem"
2 |
3 | "aerIn"
4 | "id" "x" "range" "range(32)" "type" "1" func X
5 | "id" "s" "range" "range(32)" "type" "-1" func Y
6 | "id" "t" "range" "range(8)" "type" "-1" func Z
7 | pinid X func x
8 | pinid Y func s
9 | pinid Z func t
10 | "pinlayout" " X4 X3 X2 X1 X0 Y4 Y3 Y2 Y1 Y0 Z2 Z1 Z0 "
11 |
12 | "aerOut"
13 | "id" "x" "range" "range(32)" "type" "1" func X
14 | pinid X func x
15 | "pinlayout" "X4 X3 X2 X1 X0"
16 |
17 |
18 |
19 | "Count" "Pad#" "Pin#" "Circuit Block" "Signal Name" "FET" "BIAS type" "PAD type" "Range" "Simulation value" "Description" "Channel#"
20 | 1 "gbNSath" "dac" 0
21 | 2 "gbSEtau" "dac" 1
22 | 3 "gbSEnmda" "dac" 2
23 | 4 "gbSEg" "dac" 3
24 | 5 "gbSEdh" "dac" 4
25 | 6 "gbSEdv" "dac" 5
26 | 7 "gbSItau" "dac" 6
27 | 8 "gbSIg" "dac" 7
28 | 9 "gbsynwex" "dac" 8
29 | 10 "gbsynwex0" "dac" 9
30 | 11 "gbsynwex1" "dac" 10
31 | 12 "gbsynwex2" "dac" 11
32 | 13 "gbsynwex3" "dac" 12
33 | 14 "gbsynwex4" "dac" 14
34 | 15 "gbSIdv" "dac" 15
35 | 16 "gbSIdh" "dac" 16
36 | 17 "gbNSaw" "dac" 17
37 | 18 "gbNScas" "dac" 18
38 | 19 "gbNSin" "dac" 19
39 | 20 "gbNSrefr" "dac" 20
40 | 21 "gbNSreset" "dac" 21
41 | 22 "gbNStau" "dac" 22
42 | 23 "gbNSth" "dac" 23
43 | 24 "gbSEthr" "dac" 24
44 | 25 "gbNSatau" "dac" 25
45 | 26 "gbSEtauDiff" "dac" 26
46 | 27 "gbSItauDiff" "dac" 27
47 | 28 "gbSIthr" "dac" 28
48 | 29 "gbsynwinh0" "dac" 35
49 | 30 "gbsynwinh1" "dac" 34
50 | 31 "gbsynwinh2" "dac" 33
51 | 32 "gbsynwinh3" "dac" 32
52 | 33 "gbsynwinh4" "dac" 32
53 | 34 "folbias" "dac" 29
54 | 35 "gbAEpd" "dac" 36
55 | 36 "b0" "dac" 52
56 | 37 "b1" "dac" 51
57 | 38 "b2" "dac" 50
58 | 39 "b3" "dac" 49
59 | 40 "b4" "dac" 48
60 | 41 "currentconv" "dac" 47
61 | 42 "scanbias" "bg" 14
62 | 43 "bsynwex0" "bg" 25
63 | 44 "bsynwex1" "bg" 28
64 | 45 "bsynwex2" "bg" 31
65 | 46 "bsynwex3" "bg" 32
66 | 47 "bsynwex4" "bg" 37
67 | 48 "inject" "bg" 9
68 |
--------------------------------------------------------------------------------
/test/expSetup.py:
--------------------------------------------------------------------------------
1 | import pyNCS.pyST as pyST
2 | import time,sys,random
3 | import pyNCS
4 | import numpy as np
5 | import pylab
6 | from pyNCS.neurosetup import NeuroSetup
7 | import warnings
8 |
9 | # C O N F I G # # # # # # # # # # # # # # # # # # # # # #
10 |
11 | et=pyNCS.et
12 |
13 | # set dirnames
14 | def set_default_biases(nsetup=None, biases_dir='biases/'):
15 | for c in nsetup.chips.itervalues():
16 |
17 | filename=''
18 | try:
19 | if not c.virtual:
20 | filename=biases_dir+'defaultBiases_'+c.chipclass.lower()
21 | c.load_parameters(filename)
22 | except IOError as (errno, strerror):
23 | warnings.warn("I/O error({0}): {1}".format(errno, strerror))
24 | warnings.warn("Could not find file {0}".format(filename))
25 | pass
26 |
27 | def build_setup(setupfile = 'test.xml'):
28 | nsetup = NeuroSetup(
29 | 'setupfiles/test_setuptype.xml',
30 | 'setupfiles/'+setupfile,
31 | offline=False)
32 | set_default_biases(nsetup=nsetup, biases_dir='biases/')
33 | return nsetup
34 |
35 | if __name__ == '__main__':
36 | nsetup = build_setup()
37 | nsetup.chips['ifslwta'].set_parameter('pinj', 2.82)
38 |
39 | seq_pop = pyNCS.Population('default', 'Default Population')
40 | seq_pop.populate_by_number(nsetup, 'seq', 'excitatory', 60)
41 |
42 | seq_pop1= seq_pop[:30]
43 | seq_pop2= seq_pop[30:]
44 |
45 | exc_pop = pyNCS.Population('default', 'Default Population')
46 | exc_pop.populate_by_number(nsetup, 'ifslwta', 'excitatory', 60)
47 |
48 | exc_pop1= exc_pop[:30]
49 | exc_pop2= exc_pop[30:]
50 |
51 | mon = nsetup.monitors.import_monitors_otf([exc_pop1, exc_pop2])
52 |
53 | c1=pyNCS.PConnection(seq_pop1, exc_pop1,'excitatory0', 'random_all2all',{'p':1.0})
54 | c2=pyNCS.PConnection(seq_pop2, exc_pop2,'excitatory1', 'random_all2all',{'p':.1})
55 |
56 | nsetup.chips['ifslwta'].set_parameter('nsynstdw0',.45)
57 | nsetup.chips['ifslwta'].set_parameter('nsynstdw1',.45)
58 | stim = seq_pop.soma.spiketrains_inh_poisson(np.array([np.linspace(1,1000,10)]*60), np.linspace(0,1000,10))
59 |
60 | out = nsetup.run(stim)
61 | from pylab import *
62 | ion()
63 | pyNCS.monitors.RasterPlot(mon)
64 | pyNCS.monitors.MeanRatePlot(mon)
65 |
--------------------------------------------------------------------------------
/src/pyNCS/api/loopbackAPI.py:
--------------------------------------------------------------------------------
1 | #-----------------------------------------------------------------------------
2 | # Purpose:
3 | #
4 | # Author:
5 | #
6 | # Copyright : University of Zurich, Giacomo Indiveri, Emre Neftci, Sadique Sheik, Fabio Stefanini
7 | # Licence : GPLv2
8 | #-----------------------------------------------------------------------------
9 |
10 | #Path for recording experimental data
11 | from ComAPI import *
12 | import collections
13 |
14 | class BatchCommunicator(BatchCommunicatorBase):
15 | def __init__(self):
16 | '''
17 | The BatchCommunicator API defined by the NCS tools.
18 |
19 | Usage:
20 | >>> c = Communicator(host = 'localhost', devnum = 0)
21 | >>> c.run()
22 | '''
23 |
24 | # Inputs:
25 | # *host:* the hostname of the computer where the hardware is attached (default:
26 | # localhost).
27 | ResourceManagerBase.__init__(self)
28 | RecordableCommunicatorBase.__init__(self)
29 | self.t_last = 0.
30 | self.queue = collections.deque()
31 |
32 | def run(self, stimulus=None, duration=None, context_manager=None):
33 | '''
34 | Loopback API simply puts an event packet in the API, and reads it back
35 | '''
36 | stimulus[:,1] = stimulus[:,1].cumsum()+self.t_last
37 | t_last = stimulus[-1,1]
38 | self.queue.appendleft(stimulus)
39 | return self.queue.pop()
40 |
41 |
42 | class ContinuousCommunicator(BatchCommunicator):
43 |
44 | def mon(self, duration=None):
45 | #IMPLEMENT
46 | '''
47 | Returns one event packet from the queue independent of the durection
48 | '''
49 | return self.queue.pop()
50 |
51 |
52 | def stim(self, stimulus, duration=None, context_manager=None, **stim_kwargs):
53 | #IMPLEMENT
54 | '''
55 | Adds an event packet to the queue, independent of duration and reads it.
56 | '''
57 | stimulus[:,1] = stimulus[:,1].cumsum()+ self.t_last
58 | t_last = stimulus[-1,1]
59 | self.queue.appendleft(stimulus)
60 | return self.mon()
61 |
62 | def run(self, stimulus=None, duration=None, context_manager=None):
63 | '''
64 | Loopback API simply puts an event packet in the API, and reads it back
65 | '''
66 | return self.stim(stimulus)
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | Communicator = ContinuousCommunicator
75 |
--------------------------------------------------------------------------------
/docs/examples/reservoir.txt:
--------------------------------------------------------------------------------
1 | Reservoir
2 | =========
3 |
4 | Description
5 | -----------
6 |
7 | A reservoir is a pool of units with random connections. The connections are
8 | such that the activity of the network is "at the edge of chaos". This concept
9 | forms the basis of a particular type of neural networks called
10 | liquid-state-machines (LSM).
11 |
12 | - liquid state machine
13 | - input
14 | - read-out
15 | - LSM with LIF neurons?
16 |
17 | Implementation
18 | --------------
19 |
20 | - preliminary operations::
21 |
22 | import blabla
23 | import pyNCS
24 |
25 | nsetup = pyNCS.NeuroSetup('my_setuptype.xml', 'my_setup.xml')
26 |
27 | - create a population::
28 |
29 | number_of_units = 500
30 | res = pyNCS.Population('', '')
31 | res.populate_by_number(nsetup,
32 | 'my_chip',
33 | 'my_neuron',
34 | number_of_units)
35 |
36 | - connect the units::
37 |
38 | C_res = pyNCS.Connection(res, res, 'excitatory0', fashion='random_all2all')
39 |
40 | - create input::
41 |
42 | inp = pyNCS.Population('', '')
43 | inp.populate_by_id(nsetup,
44 | 'my_sequencer',
45 | 'my_neuron',
46 | range(5, 10))
47 |
48 | - connect the input to the reservoir::
49 |
50 | C_inp = pyNCS.Connection(inp, res, 'excitatory1') # default fashion is one2one
51 |
52 | - make the input spike::
53 |
54 | pattern1 = inp.soma.spiketrains_poisson(random(len(inp)), duration=500)
55 |
56 | - prepare the hardware::
57 |
58 | nsetup.chips[res.neuronblock.neurochip.id].loadBiases('biases/reservoir.biases')
59 | # the following is equivalent to the previous statement
60 | res.neuronblock.neurochip.loadBiases('biases/reservoir.biases')
61 |
62 | nsetup.mapping.write() # connections where automatically appended
63 |
64 | - unleash hell::
65 |
66 | # stimulus lasts for 500ms but we want to record more, say 5s
67 | out = nsetup.stimulate(pattern1, tDuration=5000)
68 |
69 | - plot (with monitors is a lot easier and faster!)::
70 |
71 | # the output
72 | out[out.soma.channel].raster_plot()
73 | # external input and recurrent input
74 | imshow(out[out.synapses.channel].firing_rate(50)) # 50ms time-bin
75 | # input stimulus
76 | pattern1[inp.soma.channel].raster_plot()
77 |
78 | Parameters
79 | ----------
80 |
81 | The parameters for a good reservoir are... ?
82 |
--------------------------------------------------------------------------------
/docs/general/experiments.txt:
--------------------------------------------------------------------------------
1 | Doing real experiments
2 | ======================
3 |
4 | Structure
5 | ---------
6 |
7 | For highly complex experiments it is useful to split the scripts
8 | into several files. We normally try to follow the scheme below.
9 |
10 | Folders:
11 |
12 | :Results:
13 | contains pickles of the results under nicely-named folders
14 | :biases:
15 | bias (text) files of the chips
16 | :setupfiles:
17 | xml files of the setups (*)
18 | :chipfiles:
19 | csv and xml files representing the chips (*)
20 |
21 | (*) these folders are usually in a common folder somewhere else because they are
22 | not experiment dependent.
23 |
24 | Files and correspondent actions:
25 |
26 | :expSetup:
27 | load the setup
28 | :expMap:
29 | prepare connectivity
30 | :expPop:
31 | create populations
32 | :expStim:
33 | load data set and convert into AER
34 | :expTools:
35 | useful functions, code snippets, ...
36 | :expOsc:
37 | prepare acquisition of analog signals if needed
38 | :expMon:
39 | define monitors (?)
40 | :expRun:
41 | run the experiment and save values
42 | :expData:
43 | analysis of the data
44 | :expPlot:
45 | plot data
46 |
47 | Experiment tools
48 | ----------------
49 |
50 | We developed a specific class to save the data of our experiments.
51 |
52 | Save
53 | ~~~~
54 |
55 | ::
56 |
57 | et = pyNCS.et
58 | et.mksavedir() # creates a new folder under Results/
59 | et.globaldata.variable_to_be_saved = v1
60 | et.globaldata.an_other_one = v4
61 | et.save() # saves everything from globaldata and all expXXX scripts.
62 |
63 | Some comments. The ``Results`` folder has to be created in advance. The function
64 | ``mksavedir`` creates, by default, a folder of the format ``NNN__DD-MM-YYYY``.
65 | You can assign every `pickable` variable you want to globaldata attributes. The
66 | ``save`` function saves:
67 |
68 | - all the python files starting by ``exp`` in a single ``tar.gz``
69 | file inside the new folder
70 | - a single pickle of ``et.globaldata``
71 | - an empty file with the time of the experiment as name
72 |
73 | .. warning:: Don't forget to save chip biases!
74 |
75 | Load
76 | ~~~~
77 |
78 | ::
79 |
80 | loaded_data = pyNCS.et
81 | et.globaldata.directory = 'Results/128__19-04-2011'
82 | et.globaldata = et.globaldata.load()
83 |
84 | The ``load`` functions grabs the pickle from the specified directory. You can
85 | find the variables you saved in ``et.globaldata``.
86 |
--------------------------------------------------------------------------------
/src/pyNCS/api/BaseConfAPI.py:
--------------------------------------------------------------------------------
1 | #-----------------------------------------------------------------------------
2 | # Purpose:
3 | #
4 | # Author:
5 | #
6 | # Copyright : University of Zurich, Giacomo Indiveri, Emre Neftci, Sadique Sheik, Fabio Stefanini
7 | # Licence : GPLv2
8 | #-----------------------------------------------------------------------------
9 | #ConfAPI
10 | #Biases and mapper
11 | #Api for modules having pyAMDA-like functionality
12 | #Api for modules having pyAEX-like functionality
13 |
14 | from types import GeneratorType # For checking generator type
15 | from contextlib import contextmanager
16 | from lxml import etree
17 | import warnings
18 |
19 | class Parameter:
20 | def __init__(self, parameters, configurator):
21 | '''
22 | Parameter(parameters, configurator)
23 | parameters: dictionary of parameters and values
24 | This object is designed to be used with the configurator to set parameters
25 | '''
26 | self.param_data = dict(parameters)
27 | self.configurator = configurator
28 | self.SignalName = self.param_data['SignalName']
29 |
30 | def __str__(self):
31 | return str(self.param_data)
32 |
33 | def __getNHML__(self):
34 | '''
35 | Returns lxml.etree.Element representatoin of this parameter
36 | '''
37 | doc = etree.Element('parameter')
38 | for n, v in self.param_data.items():
39 | doc.attrib[n] = str(v)
40 | return doc
41 |
42 | def __parseNHML__(self, doc):
43 | '''
44 | Parse xml file or element tree to generate the object
45 | '''
46 | if isinstance(doc, str):
47 | # parse the file
48 | doc = etree.parse(doc).getroot()
49 | else:
50 | # assuming doc is an lxml Element object.
51 | assert doc.tag == 'parameter'
52 | self.param_data = dict(doc.attrib)
53 | for k, v in self.param_data.items():
54 | try:
55 | v = float(v)
56 | except:
57 | pass
58 | self.param_data[k] = v
59 | self.SignalName = self.param_data['SignalName']
60 |
61 | def getValue(self):
62 | return self.configurator.get_parameter(self.param_data['SignalName'])
63 |
64 | def setValue(self, value):
65 | x = self.configurator.set_parameter(self.param_data['SignalName'], value)
66 | return x
67 |
68 | v = property(getValue, setValue)
69 |
70 |
--------------------------------------------------------------------------------
/test/chipfiles/if2dwta.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/src/pyNCS/__init__.py:
--------------------------------------------------------------------------------
1 | #-----------------------------------------------------------------------------
2 | # Purpose:
3 | #
4 | # Author:
5 | #
6 | # Copyright : University of Zurich, Giacomo Indiveri, Emre Neftci, Sadique Sheik, Fabio Stefanini
7 | # Licence : GPLv2
8 | #-----------------------------------------------------------------------------
9 | # -*- coding: utf-8 -*-
10 | from __future__ import absolute_import
11 |
12 | from .chip_v2 import Chip, NeuronBlock, NeuroChip, Block
13 | from . import experimentTools as et
14 | from .group import AddrGroup, AddrGroupBase
15 | from .population import Population
16 | from .connection import Connection, PConnection
17 | from .mapping import Mapping, PMapping
18 | from .neurosetup import NeuroSetup
19 | from .monitors import Monitors, SpikeMonitor
20 | from .api import ComAPI
21 | from .api import ConfAPI
22 | from . import pyST
23 |
24 | ###################### Utility functions
25 | from functools import wraps
26 |
27 |
28 | class DocInherit(object):
29 | ## {{{ http://code.activestate.com/recipes/576862/ (r1)
30 | """
31 | Docstring inheriting method descriptor
32 |
33 | The class itself is also used as a decorator
34 |
35 | doc_inherit decorator
36 |
37 | Usage:
38 |
39 | class Foo(object):
40 | def foo(self):
41 | "Frobber"
42 | pass
43 |
44 | class Bar(Foo):
45 | @doc_inherit
46 | def foo(self):
47 | pass
48 |
49 | Now, Bar.foo.__doc__ == Bar().foo.__doc__ == Foo.foo.__doc__ == "Frobber"
50 | """
51 |
52 | def __init__(self, mthd):
53 | self.mthd = mthd
54 | self.name = mthd.__name__
55 |
56 | def __get__(self, obj, cls):
57 | if obj:
58 | return self.get_with_inst(obj, cls)
59 | else:
60 | return self.get_no_inst(cls)
61 |
62 | def get_with_inst(self, obj, cls):
63 |
64 | overridden = getattr(super(cls, obj), self.name, None)
65 |
66 | @wraps(self.mthd, assigned=('__name__', '__module__'))
67 | def f(*args, **kwargs):
68 | return self.mthd(obj, *args, **kwargs)
69 |
70 | return self.use_parent_doc(f, overridden)
71 |
72 | def get_no_inst(self, cls):
73 |
74 | for parent in cls.__mro__[1:]:
75 | overridden = getattr(parent, self.name, None)
76 | if overridden:
77 | break
78 |
79 | @wraps(self.mthd, assigned=('__name__', '__module__'))
80 | def f(*args, **kwargs):
81 | return self.mthd(*args, **kwargs)
82 |
83 | return self.use_parent_doc(f, overridden)
84 |
85 | def use_parent_doc(self, func, source):
86 | if source is None:
87 | raise NameError("Can't find {o} in parents".format(self.name))
88 | func.__doc__ = source.__doc__
89 | return func
90 |
91 | doc_inherit = DocInherit
92 |
93 |
94 |
--------------------------------------------------------------------------------
/test/chipfiles/if2dwta.csv:
--------------------------------------------------------------------------------
1 | chipclass IF2DWTA
2 |
3 | aerIn
4 | id x range range(64) type 1 func X>>1
5 | id y range range(32) type 1 func ((Y-(Y%3))<<1)/3+(X&1)
6 | id s range range(3) type -1 func Y%3
7 |
8 |
9 | pinid X func 2*x+(y&1)
10 | pinid Y func s+3*(y>>1)
11 | pinlayout Y0 Y1 Y2 Y3 Y4 Y5 X6 X5 X4 X3 X2 X1 X0
12 |
13 | aerOut
14 | id x range range(64) type 1 func X
15 | id y range range(32) type 1 func Y
16 |
17 |
18 | pinid X func x
19 | pinid Y func y
20 | pinlayout Y4 Y3 Y2 Y1 Y0 X5 X4 X3 X2 X1 X0
21 |
22 | Count PIN PKG CircuitBlock SignalName FET BiasType PadType Range SimulationValue Description Channel Shared with
23 | 1 80 Arbiter Aepd dac 0.8 56
24 | 2 79 Arbiter req_puY dac 2.8 58
25 | 3 78 Arbiter req_puX dac 2.8 60
26 | 4 2 Select selpu dac 2.8 29
27 | 5 64 Select selx0 dac 0 72
28 | 6 65 Select selx1 dac 0 70
29 | 7 66 Select selx2 dac 0 68
30 | 8 67 Select selx3 dac 0 66
31 | 9 68 Select selx4 dac 0 64
32 | 10 69 Select selx5 dac 0 62
33 | 11 96 Select sely0 dac 0 8
34 | 12 97 Select sely1 dac 0 6
35 | 13 98 Select sely2 dac 0 4
36 | 14 99 Select sely3 dac 0 2
37 | 15 100 Select sely4 dac 0 0
38 | 16 9 MUX muxx0 dac 0 35
39 | 17 8 MUX muxx1 dac 0 33
40 | 18 7 MUX muxx2 dac 0 31
41 | 19 36 MUX muxy0 dac 0 37
42 | 20 37 MUX muxy1 dac 0 39
43 | 21 53 RING ringonoff dac 0 74
44 | 22 119 Soma nadap dac 3.3 23
45 | 23 1 Soma nlk dac 0 27
46 | 24 120 Soma nlkadap dac 0 25
47 | 25 117 Soma nrf dac 0.4 19
48 | 26 118 Soma nsf dac 0.7 21
49 | 27 39 Soma inj dac 3.3 41
50 | 28 115 SYNLOC nsynlocplswdt dac 0 15
51 | 29 79 SYNLOC nsynlocselfw dac 0 58
52 | 30 108 SYNLOC nsynlocselfth dac 0 1
53 | 31 110 SYNLOC psynlocselftau dac 3.3 5
54 | 32 109 SYNLOC nsynlocth dac 3.3 3
55 | 33 111 SYNLOC psynloctau dac 3.3 7
56 | 34 116 SYNLOC nsynloclat1 dac 0 17
57 | 35 114 SYNLOC nsynlocvert1 dac 0 13
58 | 36 113 SYNLOC nsynlocvert2 dac 0 11
59 | 37 52 SYNAERINH nsynaerinhplswdt dac 0.3 76
60 | 38 48 SYNAERINH psynaerinhth dac 0 84
61 | 39 49 SYNAERINH nsynaerinhtau dac 0.3 82
62 | 40 50 SYNAERINH psynaerinhw dac 3.3 80
63 | 41 51 SYNAEREXC nsynaerexcplswdt dac 0 78
64 | 42 47 SYNAEREXC nsynaerexcth0 dac 3.3 86
65 | 43 44 SYNAEREXC psynaerexcw0 dac 0.5 92
66 | 44 45 SYNAEREXC nsynaerexcwd0 dac 0.2 90
67 | 45 46 SYNAEREXC psynaerexctau0 dac 2.9 88
68 | 46 43 SYNAEREXC nsynaerexcth1 dac 3.3 94
69 | 47 40 SYNAEREXC psynaerexcw1 dac 0.5 43
70 | 48 41 SYNAEREXC nsynaerexcwd1 dac 0.2 45
71 | 49 42 SYNAEREXC psynaerexctau1 dac 2.9 47
72 | 50 86 Power FollBias dac 0.4 54
73 | 51 54 Power llGnd dac 0 49
74 |
--------------------------------------------------------------------------------
/docs/Makefile:
--------------------------------------------------------------------------------
1 | # Makefile for Sphinx documentation
2 | #
3 |
4 | # You can set these variables from the command line.
5 | SPHINXOPTS =
6 | SPHINXBUILD = sphinx-build
7 | PAPER =
8 | BUILDDIR = _build
9 |
10 | # Internal variables.
11 | PAPEROPT_a4 = -D latex_paper_size=a4
12 | PAPEROPT_letter = -D latex_paper_size=letter
13 | ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
14 |
15 | .PHONY: help clean html dirhtml pickle json htmlhelp qthelp latex changes linkcheck doctest
16 |
17 | help:
18 | @echo "Please use \`make ' where is one of"
19 | @echo " html to make standalone HTML files"
20 | @echo " dirhtml to make HTML files named index.html in directories"
21 | @echo " pickle to make pickle files"
22 | @echo " json to make JSON files"
23 | @echo " htmlhelp to make HTML files and a HTML help project"
24 | @echo " qthelp to make HTML files and a qthelp project"
25 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
26 | @echo " changes to make an overview of all changed/added/deprecated items"
27 | @echo " linkcheck to check all external links for integrity"
28 | @echo " doctest to run all doctests embedded in the documentation (if enabled)"
29 |
30 | clean:
31 | -rm -rf $(BUILDDIR)/*
32 |
33 | html:
34 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
35 | @echo
36 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
37 |
38 | dirhtml:
39 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
40 | @echo
41 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
42 |
43 | pickle:
44 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
45 | @echo
46 | @echo "Build finished; now you can process the pickle files."
47 |
48 | json:
49 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
50 | @echo
51 | @echo "Build finished; now you can process the JSON files."
52 |
53 | htmlhelp:
54 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
55 | @echo
56 | @echo "Build finished; now you can run HTML Help Workshop with the" \
57 | ".hhp project file in $(BUILDDIR)/htmlhelp."
58 |
59 | qthelp:
60 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
61 | @echo
62 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \
63 | ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
64 | @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/NCSdocumentation.qhcp"
65 | @echo "To view the help file:"
66 | @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/NCSdocumentation.qhc"
67 |
68 | latex:
69 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
70 | @echo
71 | @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
72 | @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \
73 | "run these through (pdf)latex."
74 |
75 | changes:
76 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
77 | @echo
78 | @echo "The overview file is in $(BUILDDIR)/changes."
79 |
80 | linkcheck:
81 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
82 | @echo
83 | @echo "Link check complete; look for any errors in the above output " \
84 | "or in $(BUILDDIR)/linkcheck/output.txt."
85 |
86 | doctest:
87 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
88 | @echo "Testing of doctests in the sources finished, look at the " \
89 | "results in $(BUILDDIR)/doctest/output.txt."
90 |
--------------------------------------------------------------------------------
/src/pyNCS/api/ComAPI.py:
--------------------------------------------------------------------------------
1 | #-----------------------------------------------------------------------------
2 | # Purpose:
3 | #
4 | # Author:
5 | #
6 | # Copyright : University of Zurich, Giacomo Indiveri, Emre Neftci, Sadique Sheik, Fabio Stefanini
7 | # Licence : GPLv2
8 | #-----------------------------------------------------------------------------
9 |
10 | #Path for recording experimental data
11 | from __future__ import absolute_import
12 | from .BaseComAPI import *
13 |
14 | class BatchCommunicatorBase(ResourceManagerBase,RecordableCommunicatorBase):
15 | def __init__(self):
16 | '''
17 | The BatchCommunicator API defined by the NCS tools.
18 |
19 | Usage:
20 | >>> c = Communicator(host = 'localhost', devnum = 0)
21 | >>> c.run()
22 | '''
23 |
24 | # Inputs:
25 | # *host:* the hostname of the computer where the hardware is attached (default:
26 | # localhost).
27 | ResourceManagerBase.__init__(self)
28 | RecordableCommunicatorBase.__init__(self)
29 |
30 | def run(self, stimulus=None, duration=None, context_manager=None):
31 | #IMPLEMENT
32 | '''
33 | Stimulate the neuromorphic hardware with event stream *stimulus* and monitor it for *duration* ms
34 | Input:
35 | *stimulus*: a numpy array in (addr, time) format. Type should be uint32 (shape = (-1,2)).
36 | *duration*: monitor duration.
37 | *context_manager*: context manager used to wrap the stimulate function. Useful for syncing with external process.
38 | Output: a numpy array in addr, time format. Type is uint32 (shape = (-1,2)).
39 |
40 | Usage:
41 | >>> events = np.array([[0, 1],[100,200]], dtype='uint32') #addr, time format
42 | >>> run(events, 1500)
43 | '''
44 | return EMPTY_RAW
45 |
46 |
47 | class ContinuousCommunicatorBase(BatchCommunicatorBase):
48 |
49 | def __init__(self, *args, **kwargs):
50 | '''
51 | The Continuous Communicator API defined by the NCS tools.
52 | In addition to the Batch Communicator, this class has a mon() method which can be used to monitor data in real-time.
53 |
54 | Example Usage:
55 | >>> c = Communicator(host = 'localhost', devnum = 0)
56 | >>> c.run()
57 | >>> #Or
58 | >>> c = Communicator(host = 'localhost', devnum = 0)
59 | >>> c.open()
60 | >>> c.mon()
61 | >>> c.close()
62 | '''
63 |
64 | # Inputs:
65 | # *host:* the hostname of the computer where the hardware is attached (default:
66 | # localhost).
67 | BatchCommunicatorBase.__init__(self)
68 |
69 | def mon(self, duration):
70 | #IMPLEMENT
71 | '''
72 | Monitor the neuromorphic hardware for *duration* ms
73 | '''
74 | pass
75 |
76 | def stim(self, stimulus, duration=None, context_manager=None, **stim_kwargs):
77 | #IMPLEMENT
78 | '''
79 | Stimulate the neuromorphic hardware with event stream *stimulus* and monitor it for *duration* ms
80 | Input:
81 | *stimulus*: a numpy array in addr, time format. Type should be uint32 (shape = (-1,2)).
82 | *duration*: monitor duration.
83 | *context_manager*: context manager used to wrap the stimulate function. Useful for syncing with external process.
84 | ***stim_kwargs*: keyward arguments passed to the underlying stimulation modules
85 |
86 | Output: a numpy array in addr, time format. Type is uint32 (shape = (-1,2)).
87 | Usage:
88 | >>> events = np.array([0, 1],[100,200], dtype='uint32') #addr, time format
89 | >>> stim(events, 1500)
90 | '''
91 | return EMPTY_RAW
92 |
93 | Communicator = BatchCommunicatorBase
94 |
--------------------------------------------------------------------------------
/docs/general/hardware_setup.txt:
--------------------------------------------------------------------------------
1 | ---------------------
2 | How to set up a setup
3 | ---------------------
4 |
5 | Here we describe how to configure a new setup from scratch using existing
6 | hardware, i.e. existing VLSI chips and AER boards.
7 |
8 | Equipment
9 | =========
10 |
11 | - The ExCol Mapper (Daniel_)
12 | - AEX boards for monitoring and sequencing spike trains to the chips (Daniel_)
13 | - Optional: tmpdiff128 retina on a parallel AER compatible board
14 | - at least 1 IFSLWTA chip (Giacomo chip) consisting of 128 I&F neurons with 32 synapses each (2 non-plastic exc., 2 inhibitory, 28 plastic synapses implementing the bistable learning synapse) and optional hard-wired "soft Winner-take-all connectivity
15 | - Optional: 1 2DIFWTA (Elisabetta chip) consisting of 64 x 32 I&F, 3 non-plastic synapses per neuron, 1 inhibitory synapse, 2 excitatory synapses
16 |
17 | - boards
18 | - mapper
19 | - chips
20 | - cables
21 | - software
22 | - drivers
23 | - other resources (acquisition board, ...)
24 |
25 | Installation
26 | ============
27 |
28 | Program the mapper
29 | ~~~~~~~~~~~~~~~~~~
30 |
31 | - how to program the mapper
32 |
33 | Program the AEX FPGA
34 | ~~~~~~~~~~~~~~~~~~~~
35 |
36 | Tools you need
37 | ~~~~~~~~~~~~~~
38 |
39 | As many AEX boards as you want (and 6V power suppliers for each...), Xilinx
40 | Platform Cable USB *or parallel*, Windows or Linux machine with drivers for
41 | Xilinx Platform Cable USB, AEX svn repository access rigths. This guide is for
42 | windows machines.
43 |
44 | #. Download the code for the AEXs from the svn repository.
45 | #. Plug-in Xilinx Platform Cable USB.
46 | #. After some dialog windows you will have corrected installed Xilinx drivers.
47 | #. Download ISE Webpack from http://www.xilinx.com/tools/webpack.htm
48 |
49 | Program can be installed on both Linux and Windows machines (see
50 | http://www.xilinx.com/ise/ossupport/index.htm) but driver for usb cable can be
51 | installed very easily on Windows [Note: there's a DVD with all the tools you
52 | need in the box of the Xilinx USB cable]. You'll need to use ISE Project
53 | workspace and Impact. The first compiles the code for the fpga, the other
54 | actually programs the fpga.
55 |
56 | The AEX project file for Xilinx ISE is: ``aex/aex.ise``.
57 | The top VHDL file is: ``aextop/z_top.vhd``.
58 |
59 | Once you downladed the fpga code you can open the file 'aex/aex.ise'. On the
60 | left panel, 'Sources', blablabla.
61 |
62 | Clean everything (i.e. right-click on the top file and remove it) then
63 | ``addsource``, choose your code (for example ``z_top_CH1.vhd``),
64 | make sure it is set as Top Module on the Source panel and be sure that all the
65 | sources for all the single parts are loaded. On the FPGA Design Summary
66 | double-click on Generate Programming file. Wait and get rid of the warnings...
67 | Open Impact and create a new project, open ``aex/z_top.bit``, than choose "create PROM
68 | file", select 4M model, click on left side on Generate file, go to the Boundary
69 | Scan, initialize the chain. assign you brand new .mcs file to the PROM (xcf04s)
70 | and the brand new z_top.bit in /aex to the FPGA (xc3s500e). Right click and
71 | Program both devices. After programming the xc3s500e you could see changes in
72 | leds state. You did it! In future you can use Verify insted of Program in
73 | order to compare what\'s on the FPGA and what\'s on your code.
74 |
75 | If you want to change the routing scheme, have a look at `Reprogramming AEX`_.
76 |
77 | .. _Reprogramming AEX: aex_reprogramming.html
78 |
79 | Power-cycle
80 | ~~~~~~~~~~~
81 |
82 | There is a particular power cycle that one must respect:
83 |
84 | #. plug all the serial cables in the correct manner
85 | #. plug all USB cables, first the 0 channel board (it will be seen as
86 | `/dev/aerfx0`)
87 | #. Power up the AEX boards
88 | #. Turn on the AMDA boards (first main the daughter)
89 | #. Turn on the aex server
90 |
91 | The AMDA server starts automatically when plugging the first AMDA board. The
92 | AEX server have to be explicitly installed.
93 | Check that server are on::
94 |
95 | $> ps aux | grep Serv
96 | fabios 24743 20.1 0.4 54800 8320 pts/1 Sl+ 11:44 0:02 python Server.py
97 | root 31477 0.0 0.3 166532 6768 ? S>> Addr=[range(20,30),0,0]
57 | >>> setup.seq.addrPhysicalConstruct({0:Addr})
58 | array([5120, 5376, 5632, 5888, 6144, 6400, 6656, 6912, 7168, 7424], dtype=uint32)
59 |
60 | * Logical addresses, python floats, used by software such as SpikeLists. It has the advantage of convenientlyrepresenting complicated addresses in a single floating number. Example:
61 |
62 | .. code-block:: python
63 |
64 | #This creates the logical addresses: The addresses correspond to row 20 to 30, column 0, polarity 0 of the retina.
65 |
66 | >>> setup.seq[0].addrLogicalConstruct(Addr)
67 |
68 | array([ 20., 21., 22., 23., 24., 25., 26., 27., 28., 29.],dtype='float')
69 |
70 | or if you have several chips:
71 |
72 | .. code-block:: python
73 |
74 | #This creates the logical addresses: The addresses correspond to row 20 to 30, column 0, polarity 0 of the retina.
75 |
76 | >>> setup.seq.addrLogicalConstruct(Addr)
77 |
78 | {1:array([ 20., 21., 22., 23., 24., 25., 26., 27., 28., 29.], dtype=float)}
79 |
80 | * Human Readable addresses do not exist per se. It is only a method to conveniently define/decode physical or logical. In fact, it corresponds to the ``Addr`` variable in the examples above.
81 |
82 | *Remark:* There exists function for extracting and constructing physical and logical addresses. Construction and Extraction are both meant from the point of view of Human Readable addresses.
83 |
84 | *Remark:* Technically there exists functions for translating from physical to logical directly (without using extraction/construction functions). But these are intended for internal use only.
85 |
86 |
87 | .. Using pyST for creating mappings
88 | .. ________________________________
89 | ..
90 | ..
91 | .. Using NeuroTools in combination with pyST
92 | .. _________________________________________
93 |
94 |
95 | .. _NeuroTools: http://neuralensemble.org/trac/NeuroTools
96 | .. _pyNCS: pyncs.html
97 |
98 |
99 |
100 |
101 |
--------------------------------------------------------------------------------
/src/pyNCS/connection.py:
--------------------------------------------------------------------------------
1 | #-----------------------------------------------------------------------------
2 | # Purpose:
3 | #
4 | # Author: Fabio Stefanini
5 | #
6 | # Copyright : University of Zurich, Giacomo Indiveri, Emre Neftci, Sadique Sheik, Fabio Stefanini
7 | # Licence : GPLv2
8 | #-----------------------------------------------------------------------------
9 | from __future__ import absolute_import
10 | import numpy as np
11 | import pylab
12 |
13 | from .mapping import Mapping, PMapping
14 |
15 |
16 | class Connection(object):
17 | """
18 | A class representing the connections between populations.
19 | """
20 | def __init__(self, popsrc, popdst, synapse,
21 | fashion='one2one',
22 | fashion_kwargs={},
23 | connection_kwargs={},
24 | append=True,
25 | setup=None):
26 | """
27 | - popsrc: source population
28 | - popdst: destination population
29 | - synapse: on which synapse to connect
30 | - fashion: type of connectivity
31 | - fashion_kwargs: arguments for fashion-type connectivity
32 | - append: whether to append this connection to the setup mapping table
33 | - setup: specify setup if different from popsrc.setup
34 | """
35 | self.mapping = self._create_mapping(popsrc, popdst, synapse)
36 | self.mapping.connect(
37 | popsrc.soma,
38 | popdst.synapses[synapse],
39 | connection_kwargs = connection_kwargs,
40 | fashion=fashion,
41 | fashion_kwargs=fashion_kwargs)
42 | self.mapping.prepare()
43 | if setup is None:
44 | setup = popsrc.setup
45 | if append:
46 | setup.mapping.merge(self.mapping)
47 |
48 | self.synapse = synapse
49 | self.popsrc = popsrc
50 | self.popdst = popdst
51 | self.connection_kwargs = connection_kwargs
52 |
53 | def _create_mapping(self, popsrc, popdst, synapse):
54 | return Mapping(popsrc.name + '_to_' + popdst.name,
55 | 'Connects %s to %s on synapse \'%s\'.' %
56 | (popsrc.name, popdst.name, synapse))
57 |
58 | def __len__(self):
59 | return len(self.mapping.mapping)
60 |
61 | def __repr__(self):
62 | return "Connection object: {0} -> {1} via {2}".format(self.popsrc.name,
63 | self.popdst.name,
64 | self.synapse)
65 |
66 |
67 | def plot(self):
68 | '''
69 | plots the connectivity
70 | '''
71 | srcindx = {j:i for i,j in enumerate(self.popsrc.soma.paddr)}
72 | dstindx = {j:i for i,j in enumerate(self.popdst.synapses[self.synapse].paddr)}
73 | conn_matrix = np.zeros((len(self.popdst.synapses[self.synapse]),
74 | len(self.popsrc.soma)))
75 | for src, dst in np.array(self.mapping.mapping)[:,:2]:
76 | conn_matrix[dstindx[dst], srcindx[src]] += 1
77 | pylab.colorbar(pylab.pcolor(conn_matrix))
78 | pylab.xlabel(self.popsrc.name)
79 | pylab.ylabel(self.popdst.name)
80 |
81 | # def __connect_one2one__(self, popsrc, popdst, synapse, syn_ids=[0]):
82 | # """
83 | # Connects in a one to one fashion. Every source neuron connects to one
84 | # synapse on the destination.
85 | # - syn_ids: array of synapses into which to connect
86 | # """
87 | # nsrc = len(syn_ids)
88 | # ndst = len(popdst[0].synapses[synapse])
89 | # [self.mapping.connect(popsrc.soma[i::nsrc],
90 | # popdst.synapses[synapse][i::ndst])
91 | # for i in syn_ids]
92 |
93 | # def activate(self, setup=None):
94 | # """
95 | # Shortcut function to apply connections over-writing the existing ones.
96 | # See also NeuroSetup.Mapping.import_from_connections().
97 | # - setup: if None, self.setup will be used
98 | # """
99 | # if setup is None:
100 | # self.mapping.write()
101 | # else:
102 | # setup.mapping.import_from_connections(self)
103 | # setup.mapping.write()
104 |
105 |
106 | class PConnection(Connection):
107 | def _create_mapping(self, popsrc, popdst, synapse):
108 | return PMapping(popsrc.name + '_to_' + popdst.name,
109 | 'Connects %s to %s on synapse \'%s\'.' %
110 | (popsrc.name, popdst.name, synapse))
111 |
--------------------------------------------------------------------------------
/docs/general/aex_reprogramming.txt:
--------------------------------------------------------------------------------
1 | Reprogram routing of AEX boards
2 | ===============================
3 |
4 | Those who want to create their own AEX version, have to first checkout the code
5 | from https://x.ethz.ch/svn/aer/fpga
6 |
7 | Therein, the AEX project file for Xilinx ISE is: ``aex/aex.ise``.
8 | The top VHDL file is: ``aextop/z_top.vhd``.
9 |
10 | Once you downladed the fpga code you can open the file 'aex/aex.ise'. On the
11 | left panel, 'Sources', blablabla.
12 |
13 | .. note:: If you encounter problems you can always go back to revision 1564 of
14 | the ``aex.ise`` file, rename it as you want, for example ``aex2.ise``,
15 | and go on with your modifications
16 |
17 | In the top file, at the beginning, just after the entity declaration, you find
18 | all the configuration settings. The configuration is with respect to paths
19 | between the three interfaces, denoted as P, S, U for Parallel, Serial and USB.
20 | There are 3^3 = 9 combinations so 9 possible path to configure. At first, each
21 | path can be enabled or disabled completely. These are the first nine constants,
22 | with the names ``confPathEnableXYxS``, with XY being PP, PS, PU, SP, and so on...
23 |
24 | If ``0`` is assigned to a path, it is disabled.
25 | Then there are four configuration values for each path,
26 |
27 | - confXYFilterRangeMinxDI with default x"00000000"
28 | - confXYFilterRangeMaxxDI with default x"FFFFFFFF"
29 | - confXYOutMaskAndxDI with default x"FFFFFFFF"
30 | - confXYOutMaskOrxDI with default x"00000000"
31 |
32 | with XY being the same as before.
33 | An address A coming to the path is checked to be in the range::
34 |
35 | A >= confXYFilterRangeMinxDI and A >= confFilterRangeMaxxDI
36 |
37 | If not, the address is discarded. If the filter check is passed, A is used to
38 | calculate Anew in the following way::
39 |
40 | Anew <= (A and confXYOutMaskAndxDI) or confXYOutMaskOrxDI
41 |
42 | This gives us the possibility to make the trick. Notice first that we have to
43 | distinguish if an event is input for a chip or output from a chip, because of
44 | monitoring purposes. This reduces the address space. The range filtering is
45 | used by an AEX for checking if an address has to be sent to its chip. The 'or'
46 | mask is used for adding the stamp. The 'and' mask is used for cleaning the bits
47 | before stamping.
48 |
49 | For example, if we had 8 bits, 5 for neurons addressing:
50 |
51 | #. 01011010 (0x5A) comes from the mapper
52 | #. it is for chip number 010 (0x40)
53 | #. this cause activity on chip 010
54 | #. chip 010 stamp its activity with 110 (add 0xC0 to the address)
55 | #. mapper finds 0xC0 + 0x14 and then knows who is the sender
56 | #. mapper maps this activity to someone else...
57 |
58 | Note that each event add an address in the communication loop. If nobody removed
59 | it, the chain would soon saturate. The idea is then to stamp a chip output
60 | address in a different way of a chip input address. * better explanation
61 | please...*
62 |
63 | Each AEX board will have its own configuration because the filter and stamp
64 | change. For example, for Chip1::
65 |
66 | constant confSPFilterRangeMinxDI : std_logic_vector(31 downto 0) :=x"0000A000";
67 | constant confSPFilterRangeMaxxDI : std_logic_vector(31 downto 0) :=x"0000AFFF";
68 | constant confSPOutMaskAndxDI : std_logic_vector(31 downto 0) :=x"FFFF1FFF";
69 | constant confSPOutMaskOrxDI : std_logic_vector(31 downto 0) :=x"00002000";
70 |
71 | The path enabled are PS, PU, SP, SU, US for all the AEXs.
72 |
73 | The files created are in 'fpga/aextop' folder:
74 |
75 | - ``z_top_CH1.vhd``
76 | - ``z_top_CH2.vhd``
77 | - ``z_top_CH3.vhd``
78 | - ``z_top_RS.vhd``
79 |
80 | Notes and common problems in programming AEX
81 | --------------------------------------------
82 |
83 | The ise project file is automagically saved in any moment... If you do
84 | something wrong like removing all the sources on the left panel, this change
85 | will persist even if you close the project without explicitly saving. - At the
86 | end of the process, be sure that only D2 led is on and the others are off. Once
87 | you connect the board to the USB you should se D1 and D3 on and D2 off. Please
88 | notice that this is a possible check but is *not* exhaustive.
89 |
90 | Going further
91 | -------------
92 |
93 | The loop design we described before is the simplest one can think of. This
94 | setup will work with an input (retina or sequencer) and 3 chips, 2Difwta or
95 | ifslwta. An other possibility is to use the fact that ifslwta chips use a
96 | lower number of bits for neurons and synapses addressing. This means that in
97 | principal it is possible to use one retina and up to 6 ifslwta *is it true?*.
98 |
99 | Anyway we implemented this before in order to see if everything is going to
100 | work or not, then after we can think about something more general.
101 |
--------------------------------------------------------------------------------
/docs/general/learning.txt:
--------------------------------------------------------------------------------
1 | Use plastic synapses of ``ifslwta`` chip
2 | ========================================
3 |
4 | Learning algorithm
5 | ------------------
6 |
7 | Read `Fusi et al. 2000, Brader et al. 2007`.
8 |
9 | Learning chip
10 | -------------
11 |
12 | The algorithm above is implemented in the ``ifslwta`` chip. Input spikes
13 | trigger the update of the synaptic weight of that synapse. This operation is
14 | done by an analog circuit which changes the amount of charge stored in a
15 | capacitance which constitutes the weight of that synape.
16 |
17 | Each of the 128 neurons of the ifslwta chip has 32 synapses. Synapses 4 to 31
18 | are plastic, thus there are 32x128=3584 plastic synapses. One can use the
19 | multiplexer to use more synapses for each neuron, thus reducing the number of
20 | neurons (see hardware page of ifslwta for more details). For example, one can
21 | use a multiplexer of 1-0-1 to have 4 neurons with 28*32 learning synapses each.
22 | Notice that also non-plastic synapses will be multiplexed.
23 |
24 | Synaptic matrix class
25 | ---------------------
26 |
27 | We created a class that represent the matrix of synaptic weights on a chip
28 | (tested on ``ifslwta`` chip). Its structure is similar to a
29 | ``pyTune.Parameter`` structure. We explain here only the interesting parts of
30 | it. A ``Wij`` class is already written, ask Fabio_.
31 |
32 | By creating the matrix we mean creating all the populations and connections
33 | that we will need to probe the synaptic weights.
34 |
35 | .. note:: We first need to import the ``Wij`` class because it is not yet
36 | included in the base pyNCS package. We'll assume this class is
37 | implemented in the ``wij.py`` file somewhere.
38 |
39 | ::
40 |
41 | from wij import Wij
42 |
43 | wij = Wij('wij1', 'This is the matrix of synaptic weights on chip1.')
44 | wij.set_context(nsetup, 'ifslwta', 'excitatory',
45 | neurons=range(28),
46 | synapses=range(28))
47 |
48 | As you may have noticed, the weights the class will look at the 28 synapses
49 | of the first 28 ``excitatory`` neurons in ``ifslwta`` chip of the ``nsetup``
50 | setup.
51 |
52 | Read the synaptic weights
53 | -------------------------
54 |
55 | In order to read the matrix of synaptic weights we have to do some...
56 | electrophysiology because there is no way of direct access to them. The way to
57 | do it is to set the parameters of the learning such that the synapses are kept
58 | frozen and then send a stimulus to each synapse. If the synapse state is high
59 | we expect an output from the neuron that is connected to it. If the state is
60 | low we expect no output.
61 |
62 | This procedure relys on -- a lot of -- parameters that has to be set before
63 | doing the actual measure. Explain here...
64 |
65 | Most basic thing, we want to ``get`` the synaptic matrix. There is a method
66 | that does this for us::
67 |
68 | wij_status = wij.get()
69 |
70 | Notice you don't need to assign the value to a variable because the ``get``
71 | function automatically updates the ``wij.state`` variable for you. During the
72 | probing, the system performs the following operations:
73 |
74 | - set multiplexer to [0,0,0]
75 | - prepare stimulus and write mapping on mapper
76 | - "turn off" learning (read below)
77 | - stimulate all the synapses of each neuron sequencially (1 spike per
78 | synapse)
79 | - translate output into binary matrix.
80 |
81 | .. note:: A specific set of biases should be applied in a specific sequence
82 | prior to the stimulation. Ask Fabio_ for these biases.
83 |
84 | The output of the get function is a 28x28 matrix, i.e. the dimensions we
85 | initilized the matrix with. The weights can be visualized by::
86 |
87 | wij.show()
88 |
89 | Set the synaptic weights
90 | ------------------------
91 |
92 | In order to set each synaptic weight to a specific value we must run an
93 | experiment that drives it to the value we want it to be. Even though the
94 | learning algorithm is not deterministic in general (i.e. it relies on the
95 | stochastic behaviour of pre- and post-synaptic activities), we can use it in a
96 | deterministic way by setting some parameter to specific values. For example, if
97 | we want to drive the weight to the high state, we will set the threshold of the
98 | membrane potential to 0 and send some high frequency input: the weight will
99 | receive only potentiation jumps and eventually cross the bi-stability
100 | threshold.
101 |
102 | There is a useful function that sets the weights to all-high or all-low by just
103 | applying a sequence of biases::
104 |
105 | wij.reset(1) # set all to high
106 | wij.reset(0) # set all to zero
107 |
108 | Stop-learning
109 | -------------
110 |
111 | The stop-learning features depends on the post-synaptic neuron's firing rate.
112 | In other words, it depends on something like a Calcium concentration variable.
113 | In the chip, there is a capacitor that integrates the post-synaptic spikes and
114 | 3 comparators modeling the 3 thresholds described on the learning algorithm.
115 | The weight of the plastic synapse is modified by the pre-synaptic spikes only
116 | when the Calcium variable lies within a certain range determined by those
117 | threshold. One can use these threshold to *turn off* the learning when it is
118 | not needed, e.g. we don't want to modify the synaptic weights when we send the
119 | ``get`` stimulus. Use::
120 |
121 | wij.set_learning(0)
122 |
123 | to turn-off synaptic plasticity.
124 |
125 | .. note:: There is no ``set_learning(1)`` because the value of each threshold
126 | could depend on the specific experiment.
127 |
128 | .. _Fabio: fabio.stefanini@ini.phys.ethz.ch
129 |
--------------------------------------------------------------------------------
/src/pyNCS/api/BaseComAPI.py:
--------------------------------------------------------------------------------
1 | #-----------------------------------------------------------------------------
2 | # Purpose:
3 | #
4 | # Author:
5 | #
6 | # Copyright : University of Zurich, Giacomo Indiveri, Emre Neftci, Sadique Sheik, Fabio Stefanini
7 | # Licence : GPLv2
8 | #-----------------------------------------------------------------------------
9 |
10 | #Path for recording experimental data
11 | import numpy, getpass, warnings
12 | EMPTY_RAW = numpy.zeros([0,2], dtype='uint32')
13 | USER = getpass.getuser()
14 |
15 | class ResourceManagerBase(object):
16 | '''
17 | The ResourceManagerBase class is a base class for opening, closing a resource. It is used as parent classes for the configuration, communication and mapping APIs.
18 | The init function takes no arguments by default
19 | '''
20 | def __init__(self):
21 | self._neurosetup = None
22 | self._neurosetup_registered = False
23 | self._isopen = False
24 |
25 | def open(self):
26 | '''
27 | Opens resource
28 | '''
29 | self._isopen = True
30 |
31 | def close(self):
32 | '''
33 | Closes resource
34 | '''
35 | self._isopen = False
36 |
37 | @property
38 | def isopen(self):
39 | return self._isopen
40 |
41 | def __del__(self):
42 | if self.isopen:
43 | self.close()
44 |
45 | @property
46 | def neurosetup(self):
47 | if not self._neurosetup_registered:
48 | warnings.warn('NeuroSetup has not been registered')
49 | return None
50 | else:
51 | return self._neurosetup
52 |
53 | def register_neurosetup(self, neurosetup):
54 | '''
55 | Provides a link to the Neurosetup. This is useful for complex parameter
56 | configuration protocols requiring the sequencing and monitoring of
57 | address-events
58 | '''
59 | self._neurosetup_registered = True
60 | self._neurosetup = neurosetup
61 |
62 | class RecordableCommunicatorBase(object):
63 | REC_PATH = '/tmp/exp_rec_' + USER
64 | REC_FN_SEQ = 'seq'
65 | REC_FN_MON = 'mon'
66 | REC_HEADER_SEQ = '# File format raw address, ISI (us)'
67 | REC_HEADER_MON = '# File format raw address, timestamp (us)'
68 |
69 | def __init__(self):
70 | self._rec_fns = []
71 | self._run_id = 0
72 | self.__reset()
73 | self.del_all()
74 |
75 | def get_exp_rec(self):
76 | '''
77 | Returns the filename where the raw stimated and monitored events are saved.
78 | The filenames for all experiments are returned, and run_id is reset
79 |
80 | Output: list of filenames containing the experiment records (stimulated and monitored events). Additionally, the experiment number is reset.
81 |
82 | '''
83 | #CONVIENIENCE FUNCTION, IMPLEMENTATION NOT REQURIED
84 | import copy
85 | rec_fns = copy.copy(self._rec_fns)
86 | self.__reset()
87 | return rec_fns
88 |
89 | def run_rec(self, stimulus = None, *args, **kwargs):
90 | #CONVIENIENCE FUNCTION, IMPLEMENTATION NOT REQURIED
91 | '''
92 | Stimulate the neuromorphic hardware with event stream *stimulus* and monitor it for *duration* ms.
93 | In addition to the run() function, this function records the experimental data in /tmp/.
94 | The resulting files can be obtained with get_exp_record
95 | This function should be overridden to avoid redundant events file creation.
96 |
97 | Input: (see also run() for more information)
98 | *stimulus*: a numpy array in (addr, time) format. Type should be uint32 (shape = (-1,2)).
99 | *duration*: monitor duration.
100 | *context_manager*: context manager used to wrap the stimulate function. Useful for syncing with external process.
101 | Output: a numpy array in addr, time format. Type is uint32 (shape = (-1,2)).
102 |
103 | Usage:
104 | >>> events = np.array([[0, 1],[100,200]], dtype='uint32') #addr, time format
105 | >>> run_record(events, 1500)
106 | '''
107 | #CONVIENIENCE FUNCTION, IMPLEMENTATION NOT REQUIRED
108 | stim_fn, mon_fn = self.__gen_rec_fns()
109 | #Save stim before in case something goes wrong
110 | self.__save_rec_file(stimulus, stim_fn)
111 | mon_evs = self.run(stimulus = stimulus, *args, **kwargs)
112 | self.__save_rec_file(mon_evs, mon_fn)
113 |
114 | return mon_evs
115 |
116 | def __save_rec_file(self, ev_array, filename):
117 | '''
118 | Save data using np.save, and adds filename in self._record_fns
119 | '''
120 | self._rec_fns.append(filename+'.npy')
121 | numpy.save(filename, ev_array)
122 |
123 | self._run_id += 1
124 |
125 | def __gen_rec_fns(self):
126 | '''
127 | Generate filenames for recording
128 | '''
129 | #Get username
130 |
131 |
132 | import time
133 | N = self._run_id
134 | current_time_str = time.strftime("__" + "%d-%m-%Y-%H:%M:%S", time.localtime())
135 | filename = self.REC_PATH + '_{2}_{0}__run{1}'
136 | stim_fn = filename.format(current_time_str, N, self.REC_FN_SEQ)
137 | mon_fn = filename.format(current_time_str, N, self.REC_FN_MON )
138 | return stim_fn, mon_fn
139 |
140 | def __reset(self):
141 | self._run_id = 0
142 | self._rec_fns = []
143 | return None
144 |
145 | def reset(self):
146 | #CONVIENIENCE FUNCTION, IMPLEMENTATION NOT REQURIED
147 | pass
148 |
149 | def del_all(self):
150 | import glob, os
151 | fn_to_del = glob.glob(self.REC_PATH+'*')
152 | for f in fn_to_del:
153 | os.remove(f)
154 |
155 | def __del__(self):
156 | self.del_all()
157 |
158 | def run(self, *args, **kwargs):
159 | return EMPTY_RAW
160 |
161 |
162 |
163 |
--------------------------------------------------------------------------------
/src/pyNCS/api/IFSLWTA_brian_model.py:
--------------------------------------------------------------------------------
1 | import brian_no_units
2 | from brian.units import *
3 | from brian.group import *
4 | import time
5 | import scipy.signal as sg
6 | import scipy.stats as stats
7 | import numpy as np
8 | from brian.stdunits import *
9 | from brian.network import run, Network, network_operation
10 | from brian.connections.connection import Connection
11 | from brian.directcontrol import SpikeGeneratorGroup
12 | from brian.clock import defaultclock
13 | from brian.equations import Equations
14 | from brian.neurongroup import NeuronGroup
15 | from brian.monitor import SpikeMonitor, StateMonitor
16 |
17 |
18 | defaultclock.dt = 0.0001*second
19 | #Network Parameters:
20 | N_EP1=124;
21 | N_IP1=4;
22 | N = N_EP1+N_IP1
23 | #VLSI Neuron constants
24 | sigma_mismatch=0.25
25 |
26 | def create_netobjs(stim, params):
27 | C = params['Cap']
28 | KappaN = params['Kappan']
29 | KappaP = params['Kappap']
30 | I0N = params['I0n']
31 | I0P = params['I0p']
32 | Ut = params['Ut']
33 | Delta_t = (Ut/KappaP)
34 |
35 | #Feed-Forward parameters
36 | i_inj = params['i_inj' ]
37 | i_injinh1 = params['i_injinh1']
38 | i_injinh2 = params['i_injinh2']
39 | i_injinh3 = params['i_injinh3']
40 | i_injinh4 = params['i_injinh4']
41 | i_leak = params['i_leak' ]
42 | tau_syn_E = params['tau_syn_E']
43 | tau_syn_I = params['tau_syn_I']
44 | tau_synloc_E = params['tau_synloc_E']
45 | tau_synloc_IE = params['tau_synloc_IE']
46 | v_thresh = params['v_thresh' ]
47 | w_syn_E1 = params['w_syn_E1' ]
48 | w_syn_E2 = params['w_syn_E2' ]
49 | w_syn_I = params['w_syn_I' ]
50 | w_synloc_E = params['w_synloc_E']
51 | w_synloc_EE = params['w_synloc_EE']
52 | w_synloc_EI = params['w_synloc_EI']
53 | w_synloc_IE = params['w_synloc_IE']
54 | w_synloc_S = params['w_synloc_S']
55 | ##Feed-Back parameters
56 | #w =dict()
57 | #w['e'] =1e-11
58 | #w['i'] =5e-11/N_IP1
59 | #w['ei'] =2e-11/N_EP1
60 |
61 | eqs =Equations('''
62 | dV/dt=(-I_lk + I_fb + I_in + Ia + Iloce - Iloci - Ii)/C: volt
63 |
64 |
65 | I_fb = I0P*exp((V-v_thresh)/Delta_t) : amp
66 | I_in : amp
67 | I_lk = i_leak : amp
68 |
69 | dIa/dt=-Ia/tau_syn_E: amp
70 | dIloce/dt=-Iloce/tau_synloc_E: amp
71 | dIloci/dt=-Iloci/tau_synloc_IE: amp
72 | dIi/dt=-Ii/tau_syn_I: amp
73 | ''')
74 |
75 | EIP = NeuronGroup(N, model=eqs, reset = 0, threshold=1.5, refractory=.001)
76 | EP1 = EIP[:N_EP1]
77 | IP1 = EIP[N_EP1:]
78 |
79 | EP1.I_in = np.random.normal(1,sigma_mismatch,N_EP1)*i_inj
80 | IP1.I_in = np.random.normal(1,sigma_mismatch,N_IP1)*\
81 | np.array([i_injinh1,
82 | i_injinh2,
83 | i_injinh3,
84 | i_injinh4])
85 |
86 | #Create connections between population
87 | v_loclat = np.zeros([N_EP1])
88 | v_loclat[N_EP1/2] = w_synloc_S
89 | v_loclat[[N_EP1/2-1,N_EP1/2+1]] = w_synloc_E
90 | v_loclat[[N_EP1/2-2,N_EP1/2+2]] = w_synloc_EE
91 | v_loclat[[N_EP1/2-3,N_EP1/2+3]] = w_synloc_EE/2
92 | v_loclat = np.roll(v_loclat,-N_EP1/2)
93 | W = np.array([ np.roll(v_loclat,i) for i in range(N_EP1)])
94 | W *= np.random.normal(1,sigma_mismatch,W.shape)
95 | ConnE =Connection(EP1,EP1,'Iloce');ConnE.connect(EP1,EP1,W)
96 | ConnEI =Connection(EP1,IP1,'Iloce');ConnEI.connect(EP1,IP1, W = w_synloc_EI*np.random.normal(1,sigma_mismatch,[len(EP1),len(IP1)]))
97 | ConnIE =Connection(IP1,EP1,'Iloci');ConnIE.connect(IP1,EP1, W = w_synloc_IE*np.random.normal(1,sigma_mismatch,[len(IP1),len(EP1)]))
98 |
99 | M_EIP =SpikeMonitor(EIP)
100 | MV_EIP= StateMonitor(EIP,'V',record=range(0,N),timestep=int(1*ms/defaultclock.dt))
101 |
102 | @network_operation
103 | def update_mpot():
104 | EIP.V[EIP.V<0.]=0.
105 | # ME_EP1= StateMonitor(EP1,'Ie',record=range(0,N_EP1),timestep=int(1*ms/defaultclock.dt))
106 | # MI_EP1= StateMonitor(EP1,'Ii',record=range(0,N_EP1),timestep=int(1*ms/defaultclock.dt))
107 | # MW_EP1= StateMonitor(EP1,'Ia',record=range(0,N_EP1),timestep=int(1*ms/defaultclock.dt))
108 |
109 | netobjs = {'EIP':EIP,
110 | 'update_mpot':update_mpot,
111 | 'ConnE': ConnE,
112 | 'ConnEI': ConnEI,
113 | 'ConnIE': ConnIE,
114 | #'M_In1': M_In1,
115 | 'M_EIP': M_EIP,
116 | 'MV_EIP': MV_EIP}
117 |
118 | return netobjs, M_EIP, MV_EIP
119 |
120 |
121 |
122 | if __name__ == '__main__':
123 | from pylab import *
124 | from brian.plotting import raster_plot
125 | ion()
126 | from paramTranslation import params, loadBiases
127 | from expSetup import *
128 | configurator = pyNCS.ConfAPI.Configurator()
129 | configurator._readCSV('chipfiles/ifslwta.csv')
130 | configurator.set_parameters(loadBiases('biases/defaultBiases_ifslwta'))
131 | p=params(configurator, 'chipfiles/ifslwta_paramtrans.xml')
132 | p.translate('pinj',2.8)
133 | p.translate('nsynloclat1',0.55)
134 | p.translate('nsynloclat2',0.53)
135 | p.translate('nsynexcinh',0.45)
136 | p.translate('psynlocinhw',2.75)
137 | p.translate('psynlocinhth',.3)
138 | stim = np.transpose([np.random.randint(0,128,32000), np.cumsum(np.random.random(32000)/16)])
139 | netobjs, M_EIP, MV_EIP = create_netobjs(stim,p.cur)
140 | net = Network(netobjs.values())
141 | net.run(1)
142 | raster_plot(*[M_EIP])
143 |
144 |
145 |
146 |
--------------------------------------------------------------------------------
/src/pyNCS/api/paramTranslation.py:
--------------------------------------------------------------------------------
1 | #-----------------------------------------------------------------------------
2 | # File Name : sympyParams.py
3 | # Purpose:
4 | #
5 | # Author: Emre Neftci
6 | #
7 | # Creation Date :
8 | # Last Modified : Tue 15 Mar 2011 06:11:41 PM CET
9 | #
10 | # Copyright : (c) 2011
11 | # Licence : GPLv4
12 | #-----------------------------------------------------------------------------
13 |
14 | #chip=pyNCS.Chip('/home/emre/Neuron/software/pyNCS/src/pyNCS/pads_ifslwta.csv')
15 | import numpy as np
16 | from xml.dom import minidom as md
17 | from urllib2 import urlopen
18 | #chip=pyNCS.Chip('/home/emre/Neuron/software/pyNCS/src/pyNCS/pads_ifslwta.csv')
19 | from numpy import log,exp
20 |
21 | def log(x):
22 | if x<0:
23 | return -1e32
24 | else:
25 | return np.log(x)
26 |
27 | class params():
28 |
29 | xml_version=.1
30 |
31 |
32 | def __init__(self,configurator, xml_filename):
33 | from sympy import Symbol,exp,log
34 | self.conf=configurator
35 | self.cur=dict()
36 |
37 | for s in self.conf.get_param_names():
38 | globals()[s]=Symbol(s)
39 |
40 |
41 | self.loadXML(xml_filename)
42 |
43 | #Some default parameters
44 | for i,k in self.initial_parameters.items():
45 | self.cur.update({i:k})
46 |
47 | self.cur.update(self.conf.get_parameters())
48 |
49 | def loadXML(self,filename):
50 | if '://' in filename:
51 | doc= md.parse( urlopen(filename) )
52 | else:
53 | doc = md.parse( filename )
54 |
55 | nsetup= doc.childNodes[0]
56 | if nsetup.tagName!='paramtrans' or float(nsetup.getAttribute('version'))`_
5 |
6 |
7 | Introduction
8 | ------------
9 |
10 | This package provides the `Oscilloscope class `_ which actually is an abstraction wrapper
11 | that can be used to access any oscilloscope-like device for which exists a 'driver'. So far there is only a
12 | driver provided for the `Spectrum Card `_ -- Normally you wouldn't care too
13 | much about the actual drivers and only use the wrapper. Using a different oscilloscope then results in a simple
14 | change of one line of code:
15 |
16 | .. code-block:: python
17 |
18 | from pyOsc.spectrum import SpectrumCard as driver # already implemented
19 | # from pyOsc.agilent import AgilentEthernetController as driver # not yet implemented !
20 |
21 | import pyOsc
22 | osc= pyOsc.Oscilloscope( driver() )
23 |
24 |
25 | Tutorial
26 | --------
27 |
28 | Initializing
29 | ~~~~~~~~~~~~
30 |
31 | Let's assume we are connected via ``ssh`` to ``zaex`` where the ``SpectrumCard`` is currently installed and
32 | let's assume we have some single chip setup as described in the setup file
33 | `zaex.xml `_
34 |
35 | .. code-block:: python
36 |
37 | import pyOsc,pyNCS
38 | from pyOsc.spectrum import SpectrumCard as driver # already implemented
39 | osc= pyOsc.Oscilloscope( driver(debug=True) )
40 | basedir = '/home/federico/pyFED/'
41 | setup = pyNCS.NeuroSetup(basedir+'setups/mc_setuptype.xml',basedir+'setups/mc.xml');
42 |
43 | The spectrum card has 8 channels. As of the time of writing this tutorial, we have them connected to the
44 | ``ifslwta`` chip in a particular way. In order to avoid confusing the lines and signals, we can label
45 | the channels like this
46 |
47 | .. code-block:: python
48 |
49 | osc.names( {
50 | 0 : 'Vmem127',
51 | 1 : 'Vsyn ("Vpls")',
52 | 2 : 'Vpls ("Vsyn")',
53 | 3 : 'VsynAER',
54 | 4 : 'VplsAER',
55 | 5 : 'Vk',
56 | 6 : 'Vwstd',
57 | 7 : 'Vmem (scanner)' })
58 |
59 |
60 | Getting some data
61 | ~~~~~~~~~~~~~~~~~
62 |
63 | In the simplest scenario, we inject some current, set the scanner to any neuron, setup the channels and
64 | just start recording
65 |
66 | .. code-block:: python
67 |
68 | osc.channels( [7] ) # activate only 1 channel
69 | osc.ranges( {7:1000} ) # set the range to (-1000mV) to (1000mV)
70 | osc.sr( 1024 ) # sample rate in Hertz
71 | setup.find('ifslwta').bias.pinj.v= 2.87 # inject some current into all neurons
72 |
73 |
74 | We know that all the neurons are firing more or less continuously due to the injection current. We would
75 | like to acquire 5 seconds of data. The whole process of data acquiring is completely asynchronous, so we
76 | have to tell the oscilloscope how much data we would like and then we need to wait until the oscilloscope
77 | is ready:
78 |
79 | .. code-block:: python
80 |
81 | samples= 5* osc.sr()
82 | osc.start( samples )
83 | import time
84 | while not osc.done(): time.sleep(1)
85 |
86 |
87 | When we got so far, the whole data is acquired and can be found on the oscilloscope. In order to process
88 | it in python scripts, we need first to transfer it to the computer memory. This is done by
89 |
90 | .. code-block:: python
91 |
92 | data= osc.data()
93 |
94 | The data is now contained in raw format in the dictionary ``data``. The keys to the dictionary are the
95 | channel numbers and the samples are of type ``numpy.int16`` (for the spectrumcard, other drivers may
96 | specify different sample types).
97 |
98 |
99 | Visualizing the data
100 | ~~~~~~~~~~~~~~~~~~~~
101 |
102 | Simply type
103 |
104 | .. code-block:: python
105 |
106 | osc.plot( data )
107 | from matplotlib import pyplot as plt
108 | plt.show() #pop up plot
109 |
110 | This should result in a plot similar to the following
111 |
112 | .. figure:: ../images/raw_data.png
113 | :align: center
114 | :width: 627px
115 | :alt: raw data from oscilloscope
116 |
117 | If you want to display the data in millivolt and milliseconds instead of samples, simply type
118 |
119 | .. code-block:: python
120 |
121 | osc.plot( osc.normalize(data) )
122 |
123 |
124 | Setting a trigger
125 | ~~~~~~~~~~~~~~~~~
126 |
127 | Let's suppose we want to have a nice picture of the spiking neuron. You can easily see in the figure
128 | above that the different spikes are not exactly the same, so let's take the average over several cycles
129 | to get a smoother and more representative image.
130 |
131 | In order to do this we will set a trigger on the sharp falling edge of the membrane potential and center
132 | the data around that trigger. Let's first precisely determine the point we want to trigger at. For this
133 | purpose I use the normalized data plot from above, zoom a little bit closer and move my mouse cursor to
134 | the point I want to trigger at:
135 |
136 | .. figure:: ../images/normalized_data_zoomed.png
137 | :align: center
138 | :width: 649px
139 | :alt: raw data from oscilloscope
140 |
141 | Ok. What we want is the following
142 |
143 | - Trigger on the falling edge at 138 mV (on channel 7).
144 | - Record 200ms on every trigger.
145 | - Center the falling edge at 20% of these 200ms.
146 | - Collect 10 'rounds' of data.
147 |
148 | This translates into the following code
149 |
150 | .. code-block:: python
151 |
152 | osc.trigger( 7,'\\',138,offset=.2 )
153 | samples= osc.sr() * .2
154 | osc.rounds( 10 )
155 |
156 | As above, we start the data acquisition, wait for the oscilloscope to be ready and transfer the data:
157 |
158 | .. code-block:: python
159 |
160 | osc.start( samples )
161 | import time
162 | while not osc.done(): time.sleep(1)
163 | data= osc.data()
164 |
165 |
166 | The raw plott looks pretty confusing, because we the different rounds are just concatenated one after
167 | the other in the sample data. That's why we let the oscilloscope wrapper plot markings between the rounds
168 | and indicate the trigger level with a red line
169 |
170 | .. code-block:: python
171 |
172 | osc.plot( data,decorate=True )
173 |
174 | .. figure:: ../images/decorated_data.png
175 | :align: center
176 | :width: 649px
177 | :alt: raw data from oscilloscope
178 |
179 |
180 | We can now calculate our smooth plot by averaging the rounds. There's a convinience method in ``Oscilloscope``
181 | to do this
182 |
183 | .. code-block:: python
184 |
185 | average= osc.average(data)
186 | osc.plot(osc.normalize( average ))
187 |
188 |
189 | Feedback
190 | ~~~~~~~~
191 |
192 | If you found this tutorial useful or if you have any questions or if things did not work out
193 | the way they are supposed to, you can always `send me an email `_
194 |
195 |
--------------------------------------------------------------------------------
/docs/general/pytune_python_file_template.txt:
--------------------------------------------------------------------------------
1 | ::
2 |
3 | # -*- coding: utf-8 -*-
4 |
5 | # HELLO,
6 | # THIS IS A TEMPLATE FOR THE CREATION OF PARAMETERS IN THE NCS PLUGIN OF
7 | # pyTune. PLEASE READ ALL THE STRINGS WRITTEN IN CAPITAL LETTERS AND FOLLOW THE
8 | # DESCRIBED CONVENTIONS AS MUCH AS POSSIBLE.
9 |
10 | from __future__ import with_statement
11 | from os import path
12 | from pyTune.base import Parameter
13 | from pyAex import netClient
14 | #from pyOsc import pyOsc
15 |
16 | import numpy as np
17 |
18 | # DEFINE SCOPE CHANNELS HERE #
19 | #global scope
20 | #scope = pyOsc.Oscilloscope( driver(debug=True) )
21 | #scope.names( {
22 | #0 : 'Vmem127',
23 | #1 : 'Vsyn ("Vpls")',
24 | #2 : 'Vpls ("Vsyn")',
25 | #3 : 'VsynAER',
26 | #4 : 'VplsAER',
27 | #5 : 'Vk',
28 | #6 : 'Vwstd',
29 | #7 : 'Vmem (scanner)' })
30 |
31 | class Template(Parameter): # REPLACE WITH NameOfYourParameter
32 | '''
33 | DESCRIBE PARAMETER HERE.
34 | Units: "UNITS HERE"
35 | '''
36 | def __init__(self, paramid='Template', # if your parameter has a long name:
37 | # PlesaUseThisFormat
38 | xmlfilename='template.xml', # now instead, use_this_format
39 | history_filename='template.history'): # and_also_here
40 | '''
41 | '''
42 | # DON'T FORGET TO CREATE your_parameter.xml!
43 | # PLEASE DON'T MODIFY THIS
44 | resources = path.join(path.dirname(__file__), xmlfilename)
45 | history_filename = path.join(path.dirname(__file__), history_filename)
46 | Parameter.__init__(self, paramid, xml=resources, history_filename=history_filename)
47 |
48 | def setContext(self, population, synapses_id):
49 | """
50 | THIS SETS THE context OF A PARAMETER, I.E. POPULATION(S) ON WHICH IT
51 | ACTS. PLEASE DESCRIBE ARGUMENTS HERE, AS SHOWN IN THE FOLLOWING
52 | EXAMPLE.
53 | Sets the context for the parameter. Arguments are:
54 | - population = pyNCS.Population
55 | - synapses_id = The string of the synapses (e.g. 'excitatory0')
56 | """
57 | # DEFINE YOUR context HERE, FOR EXAMPLE:
58 | self.neurons = population.soma
59 | self.synapses = population.synapses[synapses_id]
60 |
61 | # DON'T FORGET YOU CAN USE Population.neuronblock, IN WHICH YOU FIND
62 | # ALL THE BIASES THAT YOU NEED. SEE EXAMPLE:
63 | self.bias = population.neuronblock.synapses[synapses_id].biases['tau']
64 |
65 | # THE SET OF FUNCTIONS STARTING WITH DOUBLE UNDERSCORE REPLACE THE ONES
66 | # INHERITED FROM pyTune.Parameter
67 |
68 | def __getValue__(self):
69 | """
70 | DESCRIBE HOW THE FUNCTION WORKS.
71 | """
72 | # YOU ALWAYS HAVE TO IMPLEMENT A GET FUNCTION.
73 | # DON'T FORGET YOU CAN DEFINE __getvalue_startup__ IF YOU NEED TO DO
74 | # SOME OPERATION BEFORE THE ACUTAL MEASURE (IT IS AUTOMATICALLY CALLED,
75 | # PLEASE *DON'T* CALL IT HERE.
76 | # IF THE VALUE IS A FUNCTION OF THE VALUE OF THE SUB-PARAMETERS, YOU
77 | # CAN CALL THEM EXPLICITLY HERE VIA:
78 | # Parameter.parameters['name_of_subparameter'].getValue()
79 | return value
80 |
81 | def __setValue__(self, value, searchparams):
82 | """
83 | DESCRIBE HOW THE FUNCTION WORKS.
84 | """
85 | # YOU DON'T NECESSARILY NEED TO SPECIFY A SET FUNCTION. IF YOU DON'T
86 | # SPECIFY HERE, A RECURSIVE FUNCTION WILL BE USED [TODO: is this true?]
87 | # searchparams IS A DICTIONARY CONTAINING ALL THE ADDITIONAL
88 | # INFORMATIONS YOUR ALGORITHM NEEDS, SUCH AS TOLERANCE, INCREMENT STEP
89 | # SIZE, ETC. AN EXAMPLE IS THE FOLLOWING:
90 | # searchparams = {
91 | # 'tolerance_style' : '%',
92 | # 'template' : {'tolerance' : 20,
93 | # 'max' : 10,
94 | # 'min' : 0,
95 | # 'step' : 1,
96 | # 'step_type' : 'linear',
97 | # }
98 | # 'subparam1' : {'tolerance' : 10,
99 | # 'max' : 4,
100 | # 'min' : 3,
101 | # 'step' : 0.1,
102 | # 'step_type' : 'exponential',
103 | # }
104 | # 'subparam2' : {'tolerance' : 10,
105 | # }
106 | # }
107 | # PLEASE NOTICE: DON'T FORGET TO DEFINE A FUNCTION THAT LOOKS WHEITHER
108 | # THE SEARCHPARAMS HAVE BEEN DEFINED AND PUTS DEFAULT VALUES
109 | # INSTEAD.
110 | return value
111 |
112 | def __get_method__(self): # PLEASE REPLACE method WITH THE
113 | # name_of_the_method
114 | '''
115 | DESCRIBE HOW THE METHOD WORKS.
116 | '''
117 | # IMPLEMENT YOUR OWN METHOD HERE. FOR EXAMPLE, YOU MAY HAVE TWO
118 | # DIFFERENT WAYS TO MEASURE YOUR PARAMETER, ONE USING THE SCOPE ONE
119 | # USING SPIKING DATA. YOU CAN THEN DEFINE __get_scope__ AND
120 | # __get_spiking__. YOU CAN DEFINE AS MANY METHOD AS YOU WANT AND THEN
121 | # CALL THEM IN YOUR SCRIPT BY:
122 | # getValue(method='your_method_here')
123 | return value
124 |
125 | def __set_method__(self, value, searchparams): # PLEASE REPLACE method WITH THE
126 | # name_of_the_method
127 | '''
128 | DESCRIBE HOW THE METHOD WORKS.
129 | '''
130 | # IMPLEMENT YOUR METHOD HERE. READ __get_method__ COMMENTS TO KNOW MORE
131 | # ABOUT METHODS.
132 | return value
133 |
134 | def __get_startup__(self):
135 | """
136 | """
137 | # THIS FUNCTION IS CALLED AT EVERY getValue CALL AND IT IS USED TO
138 | # APPLY PRELIMINARY SETTING IF NEEDED, E.G. SET ALL LEARNING SYNAPSES
139 | # TO HIGH IF YOU WANT TO MEASURE THEIR EFFICACY.
140 | return
141 |
142 | def __set_startup__(self):
143 | """
144 | """
145 | # THIS FUNCTION IS CALLED AT EVERY setValue CALL AND IT IS USED TO
146 | # APPLY PRELIMINARY SETTING IF NEEDED
147 | return
148 |
--------------------------------------------------------------------------------
/docs/conf.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | #
3 | # Python Spike Toolbox documentation build configuration file, created by
4 | # sphinx-quickstart on Mon Nov 23 16:07:25 2009.
5 | #
6 | # This file is execfile()d with the current directory set to its containing dir.
7 | #
8 | # Note that not all possible configuration values are present in this
9 | # autogenerated file.
10 | #
11 | # All configuration values have a default; values that are commented out
12 | # serve to show the default.
13 |
14 | import sys, os
15 |
16 | # If extensions (or modules to document with autodoc) are in another directory,
17 | # add these directories to sys.path here. If the directory is relative to the
18 | # documentation root, use os.path.abspath to make it absolute, like shown here.
19 | #sys.path.append(os.path.abspath('.'))
20 |
21 | # -- General configuration -----------------------------------------------------
22 |
23 | # Add any Sphinx extension module names here, as strings. They can be extensions
24 | # coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
25 | extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.intersphinx', 'sphinx.ext.todo', 'sphinx.ext.pngmath']
26 |
27 | # Add any paths that contain templates here, relative to this directory.
28 | templates_path = ['_templates']
29 |
30 | # The suffix of source filenames.
31 | source_suffix = '.txt'
32 |
33 | # The encoding of source files.
34 | #source_encoding = 'utf-8'
35 |
36 | # The master toctree document.
37 | master_doc = 'index'
38 |
39 | # General information about the project.
40 | project = u'Python NCS tools'
41 | copyright = u'2012, University of Zurich, Emre Neftci, Sadique Sheik, Fabio Stefanini, Giacomo Indiveri'
42 |
43 | # The version info for the project you're documenting, acts as replacement for
44 | # |version| and |release|, also used in various other places throughout the
45 | # built documents.
46 | #
47 | # The short X.Y version.
48 | version = '0.2'
49 | # The full version, including alpha/beta/rc tags.
50 | release = '0.2'
51 |
52 | # The language for content autogenerated by Sphinx. Refer to documentation
53 | # for a list of supported languages.
54 | #language = None
55 |
56 | # There are two options for replacing |today|: either, you set today to some
57 | # non-false value, then it is used:
58 | #today = ''
59 | # Else, today_fmt is used as the format for a strftime call.
60 | #today_fmt = '%B %d, %Y'
61 |
62 | # List of documents that shouldn't be included in the build.
63 | #unused_docs = []
64 |
65 | # List of directories, relative to source directory, that shouldn't be searched
66 | # for source files.
67 | exclude_trees = ['_build']
68 |
69 | # The reST default role (used for this markup: `text`) to use for all documents.
70 | #default_role = None
71 |
72 | # If true, '()' will be appended to :func: etc. cross-reference text.
73 | #add_function_parentheses = True
74 |
75 | # If true, the current module name will be prepended to all description
76 | # unit titles (such as .. function::).
77 | #add_module_names = True
78 |
79 | # If true, sectionauthor and moduleauthor directives will be shown in the
80 | # output. They are ignored by default.
81 | #show_authors = False
82 |
83 | # The name of the Pygments (syntax highlighting) style to use.
84 | pygments_style = 'sphinx'
85 |
86 | # A list of ignored prefixes for module index sorting.
87 | #modindex_common_prefix = []
88 |
89 |
90 | # -- Options for HTML output ---------------------------------------------------
91 |
92 | # The theme to use for HTML and HTML Help pages. Major themes that come with
93 | # Sphinx are currently 'default' and 'sphinxdoc'.
94 | html_theme = 'default'
95 |
96 | # Theme options are theme-specific and customize the look and feel of a theme
97 | # further. For a list of options available for each theme, see the
98 | # documentation.
99 | #html_theme_options = {}
100 |
101 | # Add any paths that contain custom themes here, relative to this directory.
102 | #html_theme_path = []
103 |
104 | # The name for this set of Sphinx documents. If None, it defaults to
105 | # " v documentation".
106 | #html_title = None
107 |
108 | # A shorter title for the navigation bar. Default is the same as html_title.
109 | #html_short_title = None
110 |
111 | # The name of an image file (relative to this directory) to place at the top
112 | # of the sidebar.
113 | #html_logo = None
114 |
115 | # The name of an image file (within the static path) to use as favicon of the
116 | # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
117 | # pixels large.
118 | #html_favicon = None
119 |
120 | # Add any paths that contain custom static files (such as style sheets) here,
121 | # relative to this directory. They are copied after the builtin static files,
122 | # so a file named "default.css" will overwrite the builtin "default.css".
123 | html_static_path = ['_static']
124 |
125 | # If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
126 | # using the given strftime format.
127 | #html_last_updated_fmt = '%b %d, %Y'
128 |
129 | # If true, SmartyPants will be used to convert quotes and dashes to
130 | # typographically correct entities.
131 | #html_use_smartypants = True
132 |
133 | # Custom sidebar templates, maps document names to template names.
134 | #html_sidebars = {}
135 |
136 | # Additional templates that should be rendered to pages, maps page names to
137 | # template names.
138 | #html_additional_pages = {}
139 |
140 | # If false, no module index is generated.
141 | #html_use_modindex = True
142 |
143 | # If false, no index is generated.
144 | #html_use_index = True
145 |
146 | # If true, the index is split into individual pages for each letter.
147 | #html_split_index = False
148 |
149 | # If true, links to the reST sources are added to the pages.
150 | #html_show_sourcelink = True
151 |
152 | # If true, an OpenSearch description file will be output, and all pages will
153 | # contain a tag referring to it. The value of this option must be the
154 | # base URL from which the finished HTML is served.
155 | #html_use_opensearch = ''
156 |
157 | # If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
158 | #html_file_suffix = ''
159 |
160 | # Output file base name for HTML help builder.
161 | htmlhelp_basename = 'PythonSpikeToolboxdoc'
162 |
163 |
164 | # -- Options for LaTeX output --------------------------------------------------
165 |
166 | # The paper size ('letter' or 'a4').
167 | #latex_paper_size = 'letter'
168 |
169 | # The font size ('10pt', '11pt' or '12pt').
170 | #latex_font_size = '10pt'
171 |
172 | # Grouping the document tree into LaTeX files. List of tuples
173 | # (source start file, target name, title, author, documentclass [howto/manual]).
174 | latex_documents = [
175 | ('index', 'PythonSpikeToolbox.tex', u'Python Spike Toolbox Documentation',
176 | u'Emre Neftci', 'manual'),
177 | ]
178 |
179 | # The name of an image file (relative to this directory) to place at the top of
180 | # the title page.
181 | #latex_logo = None
182 |
183 | # For "manual" documents, if this is true, then toplevel headings are parts,
184 | # not chapters.
185 | #latex_use_parts = False
186 |
187 | # Additional stuff for the LaTeX preamble.
188 | #latex_preamble = ''
189 |
190 | # Documents to append as an appendix to all manuals.
191 | #latex_appendices = []
192 |
193 | # If false, no module index is generated.
194 | #latex_use_modindex = True
195 |
196 |
197 | # Example configuration for intersphinx: refer to the Python standard library.
198 | intersphinx_mapping = {'http://docs.python.org/': None}
199 |
--------------------------------------------------------------------------------
/docs/general/introduction.txt:
--------------------------------------------------------------------------------
1 | Introduction
2 | ============
3 |
4 | A general introduction.
5 |
6 | Neuromorphic hardware
7 | ---------------------
8 |
9 | - multineuron chips
10 | - AER communication
11 |
12 | Description of the Chips Developed at INI
13 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
14 |
15 | Our VLSI chips can be interfaced to computers via custom "AEX" boards, and
16 | among each other via a custom "mapper" board. The AEX boards are controlled by
17 | an FPGA (Filed Programmable Gate Array) which routes the communications between
18 | serial (i.e. other chips and mapper), parallel (i.e. the chip) and usb ports
19 | (i.e. the user's computer). Here is a brief tutorial on how to use these
20 | boards, how they are configured in a multi-chip setup, and how to re-program
21 | the FPGAs on the AEX boards to suit your needs.
22 |
23 | :IFSLWTA:
24 |
25 | This chip contains a 1D sheet consisting of 128 IAF neurons, 4 of them receive
26 | excitation from the other 124 and inhibit them back. Each row has 32 synapses,
27 | 2 excitatory, 2 inhibitory, 28 excitatory plastic synapses. Neurons have local
28 | connections to first and second neighbour. Plasticity acts as a 2 state switch:
29 | each synapse (28*128) can be turned on or off by learning. If it happens that
30 | one synapse has a value between the on and off values, it will be pushed to the
31 | nearest one according to a set of thresholds.
32 |
33 | This chip shows the Stop-Learning algorithm (Brader et al., 2007; Mitra et al.,
34 | 2009).
35 |
36 | Uses 12/16bits for neuron addressing.
37 |
38 | :2DIFWTA:
39 |
40 | This chip is a 2D matrix of 32*64 IAF neurons similar to the ifslwta ones. Each
41 | neuron has 2 excitatory connections (synapses 1-2) and 1 inhibitory (synapse 0). Local connections are
42 | with the nearest neighbour (can be limited to 1/2 vertical neighbours +/- 1 lateral/diagonal neighbours).
43 | Uses 13/16bits for neuron addressing.
44 | There is a *bug* in this chip that generates illegal events on the AER bus :
45 | Every time an inhibitory synapse of a neuron with a Y coordinate of (4n+2) or
46 | (4n+3) is addressed, the system gets into a hung-up state and all AEX boards
47 | have to be restarted in order to make it work again !
48 |
49 | :CPG:
50 |
51 | :DVS Silicon Retina:
52 |
53 | :Silicon cochlea:
54 |
55 | The AER interface board
56 | ~~~~~~~~~~~~~~~~~~~~~~~
57 |
58 | AER chips need to be interfaced to the outer world. We developed a custom board
59 | to route signals from/to the chip to/from a usb connected computer and a serial
60 | bus for multi-chip and mapping capabilities.
61 |
62 | An AEX board has three I/O channels:
63 | USB, Parallel, Serial. USB protocol is used for communication with an external
64 | PC for monitoring, bias settings and stimulation. Parallel port gives access to
65 | the chip through the AMDA and daughter board. Serial communication is used by
66 | the mapper via the AER protocol. The board is controlled by a Xilinx ***model***
67 | 32bits FPGA chip. Refer to D. Fasnacht Master thesis for more infos.
68 | The mapper receives spike events from the chip with a stamp which identifies the
69 | neuron that emitted that spike. A mapping table is compiled on the mapper so
70 | every incoming event can be sent to other neurons as they were
71 | connected by a synapse. Mapper has a I/O serial interface (16bit). Refer to D.
72 | Fasnacht documentation.
73 |
74 | The mapper
75 | ~~~~~~~~~~
76 |
77 | Suppose you have N chips (so N AEX boards, AMDAs and daughter boards). Using one
78 | mapper you can arbitrarily connect neurons of these chips, building complex networks.
79 |
80 | We have two setups currently available:
81 |
82 | * the `Zenzero setup `_
83 | * the `Zaex setup `_
84 |
85 | Refer to those pages for details on how to use these existing setups. If you
86 | want to arrange a chip in a new multichip setup, you have to reprogram the AEX
87 | board's FPGA, where informations are routed and filtered properly.
88 |
89 | Please notice that what you are going to reprogram is only valid for a specific
90 | setup, so before going into any modification prepare the setup you want to
91 | arrange. For example: 1 2Difwta and 1 ifslwta. The serial connections are
92 | arranged in a loop chain as
93 |
94 | ========== === ===========
95 | Source Destination
96 | ========== === ===========
97 | Mapper OUT --> Chip1 IN
98 | ---------- --- -----------
99 | Chip1 OUT --> Chip2 IN
100 | ---------- --- -----------
101 | ...
102 | ---------- --- -----------
103 | ChipN OUT --> Mapper IN
104 | ========== === ===========
105 |
106 | ChipN is connected to the user's PC via USB. An address coming from the mapper
107 | is checked by each AEX board and sent to the next chip. If it is an address for
108 | ChipM, AEX board number M will also send the message to its chip via Parallel
109 | port. This message will pass through each AEX until the mapper rejects it (see
110 | next section for details). An address coming from ChipL will be stamped by its
111 | AEX board. Chip addressing use the bits that are not used for neurons
112 | addressing. Of course there are some limitations. The first one can think of
113 | is a bandwith limitation, the amount of information per time unit the chain can
114 | process.
115 |
116 | In this design we will suppose that mapper capabilities are enough to route all
117 | the incoming events without sensible deviations from the ideal case. This can
118 | be false in particular cases. The second is in the address space. Each chip
119 | needs a certain amount of bits for the addressing of neurons. The bigger the
120 | chip (N neurons), the higher the number (~logN). While the AEX boards can
121 | manage 32bits data, the mapper serial communication is 16bits so 16 bits are
122 | the maximum number of bits one can use for chip and neurons addressing. The
123 | design must consider the maximum amount of bits for neurons addressing and what
124 | remains for chip addressing. The design presented here refers to the use of 1
125 | Retina and 3 2Difwta chip. One can even choose not to use the retina and use
126 | the sequencer instead. They cannot be used together at the same time. You can
127 | use either 2Difwta and/or ifslwta chips. Once you program the AEX you cannot
128 | change the position of an AEX in the chain * is it true? *. 2Difwta uses 13/16
129 | bits, so we have 3 bits left for chips addressing. Retina chip uses 15/16 bits
130 | but here we can use only 13 of them restricting the size of the retina. The 8
131 | resulting addresses are as follows.
132 |
133 | .. Make a table here
134 |
135 | ============== =======
136 | Chip IN
137 | ============== =======
138 | Retina/Seq 000
139 | -------------- -------
140 | Chip 1 IN: 001
141 | -------------- -------
142 | Chip 2 IN: 010
143 | -------------- -------
144 | Chip 3 IN: 011
145 | ============== =======
146 |
147 | ============== =======
148 | Chip OUT
149 | ============== =======
150 | Retina/Seq 100
151 | -------------- -------
152 | Chip 1 101
153 | -------------- -------
154 | Chip 2 110
155 | -------------- -------
156 | Chip 3 111
157 | ============== =======
158 |
159 | Each setup needs one (and only one) special channel 0 board. This board doesn't
160 | transmit mapped events (i.e. inputs for the chips) through the serial-to-serial
161 | path. This means it has to be the last one on the chain and the one that is
162 | used to send events from usb to the chain. This serial-to-serial filtering has
163 | been introduced after realizing that the mapper cannot receive mapped events,
164 | otherwise the chain is blocked. Please notice that because of this you cannot
165 | use channel 4 (retina input) for the sequencer: your events would be trashed by
166 | the special aex.
167 |
168 | Software
169 | --------
170 |
171 | .. figure:: ../images/software.jpg
172 |
173 | Software for real-time interaction, control, configuration of a neuromorphic
174 | system. General stuff about:
175 |
176 | - what can be done
177 | - how it is implemented
178 | - what's needed to control new hardware (csv, xml, ...)
179 | - server-client architecture
180 |
--------------------------------------------------------------------------------
/docs/general/spcm.txt:
--------------------------------------------------------------------------------
1 | Spectrum Board installation
2 | ===========================
3 |
4 | A digital acquisition board is installed on one of the NCS machines. This
5 | board, named Spectrum after the producers name, can be used for the acquisition
6 | of analog signals directly from the chips, giving the user the possibility to
7 | integrate his experiments with a tool for the reading of non-AER signals. NCS
8 | group has written an interface in Python and standard basic operation can now
9 | be done from inside a python script just calling an executable.
10 |
11 | Introduction
12 | ------------
13 |
14 | The board is a Spectrum M2i.3132. It has 8 channels, 12bits. They can acquire simultaneously at 25MHZ max [#]_.
15 |
16 | Drivers and software are provided for
17 | Windows and a bunch of linux distributions and architectures. For zaex machine, we need the driver sources and compile the driver. The source code is *not*
18 | distributed so we need a special permission in order to use (and eventually modify) their driver. Every programmer using the board has to sign an agreement saying
19 | the usual things like "I will not re-ditribute the code... I will not use the code for making money...". Something like this will work::
20 |
21 | Dear Bernd,
22 | I'm a PhD working at the Institute of Neuroinfomatics in Zurich with
23 | Giacomo Indiveri. We have an M2i.3132 installed and I need the driver
24 | source code because there is no build for our distribution and architecture
25 | (Ubuntu , multicore SMP, ). I know I can sign a non-disclosure agreement,
26 | can you send it please?
27 | Thank you and best regards,
28 | Fabio Stefanini
29 |
30 | Easily speaking, the board itself is a minimal oscilloscope. It is much similar (in concept) to the hardware installed on other more expensive oscilloscopes
31 | with nice LCD panels, buttons, controls, ... This one has a lot of advantages, over the obvious disadvantage represented by the performances: it is provided as
32 | a PCI card to be installed on a computer. This means it can be used by scripts which eventually need to read analog signal and then perform some operation.
33 | First example coming to your mind: auto-adjusting biases on a chip!
34 |
35 | Since the company only gave us the driver, we needed to write our own interface, even because our very peculiar NCS-style purposes (interface with the chips).
36 | A first attempt of having a complete interface to be integrated in a complex optimization algorithm was done by the writer and it is here documented.
37 | At this Alpha stage, the C program is able to set board's parameters (how many channels you want to use? Which range in voltages? Which signal should trigger
38 | the acquisition? etc.) and perform an acquisition writing the output directly into a file.
39 |
40 | .. [q] The main contact is ''Bernd.Toerner AT spec DOT de'', ''Claudia.Boras AT spec DOT de'' was the girl
41 | replying to my email, ''Matthias.Wilma AT spec DOT de'' is the contact for technical support.
42 |
43 | .. [#] This is enough for acquiring signals from our chips. For example, with a samplerate of 25MHz you can clearly catch req/ack signals and trigger acquisition with them.
44 |
45 | Installing/Updating the board
46 | -----------------------------
47 |
48 | You can checkout all the code you need from svn_. Here's a short description of the important content you just downloaded:
49 |
50 | - examples: a set of examples programs in C provided by the company. They should easily work and I started from them writing the actual interface.
51 | - spcm_linuxkernel_source: the driver source!
52 | - ncspectrum: the programs for acquiring signals
53 | - m2i31_manual_english.pdf: the manual...
54 |
55 | .. _svn: https://svn.ini.uzh.ch/repos/avlsi/NCS/SW/spectrum/.
56 |
57 | Now have the source code. It is good to update it from time to time. Go to the `Spectrum's website`_ for new software. For the latest new driver
58 | you always have to ask them the source by email, though. Let's see how to update the driver.
59 |
60 | .. _Spectrum's website: http://www.spec.de/driver_download.html
61 |
62 | You need to be root sometimes to complete the operations(Actually you should be a member of SPCM group on ZAEX to have the right access!!). Ask zaex's admins for that. To compile the drivers type::
63 |
64 | $ sudo su
65 | # cd spcm_linuxkernel_source/m2i_krnl_linux
66 | # make -f Makefile.kernel26
67 |
68 | The kernel module should be copied in the /lib/modules/`uname -r`/extras. Run a::
69 |
70 | # sudo depmod
71 |
72 | to make sure the module list is updated. To load the module run::
73 |
74 | # sudo modprobe spcm
75 |
76 | If modprobe does not work, try::
77 |
78 | # sudo insmod /lib/modules/`uname -r`/extras/spcm.ko
79 |
80 | Check that the /dev/spcm0 node is created and check its permissions. If it has root permissions, it means udev rules didn't work so always remember to run the programs that use the device as root. Trying to solve the udev problem is also a good idea.
81 |
82 | *TODO: fix udev problem (udev rule apply correct permissions to /dev/spcm0 but segfault is raised if you are not root!)*
83 |
84 | Spectrum software
85 | -----------------
86 |
87 | From the company's website you can download the latest software. The first one is the Spcm Control Center (spcm_control_center_v127b3459.tgz). It visualizes some
88 | infos about the spcm card so you can use it in order to check that the board is really running. You can do also other unimportant stuff with it if you want.
89 |
90 | An other cool and useful one is SBench6 (sbench6-6.0.06b3529-1.64bit_stdc++6.rpm). Install it by typing::
91 |
92 | $> sudo rpm -Uvh sbench6-6.0.06b3529-1.64bit_stdc++6.rpm
93 |
94 | Once you do that you end up with a cool GUI which visualize signals in realtime. You can practice with it a bit. Just run it::
95 |
96 | $> SBench6
97 |
98 | Normally, you first visualize the signals you are going to acquire and sets the parameters (ranges, offsets, ...), try some acquisition and test different
99 | buffer lenghts and triggering and finally put everything in a python script and automatize the acquisition. The latter operation is a bit time consuming because
100 | it require to write a lot of stuff. Since you can save the configuration file directly from the GUI, it would be nice to be able to read this signal from inside the
101 | python script. Do you want to be the really first guy implementing this amazing feature? Be my guest then!
102 |
103 | For saving the configuration just go to File > Save config. It will save a txt file with a lot of stuff in it.
104 |
105 | Please notice that the free version of SBench6 doesn't allow ASCII save of data file. If you want an ASCII file with your data you can only use the C program ``rec_single_asciifile``.
106 |
107 | Common problems
108 | ---------------
109 |
110 | Debugging
111 | ~~~~~~~~~
112 |
113 | Whenever something weird happens, is cool to have a trace of all the operations that have been done with the board.
114 | Open the Spectrum Control Center and set the log level on the support tab to "log all, including library calls".
115 | Then close the Control Center and start your program.
116 | Now all driver calls and further informations are stored in the file "spcmdrv_debug.txt". If you want to contact the company, always send them this file.
117 | It is also useful for debugging you program, obviously.
118 |
119 | The system doesn't find the board
120 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
121 |
122 | It can be a problem of permission. Try running you command with ``sudo``, for example::
123 |
124 | $> sudo Sbench6
125 |
126 | If this works, it means the udev rule is not working properly setting the right permissions for ``/dev/spcm0``. If it still doesn't work
127 | the problem is maybe hard to solve. First, check that ``/dev/spcm0`` is actually there, then try to remove the module and load it again::
128 |
129 | $> sudo rmmod spcm
130 | $> ls /dev/spcm0
131 | ls: cannot access /dev/spcm0: No such file or directory
132 | $> sudo modprobe spcm
133 | $> ls /dev/spcm0
134 | /dev/spcm0
135 |
136 | SBench6 keeps crashing
137 | ~~~~~~~~~~~~~~~~~~~~~~
138 |
139 | Well... That's why it is so useful to save a config file... If it crashes, just close it and open it again. Perhaps this is related to the "acquiring
140 | zeros" problem. Who knows... You may want to contact the company.
141 |
142 |
143 | Acquired signals are all 0s
144 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
145 |
146 | This is a bug somewhere in the driver, most probably. Nobody really figured out how to solve it. A work-around is to set a smaller buffersize (under 2MB)
147 | and/or decreasing the framerate and acquire again. Do you want to fix this problem? Be my guest!
148 |
--------------------------------------------------------------------------------
/test/chipfiles/ifslwta.csv:
--------------------------------------------------------------------------------
1 | "chipclass" "IFSLWTA"
2 |
3 | "aerIn"
4 | "id" "x" "range" "range(128)" "type" "1" "f" "X"
5 | "id" "s" "range" "range(32)" "type" "-1" "f" "Y"
6 | "pinid" "X" "f" "x"
7 | "pinid" "Y" "f" "s"
8 | "pinlayout" "X0 X1 X2 X3 X4 X5 X6 Y4 Y3 Y2 Y1 Y0"
9 |
10 | "aerOut"
11 | "id" "x" "range" "range(128)" "type" "1" "f" "X"
12 | "pinid" "X" "f" "x"
13 | "pinlayout" "X6 X5 X4 X3 X2 X1 X0"
14 |
15 | Count PIN PKG CircuitBlock SignalName FET BiasType PadType Range SimulationValue Description Channel Shared with
16 | 1 4 4 Arbiter TX0 (scx) LATCH Transmitter Data
17 | 2 5 5 TX1 (scx) LATCH Transmitter Data
18 | 3 6 6 TX2 (scx) LATCH Transmitter Data
19 | 4 7 7 TX3(scx) LATCH Transmitter Data
20 | 5 8 8 TX4 (scx) LATCH Transmitter Data
21 | 6 9 9 TX5 (scx) LATCH Transmitter Data
22 | 7 10 10 TX6 (scx) LATCH Transmitter Data
23 | 8 11 11 nTREQ digiOUT Transmitter Chip Request (active low)
24 | 9 3 3 nTACK digiIN Transmitter Chip Acknowledge (active low)
25 | 10 12 12 Aepd n dac IN [0.4:1.2] AER Pull-down bias 1
26 | 11 17 17 Decoder RX0(0/1) digiIN Receiver X Data
27 | 12 16 16 RX1(0/1) digiIN Receiver X Data
28 | 13 15 15 RX2(0/1) digiIN Receiver X Data
29 | 14 14 14 RX3(0/1) digiIN Receiver X Data
30 | 15 13 13 RX4(0/1) digiIN Receiver X Data
31 | 16 30 30 RY0(0/1) digiIN Receiver Y Data
32 | 17 29 29 RY1(0/1) digiIN Receiver Y Data
33 | 18 28 28 RY2(0/1) digiIN Receiver Y Data
34 | 19 27 27 RY3(0/1) digiIN Receiver Y Data
35 | 20 26 26 RY4(0/1) digiIN Receiver Y Data
36 | 21 25 25 RY5(0/1) digiIN Receiver Y Data
37 | 22 24 24 RY6(0/1) digiIN Receiver Y Data
38 | 23 19 19 RREQ digiIN Receiver Chip Request
39 | 24 21 21 RACK digiOUT Receiver Chip Acknowledge
40 | 25 32 32 PixAck WIDE Global Pixel Acknowledge signal
41 | 26 31 31 SynPU p dac IN [2.7:2.9] Pull-up bias of AER synaptic circuits 5
42 | 27 115 119 Scanner CK IN Scanner input clock (e.g. 3KHz)
43 | 28 116 120 OR digiOUT Scanner sync signal
44 | 29 1 1 ScanPD n dac IN [0.3:0.9] Scanner pull-down bias 0
45 | 30 111 113 ScanPBias p IN [2.4:3.0] Scanner p-type Op-amp bias
46 | 31 109 111 UP WIDE Scanned global UP learning signal
47 | 32 110 112 DN WIDE Scanned global DN learning signal
48 | 33 112 114 mem WIDE Scanned membrane potential
49 | 34 18 18 MUX mux0 dac digiIN Synapse multiplexer select line 2
50 | 35 20 20 mux1 dac digiIN Synapse multiplexer select line 3
51 | 36 22 22 mux2 dac digiIN Synapse multiplexer select line 4
52 | 37 103 105 RING ring1 n dac IN Select array boundary conditions (closed/opened) 57
53 | 38 83 85 Soma nadap n dac IN [2.2:3.3] Spike-frequency adaptation rate 39
54 | 39 81 83 nlk n dac IN [0:0.7] Leak current on all neurons 37
55 | 40 82 84 nlkadap n dac IN [0:0.7] Spike-frequency adaptation recovery rate 38
56 | 41 85 87 nrf n dac IN [0.1:0.7] Refractory period setting (of all neurons) 41
57 | 42 84 86 nsf n dac IN [0.4:0.9] Spike emission threshold (of all neurons) 40
58 | 43 86 88 pinj p dac IN Excitatory neuron injection current 42
59 | 44 87 89 pinj1 p dac IN Inhibitory neuron injection current 43
60 | 45 88 90 pinj2 p dac IN Inhibitory neuron injection current 44
61 | 46 89 91 pinj3 p dac IN Inhibitory neuron injection current 45
62 | 46 90 92 pinj4 p dac IN Inhibitory neuron injection current 46
63 | 47 107 109 Vmem127 WIDE Membrane potential of neuron 127
64 | 48 108 110 LPF nlpfth n dac IN [2.4:3.0] Stop learning Ca integrator threshold 58
65 | 49 92 94 nlpfw n dac IN [0.1:0.7] Stop learning Ca integrator weight 47
66 | 50 93 95 plpftau p dac IN [2.7:3.3] Stop learning Ca integrator time constant 48
67 | 51 106 108 Vk WIDE Stop learning Ca integrator output
68 | 52 96 98 CMPV pcmp p dac IN [2.4:3.0] Stop learning mem comparator bias 51
69 | 53 95 97 thmem p dac IN [0.2:0.8] Stop learning mem comparator threshold 50
70 | 54 97 99 CMPI nwta n dac IN [0.2:0.6] Stop learning Ca comparator bias (jump-height) 52
71 | 55 98 100 thk1 p dac IN [2.4:3.3] Stop learning enable threshold 53
72 | 56 99 101 thk2 p dac IN [2.3:3.3] Stop learning disable LTD threshold 54
73 | 57 100 102 thk3 p dac IN [2.2:3.3] Stop learning disable LTP threshold 55
74 | 58 110 112 CCONV pbuf p dac IN [2.4:3.0] Stop learning UP current-conveyor bias 59 ScanPBias
75 | 59 101 103 nbuf n dac IN [0.1:0.7] Stop learning DN current-conveyor bias 56
76 | 60 78 80 LOCPLS(I) nplsloc n dac IN [0.1:0.7] Local excitatory synapses pulse extender bias 35
77 | 61 79 81 nplslocinh n dac IN [0.1:0.6] Local inhibitory synapses pulse extender bias 36
78 | 62 105 107 Vpls WIDE Inhibitory neuron pulse extender output
79 | 63 75 77 LOCINH nsynlocinhtau n dac IN [0.2:0.5] Local inhibitory synapses time constant 32
80 | 64 74 76 psynlocinhw p dac IN [2.4:3.3] Local inhibitory synapses weight 31
81 | 65 49 51 psynlocinhth p dac IN [2.4:3.0] Local inhibitory synapses threshold 10
82 | 66 46 48 nsynlocginh n dac IN [0.2:0.5] Local inhibitory synapses g-threshold 7
83 | 67 104 106 Vsyn WIDE Local inhibitory synapses output
84 | 68 76 78 SYNLOC nsynlocth n dac IN [2.4:3.0] Local excitatory synapses threshold 33
85 | 69 73 75 psynloctau p dac IN [2.7:3.3] Local excitatory synapses time constant 30
86 | 70 77 79 nsynlocself n dac IN [0.1:0.6] Self-excitatory synapse weight 34
87 | 71 72 74 nsynexcinh n dac IN [0.1:0.6] Excitatory synapse to inhibitory neuron weight 29
88 | 72 71 73 nsynloclat1 n dac IN [0.1:0.6] First nearest neighbor synapse weight 28
89 | 73 70 72 nsynloclat2 n dac IN [0.1:0.6] Second and third nearest neighbor synapse weight 27
90 | 74 69 71 SYNAERLEARN nsynaerpls n dac IN [0.1:0.7] AER plastic synapses pulse extender bias 26
91 | 75 68 70 nsynaerth n dac IN [2.4:3.0] AER plastic synapses threshold 25
92 | 76 67 69 psynaerlk p dac IN [2.4:3.3] Bistability comparator bias 24
93 | 77 66 68 psynaernmda p dac IN [0.2:0.5] AER plastic synapses NMDA threshold 23
94 | 78 65 67 psynaertau p dac IN [2.7:3.3] AER plastic synapses time constant 22
95 | 79 63 65 synaerhi p dac IN [0.4:1.6] Bistability comparator top power supply rail 20
96 | 80 64 66 synaerlo n dac IN [0.0:0.4] Bistability comparator bottom power supply rail 21
97 | 81 62 64 synaerth p dac IN [0.2:1.4] Bistability comparator threshold 19
98 | 82 102 104 Vw31 WIDE AER plastic synapse weight (syn 31, neur 127)
99 | 83 61 63 SYNAERSTD nsynstdth n dac IN [2.4:3.0] AER STD synapses threshold 18
100 | 84 57 59 nsynstdw0 n dac IN [0.1:0.7] AER STD synapse 0 weight 14
101 | 85 58 60 nsynstdw1 n dac IN [0.1:0.7] AER STD synapse 1 weight 15
102 | 86 56 58 nsynstdwd0 n dac IN [0.0:0.4] AER STD synapse 0 weight depression rate 13
103 | 87 59 61 nsynstdwd1 n dac IN [0.0:0.4] AER STD synapse 1 weight depression rate 16
104 | 88 60 62 psynstdtau p dac IN [2.7:3.3] AER STD synapses time constant 17
105 | 89 54 56 Vwstd WIDE AER STD synapse 0 weight output
106 | 90 46 48 SYNAERINH nsynaerginh n IN [0.2:0.5] AER inhibitory synapses g-threshold nsynlocginh
107 | 91 47 49 nsynaerinhtau n dac IN [0.2:0.5] AER inhibitory synapses time constant 8
108 | 92 49 51 psynaerinhth p IN [2.4:3.0] AER inhibitory synapses threshold psynlocinhth
109 | 93 50 52 nsynaerinhpls n dac IN [0.1:0.6] AER inhibitory synapses pulse extender bias 11
110 | 94 48 50 psynaerinhw p dac IN [2.4:3.3] AER inhibitory synapses weight 9
111 | 95 51 53 Vplsaer WIDE AER inhibitory synapses pulse extender output
112 | 96 52 54 Vsynaer WIDE AER inhibitory synapses output
113 | 97 35 37 Test Array vLPF WIDE Voltage output of new LPF
114 | 98 36 38 Tw WIDE Output of +FB amplifier
115 | 99 37 39 ~Tw WIDE Output of +FB amplifier, inv
116 | 100 38 40 TwBuf WIDE Output of +FB amplifier, buf
117 | 101 42 44 mem1 WIDE membrane
118 | 102 43 45 DN1 WIDE DN
119 | 103 44 46 UP1 WIDE UP
120 | 104 45 47 mem2 WIDE membrane
121 | 105 40 42 QyT1 digiIN Y Select test array
122 | 106 41 43 QyT2 digiIN Y Select test array
123 | 107 39 41 nLearnW n dac IN [0.1:0.7] weight for bistable synapse 6
124 | 108 53 55 Power llGnd dac BARE [0.0:0.2] Low-leakage Ground rail 12
125 | 109 94 96 llVdd dac INOR [3.0:3.3] Low-leakage Vdd rail 49
126 | 110 55 57 Gnd Corner Gnd Analog Vdd
127 | 111 91 93 Vdd Corner aVdd Analog Vdd
128 | 112 34 36 dGnd PaddGnd Digital core and Digital Pad Ground
129 | 113 2 2 dGnd PaddGnd Digital core and Digital Pad Ground
130 | 114 80 82 dVdd PaddVdd Digital core Vdd
131 | 115 23 23 dVdd PaddVdd Digital core Vdd
132 | 116 114 118 PadVdd PadVDD Digital Pad Vdd
133 | 117 33 35 PadGnd Corner PadGND Digital core and Digital Pad Ground
134 | 118 113 115 FollBias dac Corner FollBias [0.3:0.6] Wide-pad follower bias 60
135 |
136 | TOTAL PINS: 116
137 |
--------------------------------------------------------------------------------
/src/pyNCS/experimentTools.py:
--------------------------------------------------------------------------------
1 | #-----------------------------------------------------------------------------
2 | # Purpose:
3 | #
4 | # Author: Emre Neftci
5 | #
6 | # Copyright : University of Zurich, Giacomo Indiveri, Emre Neftci, Sadique Sheik, Fabio Stefanini
7 | # Licence : GPLv2
8 | #-----------------------------------------------------------------------------
9 | # -*- coding: utf-8 -*-
10 |
11 | #For jaer monitoring
12 | import tarfile
13 | import glob
14 | import time
15 | import os
16 | import fnmatch
17 | import warnings
18 | try:
19 | import dill as pickle
20 | except ImportError:
21 | warnings.warn('Cannot import dill, falling back to pickle. Several pyNCS objects cannot be pickled')
22 | import pickle
23 |
24 | import pylab
25 | import numpy as np
26 | from shutil import rmtree
27 |
28 | ### The globals class
29 | class datacontainer:
30 | def __init__(self):
31 | self.directory = './'
32 |
33 | global globaldata
34 | globaldata = datacontainer()
35 |
36 | REC_FN_SEQ = 'seq_address_specification'
37 | REC_FN_MON = 'mon_address_specification'
38 |
39 | def get_figsize(fig_width_pt, ratio='g'):
40 | """
41 | Method to generate figure size.
42 | """
43 | inches_per_pt = 1.0 / 72.0 # Convert pt to inch
44 | golden_mean = (np.sqrt(5) - 1.0) / 2.0 # Aesthetic ratio
45 | fig_width = fig_width_pt * inches_per_pt # width in inches
46 | if ratio is 'g':
47 | fig_height = fig_width * golden_mean # height in inches
48 | elif ratio is 's':
49 | fig_height = fig_width # square figure
50 | else:
51 | fig_height = 1. * fig_width / ratio
52 | fig_size = [fig_width, fig_height] # exact figsize
53 | return fig_size
54 |
55 |
56 | def loadPlotParameters(size=0.5, fontsize=18.0):
57 | """
58 | Load default matplotlib parameters for pretty plotting
59 | size: 0.5 -- two column page.
60 | 0.33 -- three column page.
61 | 0.25 -- two column double figure.
62 | fontsize: universal font size
63 | """
64 | if size <= 0.25:
65 | border = 0.22
66 | elif size <= 0.33:
67 | border = 0.20
68 | else:
69 | border = 0.15
70 | params0 = {'backend': 'pdf',
71 | 'savefig.dpi': 300.,
72 | 'axes.labelsize': fontsize,
73 | 'figure.subplot.bottom': border,
74 | 'figure.subplot.left': border,
75 | 'text.fontsize': fontsize,
76 | 'xtick.labelsize': fontsize,
77 | 'ytick.labelsize': fontsize,
78 | #'legend.pad': 0.1, # empty space around the legend box
79 | 'legend.fontsize': fontsize,
80 | 'lines.markersize': 5,
81 | 'lines.linewidth': 1,
82 | 'font.size': fontsize,
83 | 'text.usetex': True,
84 | 'figure.figsize': get_figsize(1000 * size, ratio=1.3)} # size in inches
85 | pylab.rcParams.update(params0)
86 |
87 | def load_compatibility(filename):
88 | """
89 | Same as experimentTools.load(), but works around recent module renaming problems
90 | Code from http://wiki.python.org/moin/UsingPickle/RenamingModules
91 | """
92 | import pickle as pickle #Does not work with dill
93 | renametable = {
94 | 'pyST': 'pyNCS.pyST',
95 | 'pyST.spikes': 'pyNCS.pyST.spikes',
96 | 'pyST.STas': 'pyNCS.pyST.STas',
97 | 'pyST.STsl': 'pyNCS.pyST.STsl',
98 | 'pyST.stgen': 'pyNCS.pyST.stgen',
99 | }
100 |
101 | def mapname(name):
102 | if name in renametable:
103 | return renametable[name]
104 | return name
105 |
106 | def mapped_load_global(self):
107 | module = mapname(self.readline()[:-1])
108 | name = mapname(self.readline()[:-1])
109 | klass = self.find_class(module, name)
110 | self.append(klass)
111 |
112 | def loads(filename_):
113 | fh = file(filename_,'rb')
114 | unpickler = pickle.Unpickler(fh)
115 | unpickler.dispatch[pickle.GLOBAL] = mapped_load_global
116 | return unpickler.load()
117 |
118 | return loads(filename)
119 |
120 | def load(filename=None, compatibility=False):
121 | """
122 | Unpickles file named 'filename' from the results directory. If no 'filename' is given, then 'globaldata.pickle' is loaded
123 | """
124 | if filename == None:
125 | filename = globaldata.directory + 'globaldata.pickle'
126 | else:
127 | filename = globaldata.directory + filename
128 | if compatibility:
129 | return load_compatibility(filename)
130 | else:
131 | return pickle.load(file(filename, 'rb'))
132 |
133 |
134 | def save_py_scripts():
135 | """
136 | Save all the python scripts from the current directory into the results directory
137 | """
138 | h = tarfile.open(globaldata.directory + 'exp_scripts.tar.bz2', 'w:bz2')
139 | all_py = glob.glob('*.py')
140 | for i in all_py:
141 | h.add(i)
142 | h.close()
143 |
144 | def save_file(filename):
145 | """
146 | Save all the python scripts from the current directory into the results directory
147 | """
148 | import shutil
149 | shutil.copy(filename, globaldata.directory+filename)
150 |
151 |
152 | def save(obj=None, filename=None):
153 | if obj == None and filename == None:
154 | f = file(globaldata.directory + 'globaldata.pickle', 'w')
155 | pickle.dump(globaldata, f)
156 | f.close()
157 | save_py_scripts()
158 | elif obj == None and filename != None:
159 | f = file(globaldata.directory + filename, 'w')
160 | pickle.dump(globaldata, f)
161 | f.close()
162 | else:
163 | f = file(globaldata.directory + filename, 'w')
164 | pickle.dump(obj, f)
165 | f.close()
166 | return None
167 |
168 |
169 | def savetxt(obj, filename):
170 | np.savetxt(globaldata.directory + filename, obj)
171 |
172 |
173 | def mksavedir(pre='Results/', exp_dir=None):
174 | """
175 | Creates a results directory in the subdirectory 'pre'. The directory name is given by ###__dd_mm_yy, where ### is the next unused 3 digit number
176 | """
177 |
178 | if pre[-1] != '/':
179 | pre + '/'
180 |
181 | if not os.path.exists(pre):
182 | os.makedirs(pre)
183 | prelist = np.sort(fnmatch.filter(os.listdir(pre), '[0-9][0-9][0-9]__*'))
184 |
185 | if exp_dir == None:
186 | if len(prelist) == 0:
187 | expDirN = "001"
188 | else:
189 | expDirN = "%03d" % (
190 | int((prelist[len(prelist) - 1].split("__"))[0]) + 1)
191 |
192 | direct = time.strftime(
193 | pre + "/" + expDirN + "__" + "%d-%m-%Y", time.localtime())
194 | assert not os.path.exists(direct)
195 |
196 | elif isinstance(exp_dir, str):
197 | direct = pre + exp_dir
198 | if os.path.exists(direct):
199 | print("Warning: overwriting directory {0}".format(direct))
200 | rmtree(direct)
201 |
202 | else:
203 | raise TypeError('exp_dir should be a string')
204 |
205 | os.mkdir(direct)
206 |
207 | globaldata.directory = direct + str('/')
208 |
209 | fh = file(
210 | globaldata.directory + time.strftime("%H:%M:%S", time.localtime()), 'w')
211 | fh.close()
212 |
213 | print("Created experiment directory {0}".format(globaldata.directory))
214 | return globaldata.directory
215 |
216 |
217 | def savefig(filename, *args, **kwargs):
218 | """
219 | Like pylab.savefig but appends the Results directory
220 | """
221 | pylab.savefig(globaldata.directory + filename, *args, **kwargs)
222 |
223 |
224 | def annotate(filename='', text=''):
225 | "Create a file in the Results directory, with contents text"
226 | f = file(globaldata.directory + filename, 'w')
227 | f.write(text)
228 | f.close()
229 |
230 | def save_rec_files(nsetup):
231 | '''
232 | Saves files recorded by the communicator and prepends address specification
233 | '''
234 | fh_addr_spec_mon = file(globaldata.directory + REC_FN_SEQ, 'w')
235 | fh_addr_spec_seq = file(globaldata.directory + REC_FN_MON, 'w')
236 | seq_addr_spec_str = nsetup.seq.reprAddressSpecification()
237 | mon_addr_spec_str = nsetup.mon.reprAddressSpecification()
238 | fh_addr_spec_mon.write(mon_addr_spec_str)
239 | fh_addr_spec_seq.write(seq_addr_spec_str)
240 | fh_addr_spec_mon.close()
241 | fh_addr_spec_seq.close()
242 | exp_fns = nsetup.communicator.get_exp_rec()
243 | import shutil, os
244 | for f in exp_fns:
245 | shutil.copyfile(f, globaldata.directory+f.split('/')[-1])
246 |
247 | def savefigs(filename='fig', extension = 'png', close=True, *args, **kwargs):
248 | """
249 | Saves all figures with filename *filename#* where # is the figure number.
250 | The order is: last opened last saved.
251 | Inputs:
252 | *filename*: figure name prefix
253 | *extension*: figure extension. savefig should resolve the format from the extension
254 | *close*: whether to close the figure after it is saved
255 | *args, **kwargs are passed to savefig
256 | """
257 | import matplotlib,pylab
258 | figures = [manager.canvas.figure
259 | for manager in matplotlib._pylab_helpers.Gcf.get_all_fig_managers()]
260 | print('Saving {0} figures'.format(len(figures)))
261 | for i, f in enumerate(figures):
262 | savefig('fig'+str(i)+'.'+extension, *args, **kwargs)
263 | if close: pylab.close()
264 |
--------------------------------------------------------------------------------
/src/pyNCS/api/BrianAPI.py:
--------------------------------------------------------------------------------
1 | #!/bin/python
2 | #-----------------------------------------------------------------------------
3 | # File Name : testComAPI.py
4 | # Purpose: Brian Simulator API for testing pyNCS. Can only be used as one
5 | # instance because mappings are global
6 | #
7 | # Author: Emre Neftci
8 | #
9 | # Creation Date : 05-06-2013
10 | # Last Modified : Thu 26 Mar 2015 12:21:07 PM PDT
11 | #
12 | # Copyright : (c)
13 | # Licence : GPLv2
14 | #-----------------------------------------------------------------------------
15 | from pyNCS.neurosetup import get_data
16 | from pyNCS.api.ComAPI import *
17 | from pyNCS.api.ConfAPI import *
18 | import pyNCS.pyST as pyST
19 | import IFSLWTA_brian_model as ibm
20 | import numpy as np
21 | from brian.directcontrol import PoissonGroup
22 | import os
23 |
24 | #TODO: multichip mappings
25 | #TODO: generalize _decode_mappings_list
26 |
27 | chipname = 'ifslwta'
28 | channel_seq = 0
29 | channel_ifslwtain = 6
30 | global_mappings_list = []
31 | global_neurosetup = None
32 | global_sympy_params = None
33 |
34 | synapse_trans_dict = {0 : ['Ii', 'w_syn_I'],
35 | 1 : ['Ii', 'w_syn_I'],
36 | 2 : ['Ia', 'w_syn_E1'],
37 | 3 : ['Ia', 'w_syn_E2']}
38 |
39 | def _decode_mappings_list(mappings_list, synapse_id):
40 | ml = np.array(mappings_list)
41 | fr = decode_addr(ml[:,0])[channel_seq] #0 for field 0
42 | to = decode_addr(ml[:,1])[channel_ifslwtain]
43 | to_syn = to[0,to[1,:]==synapse_id]
44 | fr_syn = fr[0,to[1,:]==synapse_id]
45 | if len(to_syn)==0:
46 | return []
47 | else:
48 | if np.shape(ml)[1]==3:
49 | prob = ml[:,2].astype('float')/128
50 | prob_syn = prob[to[1,:]==synapse_id]
51 | else:
52 | prob = np.ones(ml.shape[0])
53 | return zip(fr_syn,to_syn,prob_syn)
54 |
55 | def _dlist_to_mappingdict(mapping):
56 | from collections import defaultdict
57 | #sort list
58 | if len(mapping)>0:
59 | mapping_dict = defaultdict(list)
60 | mapping_dict_probs = defaultdict(list)
61 | def func(srctgt):
62 | mapping_dict[srctgt[0]].append(srctgt[1])
63 | mapping_dict_probs[srctgt[0]].append(srctgt[2])
64 | map(func, mapping)
65 | return mapping_dict, mapping_dict_probs
66 | else:
67 | return {},{}
68 |
69 | def _mappingdict_to_matrix(mapping_dict, mapping_dict_probs):
70 | N_fr = len(mapping_dict)
71 | N_to = max(max(mapping_dict.values()))+1
72 | M = np.zeros([N_fr, N_to])
73 | P = np.zeros([N_fr, N_to])
74 | for k in mapping_dict.keys():
75 | M[k,mapping_dict[k]] = 1
76 | P[k,mapping_dict[k]] = mapping_dict_probs[k]
77 | return M, P
78 |
79 | def translate_mappings(mapping_list, synapse_id):
80 | m = _decode_mappings_list(mapping_list, synapse_id)
81 | if m ==None:
82 | return None
83 | else:
84 | return _mappingdict_to_matrix(*_dlist_to_mappingdict(m))
85 |
86 | def decode_addr(addr):
87 | #decode physical addresses to neuron - synapse
88 | global global_neurosetup
89 | return global_neurosetup.seq.addrPhysicalExtract(addr)
90 |
91 | class Communicator(BatchCommunicatorBase):
92 | def run(self, stimulus=None, duration=None, context_manager=None):
93 | stimulus_abs = pyST.events(stimulus, atype='p', isISI=True)
94 | stimulus_abs.set_abs_tm()
95 | self.evn_sin = evs_in = stimulus_abs.get_adtmev().astype('float')
96 | evs_in[:,1]*=1e-6 #brian takes seconds
97 | if duration == None and len(stimulus_abs)>0:
98 | duration = np.max(evs_in[:,1])
99 | print(duration)
100 | elif duration == None:
101 | duration = 1.
102 | else:
103 | duration = float(duration)/1e3
104 | net, M_EIP, MV_EIP = self._prepare_brian_net(evs_in)
105 | self.outs = [net, M_EIP, MV_EIP]
106 | net.reinit(states=False)
107 | print('running virtual IFLSWTA for {0}s'.format(duration))
108 | net.run(duration)
109 | sp = np.array(M_EIP.spikes).reshape(-1,2)
110 | sp[:,0]+=(2**16) #slot 2 in text.xml. THIS IS A POSSIBLE SOURCE OF TEST ERROR
111 | sp[:,1]*=1e6
112 | return sp
113 |
114 |
115 | def _prepare_brian_net(self, stimulus):
116 | from brian.directcontrol import SpikeGeneratorGroup
117 | from brian.synapses.synapses import Synapses
118 | from brian.network import Network
119 | self.S = []
120 | netobjs, M_EIP, MV_EIP = ibm.create_netobjs(stimulus, global_sympy_params.cur)
121 |
122 | if len(stimulus)>0:
123 | N = max(stimulus[:,0])+1
124 | In1=SpikeGeneratorGroup(N,stimulus[stimulus[:,0] 0:
128 | gml = np.array(global_mappings_list).reshape(-1,3)
129 | for syn_idx in range(4):
130 |
131 | gml_dict, pgml_dict = _dlist_to_mappingdict(_decode_mappings_list(gml,syn_idx))
132 | if len(gml_dict)>0:
133 | if len(stimulus)==0:
134 | input_pop = PoissonGroup(max(gml_dict.keys())+1, 0)
135 | else:
136 | input_pop = In1
137 | iname, wname = synapse_trans_dict[syn_idx]
138 | EIP = netobjs['EIP']
139 | S=Synapses(input_pop,EIP,model="""w : 1
140 | p : 1""",
141 | pre=iname+"+=w*(rand() element
199 | '''
200 | if isinstance(param, dict):
201 | self.parameters[param['SignalName']] = 0
202 | elif isinstance(param, etree._Element):
203 | self.parameters[param.SignalName] = 0
204 |
205 | def reset(self):
206 | #IMPLEMENT
207 | '''
208 | Resets all the parameters to default values
209 | '''
210 | return None
211 |
212 | def __parseNHML__(self, doc):
213 | '''
214 | Parse xml file or element tree to generate the object
215 | '''
216 | super(Configurator,self).__parseNHML__(doc)
217 | global global_sympy_params
218 | from paramTranslation import params
219 | filename = get_data('chipfiles/ifslwta_paramtrans.xml')
220 | global_sympy_params = self.sympy_params = params(self, filename)
221 |
222 | def _readCSV(self, CSVfile):
223 | super(Configurator,self)._readCSV(CSVfile)
224 | global global_sympy_params
225 | from paramTranslation import params
226 | filename = get_data('chipfiles/ifslwta_paramtrans.xml')
227 | global_sympy_params = self.sympy_params = params(self, filename)
228 |
229 | class Mappings(MappingsBase):
230 | def add_mappings(self, mappings):
231 | #IMPLEMENT (REQUIRED)
232 | '''
233 | Adds *mappings* to the mappings table.
234 |
235 | Inputs:
236 | *mappings*: a two-dimenstional iterable
237 | '''
238 | global global_mappings_list
239 | global_mappings_list += mappings
240 |
241 | def get_mappings(self):
242 | #IMPLEMENT (REQUIRED)
243 | '''
244 | Returns an array representing the mappings
245 | '''
246 | global global_mappings_list
247 | return global_mappings_list
248 |
249 | def clear_mappings(self):
250 | #IMPLEMENT (REQUIRED)
251 | '''
252 | Clears the mapping table. No inputs
253 | '''
254 | global global_mappings_list
255 | while True:
256 | try:
257 | global_mappings_list.pop()
258 | except IndexError:
259 | break
260 |
261 | return None
262 |
263 |
--------------------------------------------------------------------------------
/src/pyNCS/pyST/STsl.py:
--------------------------------------------------------------------------------
1 | #-----------------------------------------------------------------------------
2 | # Purpose:
3 | #
4 | # Author: Emre Neftci
5 | #
6 | # Copyright : University of Zurich, Giacomo Indiveri, Emre Neftci, Sadique Sheik, Fabio Stefanini
7 | # Licence : GPLv2
8 | #-----------------------------------------------------------------------------
9 | from __future__ import absolute_import
10 | import os
11 | import numpy as np
12 | import pylab
13 | import matplotlib
14 | from . import pyST_globals
15 | from . import stgen
16 | from .spikes import SpikeList, SpikeTrain, load, merge, merge_spikelists
17 |
18 | #Globals
19 | addrIndex = 0
20 | timeIndex = 1
21 | STCreate = stgen.StGen()
22 |
23 |
24 | def plot_raster(SL, id_list=None, t_start=None, t_stop=None, display=True, id_color=None, kwargs={}):
25 | ''' Same as spikelist.raster_plot() but with pretty plot options
26 |
27 | id_color is used to customize colors according to neuron address (for example inhibitory vs. excitatory)
28 |
29 | Example:
30 | >>> id_color = [{'ids':range(124),'color':'blue'},{'ids':range(124,128),'color':'red'}]
31 | >>> plot_raster(chipout[158],id_color=id_color)
32 | '''
33 | #SL._SpikeList__calc_startstop()
34 | kwargs_default = {'marker': '|', 'markersize': 2, 'color': 'black'}
35 | kwargs_default.update(kwargs)
36 |
37 | if id_color == None:
38 | SL.raster_plot(id_list, t_start, t_stop, display, kwargs)
39 | else:
40 | h = pylab.axes()
41 | for i in range(len(id_color)):
42 | kwargs['color'] = id_color[i]['color']
43 | SL.id_slice(id_color[i]['ids']).raster_plot(
44 | t_start=t_start, t_stop=t_stop, display=h, kwargs=kwargs)
45 | pylab.ylim([SL.id_list().min() - 1, SL.id_list().max() + 1])
46 |
47 |
48 | STPlotRaster = plot_raster
49 |
50 |
51 | def composite_plot_superimposed(st_pre, st_post, kwargs={}, colors=['blue', 'k'], id_list=None, t_start=None, t_stop=None, t_start_rate=None, t_stop_rate=None, pre_rate_mult=1.):
52 | """
53 | Make a nice Composite plot superimposing two spike trains, a raster plot combined with a vertical rate plot.
54 | *st_pre* and *st_post* are two SpikeLists. st_post will be plotted above st_pre
55 | *colors* is a list specifying the respective colors for the bars and spikes for st_pre and st_post
56 | *kwargs* are the keyword arguments for common plot arguments in the raster plots. Default is {'alpha':0.7,'marker':','} for st_pre and plot_raster defaults for st_post
57 | *pre_rate_mult* is a float used for plotting the rates of st_pre on a different scale
58 | other arguments are the same as in composite_plot
59 | """
60 | kwargs_pre = dict()
61 | kwargs_pre.update({'alpha': 0.8, 'marker': ',', 'color': colors[0]})
62 | kwargs_pre.update(kwargs)
63 | kwargs_post = dict()
64 | kwargs_post.update(kwargs)
65 | kwargs_post.update({'color': colors[1]})
66 |
67 | h1, h2 = composite_plot(
68 | st_pre,
69 | kwargs=kwargs_pre,
70 | kwargs_bar={'alpha': 0.8, 'color': colors[0]},
71 | id_list=id_list,
72 | t_start=t_start,
73 | t_stop=t_stop,
74 | t_start_rate=t_start_rate,
75 | t_stop_rate=t_stop_rate,
76 | )
77 |
78 | twin = False
79 | if pre_rate_mult != 1.:
80 | h2t = h2.twiny()
81 | twin = True
82 | else:
83 | h2t = h2
84 |
85 | super_plot = composite_plot(
86 | st_post,
87 | kwargs=kwargs_post,
88 | kwargs_bar={'color': colors[1]},
89 | display=[h1, h2t],
90 | id_list=id_list,
91 | t_start=t_start,
92 | t_stop=t_stop,
93 | t_start_rate=t_start_rate,
94 | t_stop_rate=t_stop_rate)
95 |
96 | if twin:
97 | pre_lims = h2.get_xlim()
98 | #h2.set_xlim(pre_lims[0],pre_lims[1]*pre_rate_mult)
99 | color = colors[0]
100 | for tl in h2.get_xticklabels():
101 | tl.set_color(color)
102 | h2.set_xlabel('Frequency (Hz)', color=color)
103 |
104 | return super_plot
105 |
106 |
107 | def composite_plot(SL, id_list=None, t_start=None, t_stop=None, t_start_rate=None, t_stop_rate=None, display=True, kwargs={}, kwargs_bar={}):
108 | """
109 | Make a nice Composite plot, *i.e.* a raster plot combined with a vertical rate plot.
110 |
111 | The arguments are identical to STPlotRaster, except for display.
112 | *display* If True is given a new figure is created. If [axS,axR] is given, where axS and axR are pylab.axes objects, then the spike rater and the rate plot are plotted there.
113 | """
114 | SL._SpikeList__calc_startstop()
115 |
116 | if id_list == None:
117 | id_list = SL.id_list()
118 | if t_start is None:
119 | t_start = SL.t_start
120 | if t_stop is None:
121 | t_stop = SL.t_stop
122 | if t_start_rate is None:
123 | t_start_rate = t_start
124 | if t_stop_rate is None:
125 | t_stop_rate = t_stop
126 |
127 | if display == True:
128 | h = pylab.figure()
129 | axS = pylab.axes([0.12, 0.12, 0.57, 0.8])
130 | axR = pylab.axes([0.75, 0.12, 0.20, 0.8])
131 | elif isinstance(display, list):
132 | axS = display[0]
133 | axR = display[1]
134 |
135 | STPlotRaster(SL=SL, id_list=id_list, t_start=t_start, t_stop=t_stop,
136 | display=axS, kwargs=kwargs)
137 |
138 | min_addr = int(np.min(SL.id_list()))
139 | max_addr = int(np.max(SL.id_list()))
140 | axS.set_xlim([t_start, t_stop])
141 | axS.set_yticks([min_addr, (max_addr - min_addr) / 2, max_addr])
142 | axS.set_xticks(
143 | [int(t_start), 100 * (int(t_stop - t_start) / 200), int(t_stop)])
144 |
145 | rates = np.array(SL.mean_rates(t_start=t_start_rate, t_stop=t_stop_rate))
146 | barplot = axR.barh(id_list, rates, linewidth=0, **kwargs_bar)
147 | #remove space between bars, remove black lines
148 | pre_lims = axS.set_ylim()
149 | axR.set_ylim(pre_lims[0], pre_lims[1])
150 |
151 | axR.set_yticks([])
152 | axR.grid('on')
153 | #axS.xaxis.grid('on')
154 |
155 | axR.xaxis.set_major_locator(matplotlib.ticker.MaxNLocator(2))
156 | pylab.axes(axR)
157 | axR.set_xlabel('Frequency (Hz)')
158 |
159 | return axS, axR
160 |
161 | STCompositePlot = composite_plot
162 |
163 |
164 | def composite_plot_movie(SL, time_bin=10, t_start=None, t_stop=None, output="animation.mpg", bounds=(0, 5), fps=10, display=True, maxrate=None, ratebin=None, kwargs={}):
165 | pylab.ioff()
166 | from NeuroTools.plotting import get_display
167 | subplot = get_display(display)
168 | assert os.system('mencoder') != 32512, "mencoder not found!"
169 | if t_start is None:
170 | t_start = SL.t_start
171 | if t_stop is None:
172 | t_stop = SL.t_stop
173 | if maxrate is None:
174 | maxrate = 100
175 | if ratebin is None:
176 | ratebin = 100
177 |
178 | files = []
179 | im = pylab.figure(**kwargs)
180 | count = 0
181 | idx = 0
182 | axS, axR = STCompositePlot(SL, t_start=0, t_stop=time_bin,
183 | t_start_rate=0, t_stop_rate=ratebin, kwargs=kwargs)
184 | axR.hold(False)
185 | axS.hold(False)
186 | if t_start != SL.t_start or t_stop != SL.t_stop:
187 | spk = SL.time_slice(t_start, t_stop)
188 | raise RuntimeError('Not implemented')
189 |
190 | while (t_start < t_stop):
191 | STCompositePlot(SL, t_start=0, t_stop=t_start + time_bin, t_start_rate=t_start,
192 | t_stop_rate=t_start + ratebin, display=[axS, axR], kwargs=kwargs)
193 | axS.set_xlim([0, t_stop])
194 | axR.set_xlim([0, maxrate])
195 | fname = "_tmp_spikes_%05d.png" % count
196 | pylab.savefig(fname)
197 | files.append(fname)
198 | t_start += time_bin
199 | count += 1
200 | print('Generated frame {0}'.format(count))
201 | command = "mencoder 'mf://_tmp_*.png' -mf type=png:fps=%d -ovc lavc -lavcopts vcodec=wmv2 -oac copy -o %s" % (fps, output)
202 | os.system(command)
203 | for fname in files:
204 | os.remove(fname)
205 |
206 |
207 | def mapSpikeListAddresses(SL, mapping=None):
208 | '''
209 | this function maps the addresses of a spike list into another using the given mapping. Useful for logical to physical translation and vice versa
210 | SL=original spike list
211 | mapping=dictionary containing address mapping, If mapping is None, then the addresses will be mapped onto a linear scale, i.e. range(len(SL.id_list()))
212 | '''
213 | assert isinstance(SL, SpikeList), "SL must be a NeuroTools SpikeList"
214 | mapped_SL = SpikeList([], [])
215 | addr_SL = SL.id_list()
216 | if mapping == None:
217 | mapping = dict(zip(np.sort(SL.id_list()), range(len(SL.id_list()))))
218 | for k, v in mapping.iteritems():
219 | if k in addr_SL:
220 | try:
221 | mapped_SL[v] = SL[k]
222 | except KeyError:
223 | pass
224 |
225 | all_others = np.setdiff1d(SL.id_list(), mapping.keys())
226 | for k in all_others:
227 | mapped_SL[k] = SL[k]
228 |
229 | return mapped_SL
230 |
231 |
232 | def ksi(SL, t_stop=800, pow_freq=None, t_bin=10.):
233 | """
234 | Kuramoto Synchronization Index (KSI) (Kuaramoto 1984) for measuring phase coherency with respect to the strongest freqeuncy of the population activity.
235 |
236 | Returns ksi in the range (0,1). 0 meaning no cohrency and 1 meaning entirely coherent
237 |
238 | Inputs:
239 | SL - SpikeList of duration of at least t_stop
240 | t_stop - the end of the SpikeTrain (in ms)
241 | t_bin - time bin for computing population activity and spectrum
242 | pow_freq- if given, this frequency is taken as the strongest frequency
243 |
244 | """
245 | #Determine the strongest frequency
246 | N = len(SL)
247 |
248 | if pow_freq == None:
249 | psth = SL.time_slice(
250 | t_start=0, t_stop=t_stop).spike_histogram(t_bin).mean(axis=0)
251 | t = np.arange(0, t_stop * 1e-3, t_bin * 1e-3)
252 | sp = abs(np.fft.fft(psth).real)
253 | freq = abs(np.fft.fftfreq(t.shape[-1], d=t_bin * 1e-3))
254 | pow_freq = freq[1 + np.argmax(sp.real[1:])]
255 |
256 | l_vs = [[] for i in range(len(SL))]
257 |
258 | for i, k in enumerate(SL.id_list()):
259 | tm = SL[k].spike_times / 1000 # In seconds
260 | l_vs[i] = (tm + .5 / pow_freq) % (1. / pow_freq) - .5 / pow_freq
261 |
262 | vs = np.hstack(l_vs) * pow_freq * 2 * np.pi # Flatten
263 |
264 | return abs(np.sum(np.exp(1j * vs)) / len(vs)), pow_freq
265 |
--------------------------------------------------------------------------------
/test/pyNCS_unittest.py:
--------------------------------------------------------------------------------
1 | #-----------------------------------------------------------------------------
2 | # Purpose: Test pyNCS functions. Currently using pyAex module, but this should change in the future.
3 | #
4 | # Author: Emre Neftci
5 | #
6 | # Copyright : University of Zurich, Giacomo Indiveri, Emre Neftci, Sadique Sheik, Fabio Stefanini
7 | # Licence : GPLv2
8 | #-----------------------------------------------------------------------------
9 | #import pyAex
10 | import pyNCS
11 | import pyNCS.pyST as pyST
12 | import numpy as np
13 | import unittest, warnings, optparse, os, time, sys
14 |
15 |
16 |
17 | def create_default_population(setup,chipname='seq',N=10,*args,**kwargs):
18 | '''
19 | Creates a default population
20 | '''
21 | test_pops = pyNCS.Population('default', 'Default Population')
22 | test_pops.populate_by_number(setup, chipname, 'excitatory', N, *args, **kwargs)
23 | return test_pops
24 |
25 | def evs_loopback(nsetup, sequencer):
26 | '''
27 | This function takes a sequencer object (e.g. returned by
28 | Group.spiketrains_poisson() ) and creates a RawOutput object out of it. This
29 | is usefull for generating synthetic data and treating is as neuromorphic
30 | system ouput.
31 | '''
32 | evs = nsetup.mon.exportAER(sequencer, isi=False)
33 | ch_evs = nsetup.mon.extract(evs)
34 | return nsetup.mon.rawoutput_from_chevents(ch_evs)
35 |
36 |
37 | class TestSequenceFunctions(unittest.TestCase):
38 |
39 | def setUp(self):
40 | import expSetup
41 | self.nsetup = expSetup.build_setup()
42 |
43 | def testBuildLinearPopulation(self):
44 | N=10
45 | #for transition populations + state populations (for inital and test)
46 | test_pops=create_default_population(self.nsetup,'seq',N)
47 | addrs=self.nsetup.mon[test_pops.soma.channel].addrLogicalConstruct([range(N)])
48 | for i,a in enumerate(test_pops.soma.laddr):
49 | self.assert_(a in addrs)
50 |
51 | def testMonitors(self):
52 | N=3
53 | s=create_default_population(self.nsetup,'seq',N)
54 | t=create_default_population(self.nsetup, 'ifslwta', N)
55 | c=pyNCS.PConnection(s,t,'excitatory0')
56 |
57 | stmon1=pyNCS.monitors.SpikeMonitor(t.soma)
58 | self.nsetup.monitors.import_monitors([stmon1])
59 | input_stim=s.soma.spiketrains_poisson(rate = np.linspace(10,100,N), duration=500)
60 | self.nsetup.prepare()
61 | self.nsetup.chips['ifslwta'].set_parameter('nsynstdw0',.6)
62 | out = self.nsetup.run(input_stim)
63 | r= stmon1.sl.mean_rates()
64 | self.assertTrue(np.all(r>0))
65 |
66 | def testSequencers(self):
67 | N=3
68 | s=create_default_population(self.nsetup,'seq',N)
69 | t=create_default_population(self.nsetup,'ifslwta', N)
70 | c=pyNCS.PConnection(s,t,'excitatory0')
71 |
72 | sequencer = pyNCS.monitors.Monitors()
73 | mon_in, = sequencer.create(s)
74 | mon_in.create_spiketrains('poisson', rate = np.linspace(100,2000,N), duration = 1000)
75 |
76 | stmon1=pyNCS.monitors.SpikeMonitor(t.soma)
77 | self.nsetup.monitors.import_monitors([stmon1])
78 |
79 | self.nsetup.prepare()
80 | self.nsetup.chips['ifslwta'].set_parameter('nsynstdw0',.7)
81 |
82 | out = self.nsetup.run(sequencer)
83 | r= stmon1.sl.mean_rates()
84 | self.assertTrue(np.all(r > 0))
85 |
86 | def testSequencers_nsetup(self):
87 | N=3
88 | s=create_default_population(self.nsetup,'seq',N)
89 | t=create_default_population(self.nsetup,'ifslwta', N)
90 | c=pyNCS.PConnection(s,t,'excitatory0')
91 |
92 | sequencers = self.nsetup.sequencers
93 | mon_in, = sequencers.create(s)
94 | mon_in.create_spiketrains('poisson', rate = np.linspace(100,2000,N), duration = 1000)
95 |
96 | stmon1=pyNCS.monitors.SpikeMonitor(t.soma)
97 | self.nsetup.monitors.import_monitors([stmon1])
98 |
99 | self.nsetup.prepare()
100 | self.nsetup.chips['ifslwta'].set_parameter('nsynstdw0',.7)
101 |
102 | out = self.nsetup.run()
103 | r= stmon1.sl.mean_rates()
104 | self.assertTrue(np.all(r > 0))
105 |
106 | def testMonitors_from_SpikeList(self):
107 | from pyNCS import monitors
108 | from pylab import close
109 | N=10
110 | test_pops=create_default_population(self.nsetup,'seq',N)
111 | st = test_pops.soma.spiketrains_poisson(10)[0]
112 | mon = monitors.create_SpikeMonitor_from_SpikeList(st)
113 | monitors.MeanRatePlot(mon)
114 | close('all')
115 |
116 | def testPMapping(self):
117 | N=30
118 | p=0.5
119 | #pyAex.MAPVERS=3
120 | s=create_default_population(self.nsetup, 'seq', N)
121 | t=create_default_population(self.nsetup, 'ifslwta', N)
122 | t2=create_default_population(self.nsetup, 'ifslwta', 124-N, offset=N)
123 | mon = self.nsetup.monitors.import_monitors_otf(t)[0]
124 | mon_zero = self.nsetup.monitors.import_monitors_otf(t2)[0]
125 | m=pyNCS.PMapping('')
126 | m.connect(s.soma,t.synapses['excitatory0'], fashion='random_all2all', fashion_kwargs={'p':p})
127 | m.connect(s.soma,t.synapses['excitatory0'], fashion='one2one',fashion_kwargs={'p':p}, expand = True)
128 | P = int(p*127)
129 | for i in s.soma.paddr:
130 | for j in t.synapses['excitatory0'].paddr:
131 | self.assert_([i, j, P] in m.mapping)
132 | for n in range(len(s.soma.paddr)):
133 | self.assert_([s.soma.paddr[n], t.synapses['excitatory0'].paddr[n], P] in m.mapping)
134 | self.nsetup.mapping.merge(m)
135 | self.nsetup.prepare()
136 | self.nsetup.chips['ifslwta'].set_parameter('nsynstdw0',.5)
137 | input_stim=s.soma.spiketrains_poisson(400)
138 | out = self.nsetup.run(input_stim)
139 | self.assertTrue(np.all(350>mon.sl.mean_rates()) and np.all(mon.sl.mean_rates()>100))
140 | self.assertTrue(np.all(mon_zero.sl.mean_rates()<2))
141 |
142 | def testPConnection(self):
143 | N=30
144 | p=0.5
145 | #pyAex.MAPVERS=3
146 | s=create_default_population(self.nsetup, 'seq', N)
147 | t=create_default_population(self.nsetup, 'ifslwta', N)
148 | t2=create_default_population(self.nsetup, 'ifslwta', 124-N, offset=N)
149 | mon = self.nsetup.monitors.import_monitors_otf(t)[0]
150 | mon_zero = self.nsetup.monitors.import_monitors_otf(t2)[0]
151 | c=pyNCS.PConnection(s,t,'excitatory0','random_all2all',{'p':p})
152 | m=c.mapping
153 | P = int(p*127)
154 | for i in s.soma.paddr:
155 | for j in t.synapses['excitatory0'].paddr:
156 | self.assert_([i, j, P] in m.mapping)
157 | for n in range(len(s.soma.paddr)):
158 | self.assert_([s.soma.paddr[n], t.synapses['excitatory0'].paddr[n], P] in m.mapping)
159 |
160 | self.nsetup.prepare()
161 | input_stim=s.soma.spiketrains_poisson(400)
162 | self.nsetup.chips['ifslwta'].set_parameter('nsynstdw0',.5)
163 | out = self.nsetup.run(input_stim)
164 | self.assertTrue(np.all(350>mon.sl.mean_rates()) and np.all(mon.sl.mean_rates()>100))
165 | self.assertTrue(np.all(mon_zero.sl.mean_rates()<2))
166 |
167 | def testPMappingLarge(self):
168 | N=124
169 | p=0.5
170 | #pyAex.MAPVERS=3
171 | s=create_default_population(self.nsetup, 'seq', N)
172 | t=create_default_population(self.nsetup, 'ifslwta', N)
173 | m=pyNCS.PMapping('')
174 | M = np.random.randint(0,2,size=(len(s.soma),2))
175 | m.mapping.extend(np.random.randint(0,50000,size=(500000,2)))
176 | for j in xrange(len(s)):
177 | print j
178 | m.connect(s.soma[j], t.synapses['inhibitory'][(j*2):((j+1)*2)], fashion = 'by_boolean_matrix', fashion_kwargs={'connection': M[[j],:]})
179 |
180 |
181 | def testSeqPopulationFunctions(self):
182 | N=5
183 | test_pops1=create_default_population(self.nsetup,'seq',N)
184 | test_pops2=create_default_population(self.nsetup,'seq',2*N,offset=N)
185 | pop=pyNCS.Population()
186 | pop.init(self.nsetup, 'seq', 'excitatory')
187 | pop.union(test_pops1)
188 | pop.union(test_pops2)
189 | testaddr = np.concatenate([test_pops1.soma.paddr,test_pops2.soma.paddr])
190 | for a in testaddr:
191 | self.assertTrue(a in pop.soma.paddr)
192 |
193 | def testIFSLWTAPopulationFunctions(self):
194 | N=5
195 | test_pops1=create_default_population(self.nsetup,'ifslwta',N)
196 | test_pops2=create_default_population(self.nsetup,'ifslwta',2*N,offset=N)
197 | pop=pyNCS.Population()
198 | pop.init(self.nsetup, 'ifslwta', 'excitatory')
199 | pop.union(test_pops1)
200 | pop.union(test_pops2)
201 | testaddr = np.concatenate([test_pops1.soma.paddr,test_pops2.soma.paddr])
202 | for a in testaddr:
203 | self.assertTrue(a in pop.soma.paddr)
204 |
205 | def testComAPI_RecordableCommunicatorBase(self):
206 | import pyNCS.api.ComAPI, os
207 | rec_com = pyNCS.ComAPI.RecordableCommunicatorBase()
208 | rec_com.run_rec(np.ones([0,2]))
209 | self.assertTrue(len(rec_com._rec_fns)==2)
210 | self.assertTrue(os.path.exists(rec_com._rec_fns[0]))
211 | self.assertTrue(os.path.exists(rec_com._rec_fns[1]))
212 | fns = rec_com.get_exp_rec()
213 | self.assertTrue(len(rec_com._rec_fns)==0)
214 |
215 | def testExperimentTools(self):
216 | import pyNCS.experimentTools as et
217 | test_pops=create_default_population(self.nsetup,'seq', 5)
218 | input_stim=test_pops.soma.spiketrains_poisson(100)
219 | self.nsetup.run(input_stim)
220 | et.mksavedir(pre='/tmp/test_et/')
221 | et.save_rec_files(self.nsetup)
222 |
223 | def testMonitorsEmptyPlot(self):
224 | #github inincs/pyNCS issue#3
225 | test_pops1=create_default_population(self.nsetup,'seq', N=5)
226 | test_pops2=create_default_population(self.nsetup,'seq', N=5, offset=5)
227 | stmon1=pyNCS.monitors.SpikeMonitor(test_pops1.soma)
228 | stmon2=pyNCS.monitors.SpikeMonitor(test_pops2.soma)
229 | self.nsetup.monitors.import_monitors([stmon1,stmon2])
230 | mon = test_pops1.soma.spiketrains_poisson(rate = 50)
231 | #Monitor loopback
232 | rawoutput = evs_loopback(self.nsetup, mon)
233 | self.nsetup.monitors.populate_monitors(rawoutput)
234 | pyNCS.monitors.RasterPlot(self.nsetup.monitors.monitors)
235 | #import pylab
236 | #pylab.show()
237 |
238 | def testEmptyMonitorReturnsCorrectDimensions(self):
239 | test_pops1=create_default_population(self.nsetup,'seq', N=5)
240 | stmon1=pyNCS.monitors.SpikeMonitor(test_pops1.soma)
241 | stmon1.populate(pyNCS.pyST.SpikeList())
242 | self.assertTrue(len(stmon1.sl.mean_rates())==5)
243 |
244 |
245 |
246 |
247 |
248 | def tearDown(self):
249 | del self.nsetup
250 |
251 |
252 | if __name__ == '__main__':
253 | unittest.main()
254 |
255 |
256 | #to debug
257 | #suite.debug()
258 | #or
259 | #TestSequenceFunctions('testStimulation').debug()
260 |
261 |
262 |
--------------------------------------------------------------------------------
/src/pyNCS/api/ConfAPI.py:
--------------------------------------------------------------------------------
1 | #-----------------------------------------------------------------------------
2 | # Purpose:
3 | #
4 | # Author:
5 | #
6 | # Copyright : University of Zurich, Giacomo Indiveri, Emre Neftci, Sadique Sheik, Fabio Stefanini
7 | # Licence : GPLv2
8 | #-----------------------------------------------------------------------------
9 | #ConfAPI
10 | #Biases and mapper
11 | #Api for modules having pyAMDA-like functionality
12 | #Api for modules having pyAEX-like functionality
13 |
14 | from __future__ import absolute_import
15 | from .BaseConfAPI import *
16 | from .ComAPI import ResourceManagerBase
17 |
18 | class ConfiguratorBase(ResourceManagerBase):
19 | def __init__(self):
20 | '''
21 | ConfiguratorBase()
22 | Base class for managing parameters
23 | Contains functions
24 | - set_parameter (required)
25 | - get_parameter (required)
26 | - add_parameter (required)
27 | - get_parameter_names (required)
28 | - reset (optional)
29 | - set_parameters (optional)
30 | - get_parameters (optional)
31 | - context_get_param (optional)
32 |
33 | Parameters should be stored in the _parameter dictionary.
34 | The dictionary's keys should be the parameter names.
35 | Inherits ResourceManagerBase
36 | '''
37 | self.parameters = {}
38 | ResourceManagerBase.__init__(self)
39 |
40 | def _readCSV(self, CSVfile):
41 | '''
42 | Parse the CSV file to build the configurator object.
43 | NOTE: Downward compatibility function
44 | '''
45 | with open(CSVfile, 'r') as CSV:
46 | csv = CSV.readlines()
47 |
48 | #The following builds bias representations only
49 | tableFlag = False
50 | for line in csv:
51 | line = line.replace('\'', '') # remove single and double quotes
52 | line = line.replace('"', '')
53 | if line.startswith('\t') or line.startswith('\n'):
54 | tableFlag = False
55 | elif 'signal' in line.lower() and not tableFlag:
56 | # TODO: This code assumes that signal is an essential part of
57 | # table
58 | # WARNING: There should be some intelligent way to do this!
59 | tableFlag = True
60 | tableFields = line.strip().split('\t')
61 | elif tableFlag and line.strip():
62 | row = line.strip().split('\t')
63 | # WARNING: This only works if the word bias exists as a field
64 | if row[tableFields.index('BiasType')]:
65 | parameters = {}
66 | for i in range(len(row)):
67 | val = row[i]
68 | # Check if the string is a number
69 | try:
70 | val = float(val)
71 | except:
72 | pass
73 | parameters[tableFields[i]] = val
74 | self.add_parameter(parameters)
75 | return
76 |
77 | def __getNHML__(self):
78 | doc = etree.Element('parameters')
79 | for p in self.parameters.values():
80 | doc.append(p.__getNHML__())
81 | return doc
82 |
83 | def __parseNHML__(self, doc):
84 | '''
85 | Parse xml file or element tree to generate the object
86 | '''
87 | if isinstance(doc, str):
88 | # parse the file
89 | doc = etree.parse(doc).getroot()
90 | if not doc.tag == 'parameters':
91 | doc = doc.find('parameters')
92 | else:
93 | # assuming doc is an lxml Element object.
94 | assert doc.tag == 'parameters'
95 |
96 | for param in doc:
97 | self.add_parameter(param)
98 |
99 | def add_parameter(self, param):
100 | #CONVENIENCE FUNCITON. IMPLEMENTATION NOT REQUIRED
101 | '''
102 | Add a parameter to the configurator
103 | param: dictionary with all attributes of parameter or an xml element or
104 | file name with the element
105 | '''
106 | if isinstance(param, dict):
107 | self.parameters[param['SignalName']] = Parameter(param, self)
108 | elif isinstance(param, etree._Element):
109 | parameter = Parameter({'SignalName': ''}, self)
110 | parameter.__parseNHML__(param)
111 | self.parameters[parameter.SignalName] = parameter
112 |
113 | def get_parameter(self, param_name):
114 | #IMPLEMENT
115 | '''
116 | Gets parameter param_name.
117 | '''
118 | return self.parameters[param_name]
119 |
120 | def get_parameters(self, param_names=None):
121 | #CONVENIENCE FUNCTION. IMPLEMENTATION IS NOT REQUIRED
122 | '''
123 | Returns parameters (dictionary of name-value pairs).
124 | Input:
125 | *param_names:* A list of parameter names
126 | If param_names is None, then this function returns all the parameters
127 | (using self.get_param_names())
128 | '''
129 | if param_names is None:
130 | param_names = self.get_param_names()
131 |
132 | if not isinstance(param_names, (list, tuple, GeneratorType)):
133 | raise TypeError('param_names should be a list, tuple or generator, not {0}'.
134 | format(type(param_names)))
135 |
136 | b = dict()
137 | for i, name in enumerate(param_names):
138 | b[name] = self.get_parameter(name)
139 | return b
140 |
141 | def set_parameter(self, param_name, param_value):
142 | #IMPLEMENT
143 | '''
144 | Sets parameter param_name with param_value
145 | '''
146 | self.parameters[param_name] = param_value
147 | return None
148 |
149 | def set_parameters(self, param_dict):
150 | #CONVENIENCE FUNCTION. IMPLEMENTATION IS NOT REQUIRED
151 | '''
152 | Set several parameters using a dictionary.
153 | Input:
154 | *param_dict*: dictionary of parameter names (str) - value (float) pairs.
155 | '''
156 | for name, value in param_dict.iteritems():
157 | self.set_parameter(name, value)
158 | self.get_parameters(param_dict.keys())
159 | return None
160 |
161 | def update_parameter(self, param_name, param_value):
162 | #CONVENIENCE FUNCTION. IMPLEMENTATION NOT REQUIRED
163 | '''
164 | Update/Inform the object of changes made from other clients.
165 | Input:
166 | *param_name*: Parameter name
167 | *param_value*: Parameter value
168 | Ideal to use when the parameters can be changed from multiple clients
169 | simultaneously.
170 | '''
171 | self.parameters[param_name].v = param_value
172 | return
173 |
174 | def get_param_names(self):
175 | #CONVENIENCE FUNCTION. IMPLEMENTATION IS NOT REQUIRED
176 | '''
177 | Returns names of all the parameters
178 | '''
179 | return self.parameters.keys()
180 |
181 | def save_parameters(self, filename, *kwargs):
182 | #CONVENIENCE FUNCTION. IMPLEMENTATION IS NOT REQUIRED
183 | '''
184 | Saves parameters to a file
185 | '''
186 | d = self.get_parameters()
187 | with open(filename, 'w') as f:
188 | f.write("\n".join(["%s\t%.17e" % (k, v) for k, v in d.items()]))
189 | print('Parameters have been saved to the file {0}'.format(filename))
190 | return None
191 |
192 | def load_parameters(self, filename, *kwargs):
193 | #CONVENIENCE FUNCTION. IMPLEMENTATION IS NOT REQUIRED
194 | '''
195 | Saves parameters to a file
196 | '''
197 | name_value_pairs = {}
198 | with open(filename, 'r') as f:
199 | while True:
200 | s = f.readline()
201 | if len(s) == 0:
202 | break
203 | else:
204 | s = s.strip()
205 |
206 | if s[0] == '%' or s[0] == '#':
207 | continue
208 | if s.find(' ')!=-1:
209 | sp = s.split(' ')
210 | elif s.find('\t')!=-1:
211 | sp = s.split('\t')
212 | else:
213 | raise Exception('Unknown delimiter. Reads spaces or tabs.')
214 |
215 | name_value_pairs[sp[0]] = sp[1]
216 | self.set_parameters(name_value_pairs)
217 |
218 |
219 |
220 |
221 | return None
222 |
223 | def reset(self):
224 | #CONVENIENCE FUNCTION. IMPLEMENTATION IS NOT REQUIRED
225 | '''
226 | Resets all the parameters to default values
227 | '''
228 | return None
229 |
230 | @contextmanager
231 | def context_get_param(self):
232 | #CONVENIENCE FUNCTION. IMPLEMENTATION IS NOT REQUIRED
233 | '''
234 | Convenience contextmanager:
235 | Context used when getting parameter object
236 | '''
237 | #This implementation raises an informative exception
238 | try:
239 | yield
240 | except KeyError as e:
241 | raise KeyError('There is no parameter {0} in the configurator'.
242 | format(e.message))
243 |
244 |
245 | class MappingsBase(ResourceManagerBase):
246 | def __init__(self):
247 | '''
248 | MappingsBase()
249 | Base class for managing mappings
250 |
251 | Contains methods:
252 | - add_mappings() (required)
253 | - set_mappings(mappings) (optional)
254 | - get_mappings()
255 | - clear_mappings()
256 | - del_mappings() (optional, not used by pyNCS by default)
257 | '''
258 | ResourceManagerBase.__init__(self)
259 |
260 | def add_mappings(self, mappings):
261 | #IMPLEMENT (REQUIRED)
262 | '''
263 | Adds *mappings* to the mappings table.
264 |
265 | Inputs:
266 | *mappings*: a two-dimenstional iterable
267 | '''
268 | pass
269 |
270 | def get_mappings(self):
271 | #IMPLEMENT (REQUIRED)
272 | '''
273 | Returns an array representing the mappings
274 | '''
275 | return None
276 |
277 | def clear_mappings(self):
278 | #IMPLEMENT (REQUIRED)
279 | '''
280 | Clears the mapping table. No inputs
281 | '''
282 | return None
283 |
284 | def set_mappings(self, mappings):
285 | #CONVIENCE FUNCTION, IMPLEMENTATION NOT REQUIRED
286 | '''
287 | Clears the mapping table and adds *mappings* to the mappings table.
288 |
289 | Inputs:
290 | *mappings*: a two-dimenstional iterable
291 | '''
292 | self.clear_mappings()
293 | self.add_mappings(mappings)
294 |
295 | def del_mappings(self):
296 | #IMPLEMENT (OPTIONAL)
297 | '''
298 | Clears the mapping table. No inputs
299 | '''
300 | raise NotImplementedError('del_mappings has not been implemented')
301 |
302 | def filter_events(self, events):
303 | #CONVIENCE FUNCTION, IMPLEMENTATION NOT REQUIRED
304 | '''
305 | Before Neurosetup sends the physical events are setup, they are first passed through this function. Useful if there are no virtual neurons.
306 | '''
307 | return events
308 |
309 | # Default blank initializations
310 | # Override these classes in custom API as required
311 | Configurator = ConfiguratorBase
312 | Mappings = MappingsBase
313 |
--------------------------------------------------------------------------------
/docs/general/tutorial.txt:
--------------------------------------------------------------------------------
1 | Step by step tutorial
2 | =====================
3 |
4 | In this example we will guide you to the first use of the hardware setup. The
5 | neural network we will build has the following structure:
6 |
7 | - a population of 50 neurons
8 | - a DVS sensor that sends excitatory input to the population
9 |
10 | We will assume the hardware setup is on and working properly. If this is not
11 | the case, please refer to the hardware section of the documentation.
12 |
13 | Import
14 | ------
15 |
16 | ::
17 |
18 | import pyNCS
19 |
20 | That's it.
21 |
22 | Loading a setup
23 | ---------------
24 |
25 | With *setup* we refer to the set of chips, boards, mapper, server, clients...
26 | everything that is used in the hardware experiment. To control the setup we
27 | implemented a `pyNCS.NeuroSetup` class. First copy the contents of `chipfiles`, `biases` and `setupfiles` directory from the pyNCS module to a local folder where you want to the experiments. Then run::
28 |
29 | #Specifies the path to the setupfiles directory
30 | setupdir = './setupfiles/'
31 | #Constructs the nsetup object.
32 | nsetup = pyNCS.NeuroSetupAPI(setupdir+'zenzero_setuptype.xml',
33 | setupdir+'zenzero.xml',
34 | prefix='./'
35 | )
36 |
37 | The setup is needed to create all the elements of the experiment, such as
38 | populations, connections, stimuli etc. It encapsulates all the informations
39 | about the hardware used. These informations are contained in xml files.
40 |
41 |
42 | The first xml file contains the setuptype. In this example, the setuptype is a
43 | setup with 4 AER channels: 4 chips can be connected in a loop.
44 | The second xml file contains informations about which chip is connected to
45 | which AEX board and which AMDA board. These informations are needed by the
46 | system to access chips, i.e. get/set biases, send/receive as well as
47 | encode/decode AER events, get/set mapping tables implementing the connectivity
48 | of the network, etc. (see :doc:`installation` for more details).
49 |
50 | .. note:: If you run through the network, which means for this tutorial any computer besides zenzero, then you must have an account on zenzero and copied your public key to it. You can conveniently do this with::
51 |
52 | ssh-copy-id -i ~/.ssh/id_rsa.pub username@zenzero
53 |
54 | For example, to get all the parameters of a chip::
55 |
56 | parameters = nsetup.chips['ifslwta0'].get_parameters()
57 |
58 | .. note:: In case there are problems in loading the setup, you may want to take a look at `:doc:` to fix or prevent errors.
59 |
60 | Creating populations
61 | --------------------
62 |
63 | A population is a group of neurons on a chip. Each chip contains a certain
64 | number of neuronal circuits (somata). Each neuron has a certain number of
65 | synapses. If the chip is a neuromorphic sensor, it is very unlikely to have
66 | synapses...
67 |
68 | Let's create a population of neurons::
69 |
70 | my_pop = pyNCS.Population( 'my_pop', 'My first population')
71 |
72 | The population is empty until we *populate* it, which means we have to fill it
73 | up::
74 |
75 | my_pop.populate_by_number( nsetup, 'ifslwta0', 'excitatory', 50)
76 |
77 | There are several ways of populating. In this example we don't care about the
78 | position of the neurons on the chip, we just want to use 50 neurons. To do
79 | this, we called the `populate_by_number` function with the following
80 | arguments:
81 |
82 | - ``nsetup``: the setup
83 | - ``'ifslwta0'``: this is the name of the chip containing the neurons we want to
84 | use
85 | - ``'excitatory'``: in a neuromorphic chip there are in general several groups of
86 | neurons, sharing biases, connectivity or other properties. We have to tell
87 | the system which one of these groups we want to pick-up neurons from.
88 | - ``50``: the number of neurons we need
89 |
90 | Neurons and synapses are represented as digital addresses. This means that the
91 | population is basically a container of addresses.
92 |
93 | Let's create the input population::
94 |
95 | input_pop = pyNCS.Population('input', 'Virtual input neurons')
96 | input_pop.populate_by_number(nsetup, 'seq', 'excitatory', 100)
97 |
98 | The virtual chip 'seq' has 4096 neurons, but the corresponding population will have 100 neurons. You can check this by typing::
99 |
100 | len(input_pop) #Should output 100
101 |
102 | Setting parameters
103 | ------------------
104 |
105 | Each chip has a certain amount of parameters that can be set. Parameters are
106 | mostly biases and we can control them by changing gate voltages of the
107 | corresponding transistors. Normally there is a voltage that controls the leak
108 | of the neuron, one that controls the weight of the excitatory synapses, one for
109 | the time constants, and so on and so forth. Before starting any experiment with
110 | the hardware one has to *set* the biases, which more or less corresponds to the
111 | *boot* operation of traditional computers.
112 |
113 | The relation between a voltage and
114 | the corresponding physical quantity that it controls is what is called
115 | parameter translation. There are several theoretical and empirical methods that
116 | try to operate this translation in a systematic and reliable way in order to
117 | adjust the parameters to each experiment. We will not cover the problem here
118 | and will assume you are already in possess of basic sets of biases. What this
119 | practically means is explained as follows.
120 |
121 | The set of parameters can be very large. Usually we handle this parameters
122 | using text files. We already have bias files for default sets of parameters for
123 | basic experiments but each experiments has usually its own set. Most probably
124 | you have already copied the biase files into the ``biases`` folder. Now you
125 | would like to load this biases to *boot* the system in the proper
126 | configuration. The operation is as simple as the following::
127 |
128 | nsetup.chips['ifslwta0'].load_parameters('biases/ifslwta_default.biases')
129 |
130 | .. note:: The DVS sensor doesn't have digital biases but physical potentiometers
131 | on the board it is soldered on. Do not change them unless you know what you are doing.
132 |
133 | Creating connections
134 | --------------------
135 |
136 | We now need to connect the sensor output the excitatory synapses of our
137 | population of 50 neurons. This will be done using the ``pyNCS.Connection``
138 | class::
139 |
140 | C = pyNCS.Connection(input_pop, my_pop, 'excitatory0', 'all2all')
141 |
142 | The ``excitatory0`` string is the name of the excitatory synapses the each
143 | neuron of the ``ifslwta0`` chip has. The last argument is the connectivity
144 | *fashion*, the default one is a one-to-one connectivity. With an all-to-all
145 | connectivity, our 50 neurons will represent the average activity of the whole
146 | input array.
147 |
148 | .. note:: There is also a lower level `pyMap module`_ which also has a very
149 | nice interactive GUI. You may want to use it to check that the
150 | mapping is correct. (As of Jan 2012, pyMAP is broken). Try the following::
151 |
152 | mapper_hostname = 'zanzara2' # change this to the real hostname!
153 | M = pyMap.Mapping(setup, host=mapper_hostname).gui()
154 | M.mainloop()
155 |
156 | .. _pyMap module: pymap.html
157 |
158 | Sending and receiving stimuli
159 | -----------------------------
160 |
161 | In some experiments you want to interact in real-time with the system. For
162 | example, you might have sets of recordings of calcium concentrations that you
163 | want to convert into spikes and send to the system. Here we will show how to
164 | send and receive events from the hardware.
165 |
166 | Suppose you have vectors of mean-rates of a population of
167 | neurons. You can now create poisson trains with constant mean-rates
168 | corresponding to those of your vector. Let's than turn off the DVS (power off)
169 | to replace the real-time input with the input we will send to the system.
170 |
171 | There are several functions to create trains of spikes. These functions are
172 | usually methods of the ``population.soma`` group.
173 |
174 | ::
175 |
176 | from numpy import random
177 | #Generate a list of random numbers uniformly distributed in [20,30]
178 | meanrates = random.random(len(input_pop))*10 + 20
179 |
180 | stim = input_pop.soma.spiketrains_poisson(meanrates, duration=2000)
181 |
182 | The variable ``stim`` now contains our spike-trains (a ``SpikeList`` instance from
183 | ``pyST.spikes``) with poisson trains of random mean-rates between 20Hz and 30Hz
184 | lasting for 2000ms.
185 |
186 | By default, the input synapse 'excitatory0' is initially turned off by setting its weight to zero. You can increase the weight by setting the appropriate bias as follows::
187 |
188 | nsetup.chips['ifslwta0'].set_parameter('nsynstdw0',0.4)
189 |
190 | We can not send the input and monitor some output using nsetup.run::
191 |
192 | output = nsetup.run(stim)
193 |
194 | .. note:: If you are using the 'pyAex.api.com_aextcpclient' as the communicator (see :doc:`installation`), you must be sure that the server is started on the host::
195 |
196 | #Go to your pyAex direction in a shell on the host computer
197 | cd pyAex/Script/
198 | #Start the server
199 | python Server.py
200 |
201 | To stop the server, type ``stop``
202 |
203 |
204 | Monitors and plots
205 | ------------------
206 |
207 | There are several ways to visualize spiketrains. Assuming stim is a SpikeList object, the most basic vizualization is as follows::
208 |
209 | from pylab import ion
210 | ion()
211 |
212 | stim[input_pop.soma.channel].raster_plot()
213 |
214 | output[my_pop.soma.channel].raster_plot()
215 |
216 | Monitors are a much more convenient way of visualizing data when dealing with
217 | several populations of neurons. A monitor will slice addresses and times according to the Population it is monitoring.
218 |
219 | Create a monitor with the following::
220 |
221 | from pyNCS.monitors import SpikeMonitor
222 | my_mon = SpikeMonitor(my_pop.soma)
223 |
224 | Then import it to the setup with::
225 |
226 | nsetup.monitors.import_monitors([my_mon])
227 |
228 | When ``nsetup.run`` is run, ``my_mon`` gets automatically populated with the relevant output spikes. You will have to run ``nsetup.run`` again or ``nsetup.monitors.populate_monitors(output)``.
229 | Raster plots and rate plots can be convienently obtained with::
230 |
231 | from pyNCS.monitors import RasterPlot, MeanRatePlot
232 | RasterPlot(my_mon)
233 | MeanRatePlot(my_mon)
234 |
235 | The results should look like this:
236 |
237 | .. image:: ../images/meanrate_tutorial.png
238 | :width: 400px
239 |
240 | .. image:: ../images/raster_tutorial.png
241 | :width: 400px
242 |
243 | You can also use SpikeMonitors to vizualize inputs::
244 |
245 | input_mon = SpikeMonitor(input_pop.soma)
246 | input_mon.populate(stim[input_pop.soma.channel])
247 | RasterPlot(input_mon)
248 | MeanRatePlot(input_mon)
249 |
250 |
251 | Beyond this tutorial
252 | --------------------
253 |
254 | Congratulations, you have completed the first NCS tutorial and began your neuromorphic hardware career.
255 | If you want to see furhter examples, download the zenzero_unittest folder from the svn repository https://svn.ini.uzh.ch/repos/ncs/ini/code/python/ncs_unittests/zenzero_unittest, and take a look at the folders in the test directory. Each test can be run independently by typing::
256 |
257 | cd tests/test_swta_ifslwta0
258 | ipython
259 | run expRun
260 |
261 | The entire unittests can be run with::
262 |
263 | python zenzero_unittest.py
264 |
265 |
266 |
267 |
268 |
269 |
270 |
--------------------------------------------------------------------------------
/docs/general/installation.txt:
--------------------------------------------------------------------------------
1 | Software Installation
2 | =====================
3 |
4 | Preliminary remarks
5 | -------------------
6 |
7 | The software is mainly tested on Linux. It has been reported to work on Mac OS X without considerable difficulty, but is is currently not supported by Windows.
8 |
9 | Prerequisites
10 | .............
11 |
12 | You first need the following python packages
13 |
14 | - `python `_
15 | - `python-dev `_
16 | - `numpy `_
17 | - `scipy `_
18 | - `matplotlib `_
19 | - `pydot `_
20 | - `lxml `_
21 |
22 | For real-time vizualization, you will need Enthoughts Chaco Module:
23 |
24 | - `TraitsGUI `_
25 | - `chaco `_
26 |
27 |
28 | Finally, a nice matlab--style Python prompt is IPython.
29 |
30 | - (Optional) `IPython `_
31 |
32 | You can try to install all these packages in ubuntu, add the "universe" repository and run the following command in a terminal:
33 |
34 | ``sudo apt-get install python python-pydot python-dev python-numpy python-matplotlib iPython python-scipy python-chaco python-lxml``
35 |
36 |
37 | Optional packages:
38 |
39 | - `interval `_
40 | - `Python Imaging Library (PIL) `_
41 | - `TableIO `_
42 | - `setuptools `_
43 | - `wxPython `_
44 |
45 | Installation of pyNCS
46 | ---------------------
47 |
48 | - This packages contains all the objects needed for the setup. You can download
49 | the latest version of pyNCS by running the following command through your commandline tools.
50 |
51 | ``git clone https://github.com/inincs/pyNCS.git``
52 |
53 | For installing the python package go to the downloaded directory and run
54 |
55 | ``sudo python setup.py install``
56 |
57 | You can do the same for any python package.
58 |
59 |
60 | Installation of INI python packages
61 | -----------------------------------
62 |
63 |
64 | The NCS drivers can be downloaded directly from their respective repositories.
65 |
66 | - pyAMDA: this module is required by pyNCS and contains the module to set the biases (responsible: Sadique Sheik, Daniel Sonnleithner)
67 |
68 | ``svn co https://svn.ini.unizh.ch/repos/ncs/ini/code/python/pyAMDA``
69 |
70 | - pyAex: This module has the client and servers classes used for Stimulation/Monitoring module the chips and setting the mappings (responsible: Emre_)
71 |
72 | ``svn co https://svn.ini.uzh.ch/repos/ncs/ini/code/python/pyAex``
73 |
74 |
75 | This will install the python module to the appropriate place on your system.
76 |
77 | **The following is only needed if your computer is going to act as a server, i.e. it will be directly connected to an AEX board. If you don't know what this means, this means it is probably not required**
78 |
79 | If your computer is going to act as a Server (i.e. you are going to connect
80 | chips to your computer), you also need
81 |
82 | - fxload
83 |
84 | ``sudo apt-get install fxload``
85 |
86 | - aerfx2 and fx2: the driver for the AEX boards (Daniel_)
87 | - udevamda: the udev rule for the amda boards (Sadique Sheik, Daniel Sonnleithner). you may install the udev rules by running ``make install`` as root in the udevamda directory
88 |
89 | Setup files and chip files explained
90 | ------------------------------------
91 |
92 | The "setup files" and the "chip files" contain information about the hardware setup, such
93 | as IP addresses of the servers and mappers, ID of the boards connected, the list of the chips connected to the hardware, how to interpret AER packets, and so on.
94 | The pyNCS package comes with them in the ``test/setupfiles`` and ``test/chipfiles``
95 | folders. Here we explain some details about them.
96 |
97 | Chip files
98 | ..........
99 |
100 | Chip files contain information that the driver needs to get/set biases (parameters) on the chip and translate its address events. This information is contained in a csv file, for example ``ifslwta.csv``. Higher level information relative to the neurons and the synapses present on the chip is contained in an xml file with the same basename, for example ``ifslwta.xml``.
101 | Chip files are usually written once for every type of chip, and do not need to be changed.
102 |
103 | Setup files
104 | ...........
105 |
106 | The setup files indicate which chip is connected to which AER interface (e.g. AEX board), the latter being referred to as a `slot`. Each slot is associated to one channel. There are at least as many slots as there are chips.
107 |
108 | There are two xml files for the setup. One is a *setup type file*, for example ``setuptype.xml``,
109 | the other is a *setup file*, for example ``setup.xml``. The former is the general description of the setup, which you need to modify if you are building a new setup, but stays fixed otherwise. The latter one described which chips are present in the actual setup, and which software modules it should use to access it.
110 |
111 | setuptype.xml
112 | """""""""""""
113 | Here is an example of setup type file::
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 | ``channelAddressing``
137 |
138 | First, the setuptype must contain two ```` tags. These indicate the encoding of the channels, one for the monitoring ( with attribute ``type="monitor"``), one for the sequencing ( with attribute ``type="sequencer"`` input to chip). The attribute ``bits`` defines the list of bit positions which encode the channel.
139 | For example, the address space used in the above setup type file is::
140 |
141 | | channel | chip address space |
142 | | 16 15 14 | 13 12 11 10 9 8 7 6 5 4 3 2 1 |
143 |
144 | meaning, for instance, that the address event ``0x64d2`` monitored from the setup will be decoded into channel ``3`` and chip address ``0x4d2``.
145 |
146 |
147 | ``slot``
148 |
149 | The setup type then contains a number of ```` tags. One chip will occupy one slot, as defined by the associated ``setup.xml`` file (see below). The ``id`` can be anything, but it must match with the associated setup file. In the setup type file, the slots define how the channel of its sequencer and the monitor.
150 | Usually, you only need to define the channel number in the attribute ``out`` for ```` and ``in`` for ````. The others are used in special cases.
151 |
152 | For example, take ````::
153 |
154 |
155 |
156 |
157 |
158 |
159 | This slot has ```` , meaning that the address ``0x64d2`` will be interpreted as originating from channel number ``3``, meaning the chip in slot ``3``. The number in brackets refers to the channel number encoded by the channel bits. In the example above these were bits 16 15 and 14.
160 | The same slot contains the tag ````. This indicates that, to stimulate synapse ``0x4d2``, a ``0xe000`` (corresponding to ``7 * 2^13``) must be added.
161 |
162 | Again the ``in`` in aerMon and the ``out`` in aerSeq are usally not used, so their function is not covered here.
163 |
164 | If possible, the setuptype will be checked against a DTD available online (Document Type Definition)
165 |
166 |
167 | setup.xml
168 | """""""""
169 |
170 | The ``setup.xml`` file describes which chips fit in the slots defined in the setup type. All the tags in setup.xml are enclosed by the ```` tags. The ```` should contain ```` tags, one for each chip. Here is an example::
171 |
172 |
173 |
174 |
175 |
176 | zsd
177 | T03
178 |
179 |
180 |
181 |
182 |
183 | zsd
184 | 5
185 |
186 |
187 | zanzara2
188 | 1.0
189 |
190 |
191 |
192 | Let's analyze it attribute by attribute.
193 |
194 | ``chipfile``
195 | Usually chipfiles and setupfiles are stored in the client in some common
196 | directory, it could be ``/usr/share/ncs/`` or ``~/.ncs``, so that every
197 | experiment just refers to that common source. If this is not the case you have
198 | to make sure setupfiles correctly point to chipfiles.
199 |
200 | ``id``
201 | This defines the name of the chip. This name will be used in pyNCS to identify it.
202 |
203 | ````
204 | indicates the configurator API which should be used to access the chip
205 | biases. In this case, it contains the information about which chip is
206 | connected to which host (server) and which AMDA board -- the board that
207 | gets/sets biases on the chip. The attribute ``module=pyAmda.api`` is the
208 | python module implementing the configurator API. The parameter elements are
209 | used as keyword arguments for that module, in this case
210 | {'host':'zsd','board':'T03'}. The actual id of the AMDA board should be
211 | written on a sticker below the board itself, e.g. could be ``AMDA #2.09``.
212 |
213 | ``slot``
214 | what we call the channel. On top of the FPGA mounted on the AEX board there
215 | should be a sticker referring to the channel number. In this case it should be
216 | ``FES 0``.
217 |
218 | In addition, there are ```` and ```` tags. The former defines a chip which does not physically exist, therefore does not have a configurator. It is typically used to provide 'input neurons'.
219 | The latter (````) defines the default virtual chip to use if a slot that is defined in setuptup is not present in the setup.xml. Note that ```` does not take a configurator element, therefore defaultchip is only specifies virtual chips.
220 |
221 | The last fields of the ``setup.xml`` file describes which modules should be used to communicate with the setup::
222 |
223 |
224 | zsd
225 | 5
226 |
227 |
228 | zanzara2
229 | 1.0
230 |
231 |
232 |
233 | ```` and ````
234 | indicate the modules implementing the respective pyNCS API (communicator or mapper). As with the ````, the parameter elements are used as keyword arguments for that module. The ones indicated above are probably the ones you would like to use. See pyNCS documentation otherwise.
235 |
236 | .. image:: ../images/amda_and_aex.jpg
237 | :width: 400px
238 |
239 | .. _Emre: mailto:emre(at)ini.phys.ethz.ch
240 | .. _Daniel: mailto:fasnacht(at)sos.phys.ethz.ch
241 | .. _ncs: http://ncs.ethz.ch
242 |
--------------------------------------------------------------------------------