Skip to content

Top-level methods#

These methods are directly available in the main namespace when importing ANNarchy:

from ANNarchy import *

Note that numpy is automatically imported as:

import numpy as np

Configuration and compilation#

Contrary to other simulators, ANNarchy is entirely based on code generation. It provides a set of first-level functions to ensure the network is correctly created. It is important to call these functions in the right order.

ANNarchy.setup(**keyValueArgs) #

The setup function is used to configure ANNarchy simulation environment. It takes various optional arguments:

  • dt: simulation step size (default: 1.0 ms).
  • paradigm: parallel framework for code generation. Accepted values: "openmp" or "cuda" (default: "openmp").
  • method: default method to numerize ODEs. Default is the explicit forward Euler method ('explicit').
  • sparse_matrix_format: the default matrix format for projections in ANNarchy (by default: List-In-List for CPUs and Compressed Sparse Row). Note that affects only the C++ data structures.
  • sparse_matrix_storage_order: encodes whether the row in a connectivity matrix encodes pre-synaptic neurons (post_to_pre, default) or post-synaptic neurons (pre_to_post). Note that affects only the C++ data structures.
  • precision: default floating precision for variables in ANNarchy. Accepted values: "float" or "double" (default: "double")
  • num_threads: number of treads used by openMP (overrides the environment variable OMP_NUM_THREADS when set, default = None).
  • visible_cores: allows a fine-grained control which cores are useable for the created threads (default = [] for no limitation). It can be used to limit created openMP threads to a physical socket.
  • structural_plasticity: allows synapses to be dynamically added/removed during the simulation (default: False).
  • seed: the seed (integer) to be used in the random number generators (default = -1 is equivalent to time(NULL)).

The following parameters are mainly for debugging and profiling, and should be ignored by most users:

  • verbose: shows details about compilation process on console (by default False). Additional some information of the network construction will be shown.
  • suppress_warnings: if True, warnings (e. g. from the mathematical parser) are suppressed.
  • show_time: if True, initialization times are shown. Attention: verbose should be set to True additionally.
  • disable_shared_library_time_offset: by default False. If set to True, the shared library generated by ANNarchy will not be extended by time offset.

Note:

This function should be used before any other functions of ANNarchy (including importing a network definition), right after from ANNarchy import *:

from ANNarchy import *
setup(dt=1.0, method='midpoint', num_threads=2)
Source code in ANNarchy/core/Global.py
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
def setup(**keyValueArgs):
    """
    The setup function is used to configure ANNarchy simulation environment. It takes various optional arguments:

    * dt: simulation step size (default: 1.0 ms).
    * paradigm: parallel framework for code generation. Accepted values: "openmp" or "cuda" (default: "openmp").
    * method: default method to numerize ODEs. Default is the explicit forward Euler method ('explicit').
    * sparse_matrix_format: the default matrix format for projections in ANNarchy (by default: List-In-List for CPUs and Compressed Sparse Row).
                            Note that affects only the C++ data structures.
    * sparse_matrix_storage_order: encodes whether the row in a connectivity matrix encodes pre-synaptic neurons (post_to_pre, default) or 
                                   post-synaptic neurons (pre_to_post). Note that affects only the C++ data structures.
    * precision: default floating precision for variables in ANNarchy. Accepted values: "float" or "double" (default: "double")
    * num_threads: number of treads used by openMP (overrides the environment variable ``OMP_NUM_THREADS`` when set, default = None).
    * visible_cores: allows a fine-grained control which cores are useable for the created threads (default = [] for no limitation).
                     It can be used to limit created openMP threads to a physical socket.
    * structural_plasticity: allows synapses to be dynamically added/removed during the simulation (default: False).
    * seed: the seed (integer) to be used in the random number generators (default = -1 is equivalent to time(NULL)).

    The following parameters are mainly for debugging and profiling, and should be ignored by most users:

    * verbose: shows details about compilation process on console (by default False). Additional some information of the network construction will be shown.
    * suppress_warnings: if True, warnings (e. g. from the mathematical parser) are suppressed.
    * show_time: if True, initialization times are shown. Attention: verbose should be set to True additionally.
    * disable_shared_library_time_offset: by default False. If set to True, the shared library generated by ANNarchy will not be extended by time offset.

    **Note:**

    This function should be used before any other functions of ANNarchy (including importing a network definition), right after `from ANNarchy import *`:

    ```python
    from ANNarchy import *
    setup(dt=1.0, method='midpoint', num_threads=2)
    ```

    """
    if len(_network[0]['populations']) > 0 or len(_network[0]['projections']) > 0 or len(_network[0]['monitors']) > 0:
        if 'dt' in keyValueArgs:
            _warning('setup(): populations or projections have already been created. Changing dt now might lead to strange behaviors with the synaptic delays (internally generated in steps, not ms)...')
        if 'precision' in keyValueArgs:
            _warning('setup(): populations or projections have already been created. Changing precision now might lead to strange behaviors...')

    for key in keyValueArgs:
        # sanity check: filter out performance flags
        if key in _performance_related_config_keys:
            _error("Performance related flags can not be configured by setup()")

        if key in config.keys():
            config[key] = keyValueArgs[key]
        else:
            _warning('setup(): unknown key:', key)

        if key == 'seed': # also seed numpy
            np.random.seed(keyValueArgs[key])

ANNarchy.compile(directory='annarchy', clean=False, populations=None, projections=None, compiler='default', compiler_flags='default', add_sources='', extra_libs='', cuda_config={'device': 0}, annarchy_json='', silent=False, debug_build=False, profile_enabled=False, net_id=0) #

This method uses the network architecture to generate optimized C++ code and compile a shared library that will perform the simulation.

The compiler, compiler_flags and part of cuda_config take their default value from the configuration file ~/.config/ANNarchy/annarchy.json.

The following arguments are for internal development use only:

  • debug_build: creates a debug version of ANNarchy, which logs the creation of objects and some other data (default: False).
  • profile_enabled: creates a profilable version of ANNarchy, which logs several computation timings (default: False).

Parameters:

  • directory

    name of the subdirectory where the code will be generated and compiled. Must be a relative path. Default: "annarchy/".

  • clean

    boolean to specifying if the library should be recompiled entirely or only the changes since last compilation (default: False).

  • populations

    list of populations which should be compiled. If set to None, all available populations will be used.

  • projections

    list of projection which should be compiled. If set to None, all available projections will be used.

  • compiler

    C++ compiler to use. Default: g++ on GNU/Linux, clang++ on OS X. Valid compilers are [g++, clang++].

  • compiler_flags

    platform-specific flags to pass to the compiler. Default: "-march=native -O2". Warning: -O3 often generates slower code and can cause linking problems, so it is not recommended.

  • cuda_config

    dictionary defining the CUDA configuration for each population and projection.

  • annarchy_json

    compiler flags etc can be stored in a .json file normally placed in the home directory (see comment below). With this flag one can directly assign a file location.

  • silent

    defines if status message like "Compiling... OK" should be printed.

Source code in ANNarchy/generator/Compiler.py
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
def compile(
        directory='annarchy',
        clean=False,
        populations=None,
        projections=None,
        compiler="default",
        compiler_flags="default",
        add_sources="",
        extra_libs="",
        cuda_config={'device': 0},
        annarchy_json="",
        silent=False,
        debug_build=False,
        profile_enabled=False,
        net_id=0
    ):
    """
    This method uses the network architecture to generate optimized C++ code and compile a shared library that will perform the simulation.

    The ``compiler``, ``compiler_flags`` and part of ``cuda_config`` take their default value from the configuration file ``~/.config/ANNarchy/annarchy.json``.

    The following arguments are for internal development use only:

    * **debug_build**: creates a debug version of ANNarchy, which logs the creation of objects and some other data (default: False).
    * **profile_enabled**: creates a profilable version of ANNarchy, which logs several computation timings (default: False).

    :param directory: name of the subdirectory where the code will be generated and compiled. Must be a relative path. Default: "annarchy/".
    :param clean: boolean to specifying if the library should be recompiled entirely or only the changes since last compilation (default: False).
    :param populations: list of populations which should be compiled. If set to None, all available populations will be used.
    :param projections: list of projection which should be compiled. If set to None, all available projections will be used.
    :param compiler: C++ compiler to use. Default: g++ on GNU/Linux, clang++ on OS X. Valid compilers are [g++, clang++].
    :param compiler_flags: platform-specific flags to pass to the compiler. Default: "-march=native -O2". Warning: -O3 often generates slower code and can cause linking problems, so it is not recommended.
    :param cuda_config: dictionary defining the CUDA configuration for each population and projection.
    :param annarchy_json: compiler flags etc can be stored in a .json file normally placed in the home directory (see comment below). With this flag one can directly assign a file location.
    :param silent: defines if status message like "Compiling... OK" should be printed.
    """
    # Check if the network has already been compiled
    if Global._network[net_id]['compiled']:
        Global._print("""compile(): the network has already been compiled, doing nothing.
    If you are re-running a Jupyter notebook, you should call `clear()` right after importing ANNarchy in order to reset everything.""")
        return

    # Get command-line arguments. Note that setup() related flags has been partially parsed!
    options, unknown = ANNarchy._arg_parser.parser.parse_known_args()

    # Check for unknown flags
    if len(unknown) > 0 and Global.config['verbose']:
        Global._warning('unrecognized command-line arguments:', unknown)

    # Get CUDA configuration
    if options.gpu_device >= 0:
        cuda_config['device'] = int(options.gpu_device)

    # Check that a single backend is chosen
    if (options.num_threads != None) and (options.gpu_device >= 0):
        Global._error('CUDA and openMP can not be active at the same time, please check your command line arguments.')

    # check if profiling was enabled by --profile
    if options.profile != None:
        profile_enabled = options.profile
        Global.config['profiling'] = options.profile
        Global.config['profile_out'] = options.profile_out
    # check if profiling enabled due compile()
    if profile_enabled != False and options.profile == None:
        Global.config['profiling'] = True
    # if profiling is enabled
    if profile_enabled:
        from ANNarchy.core.Profiler import Profiler
        # this will automatically create and register Global._profiler instance
        profiler = Profiler()
        if Global.config['profile_out'] == None:
            Global.config['profile_out'] = "."

    # Debug
    if not debug_build:
        debug_build = options.debug  # debug build
    Global.config["debug"] = debug_build

    # Clean
    clean = options.clean or clean # enforce rebuild

    # Populations to compile
    if populations is None: # Default network
        populations = Global._network[net_id]['populations']

    # Projections to compile
    if projections is None: # Default network
        projections = Global._network[net_id]['projections']

    # Compiling directory
    annarchy_dir = os.getcwd() + '/' + directory
    if not annarchy_dir.endswith('/'):
        annarchy_dir += '/'

    # Turn OMP off for MacOS
    #if (Global._check_paradigm("openmp") and Global.config['num_threads'] > 1 and sys.platform == "darwin"):
    #    Global._warning("OpenMP is still not supported by the default clang on Mac OS... Running single-threaded.")
    #    Global.config['num_threads'] = 1

    # Test if the current ANNarchy version is newer than what was used to create the subfolder
    from pkg_resources import parse_version
    if os.path.isfile(annarchy_dir+'/release'):
        with open(annarchy_dir+'/release', 'r') as rfile:
            prev_release = rfile.read().strip()
            prev_paradigm = ''

            # HD (03.08.2016):
            # in ANNarchy 4.5.7b I added also the paradigm to the release tag.
            # This if clause can be removed in later releases (TODO)
            if prev_release.find(',') != -1:
                prev_paradigm, prev_release = prev_release.split(', ')
            else:
                # old release tag
                clean = True

            if parse_version(prev_release) < parse_version(ANNarchy.__release__):
                clean = True

            elif prev_paradigm != Global.config['paradigm']:
                clean = True

    else:
        clean = True # for very old versions

    # Check if the last compilation was successful
    if os.path.isfile(annarchy_dir+'/compilation'):
        with open(annarchy_dir + '/compilation', 'r') as rfile:
            res = rfile.read()
            if res.strip() == "0": # the last compilation failed
                clean = True
    else:
        clean = True

    # Manage the compilation subfolder
    _folder_management(annarchy_dir, profile_enabled, clean, net_id)

    # Create a Compiler object
    compiler = Compiler(
        annarchy_dir=annarchy_dir,
        clean=clean,
        compiler=compiler,
        compiler_flags=compiler_flags,
        add_sources=add_sources,
        extra_libs=extra_libs,
        path_to_json=annarchy_json,
        silent=silent,
        cuda_config=cuda_config,
        debug_build=debug_build,
        profile_enabled=profile_enabled,
        populations=populations,
        projections=projections,
        net_id=net_id
    )

    # Code Generation
    compiler.generate()

    if Global.config['verbose']:
        net_str = "" if compiler.net_id == 0 else str(compiler.net_id)+" "
        Global._print('Construct network '+net_str+'...', end=" ")

    # Create the Python objects
    _instantiate(compiler.net_id, cuda_config=compiler.cuda_config, user_config=compiler.user_config)

    # NormProjections require an update of afferent projections
    _update_num_aff_connections(compiler.net_id)

    if Global.config['verbose']:
        Global._print('OK')

    # Create a report if requested
    if options.report is not None:
        report(options.report)

ANNarchy.clear(functions=True, neurons=True, synapses=True, constants=True) #

Clears all variables (erasing already defined populations, projections, monitors and constants), as if you had just imported ANNarchy.

  • functions: if True (default), all functions defined with add_function are erased.
  • neurons: if True (default), all neurons defined with Neuron are erased.
  • synapses: if True (default), all synapses defined with Synapse are erased.
  • constants: if True (default), all constants defined with Constant are erased.

Useful when re-running Jupyter/IPython notebooks multiple times:

from ANNarchy import *
clear()
Source code in ANNarchy/core/Global.py
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
def clear(functions=True, neurons=True, synapses=True, constants=True):
    """
    Clears all variables (erasing already defined populations, projections, monitors and constants), as if you had just imported ANNarchy.

    * functions: if True (default), all functions defined with ``add_function`` are erased.
    * neurons: if True (default), all neurons defined with ``Neuron`` are erased.
    * synapses: if True (default), all synapses defined with ``Synapse`` are erased.
    * constants: if True (default), all constants defined with ``Constant`` are erased.

    Useful when re-running Jupyter/IPython notebooks multiple times:

    ```python
    from ANNarchy import *
    clear()
    ```
    """
    # Reset objects
    global _objects
    _objects = {
        'functions': [] if functions else _objects['functions'],
        'neurons': [] if neurons else _objects['neurons'],
        'synapses': [] if synapses else _objects['synapses'],
        'constants': [] if constants else _objects['constants'],
    }

    # Remove the present profiler
    global _profiler
    if _profiler is not None:
        check_profile_results()

        del _profiler

        # restore default values
        _profiler = None
        config["profiling"] = False

    # Reinitialize initial state
    global _network
    _network.clear()

Simulation#

Different methods are available to run the simulation:

ANNarchy.simulate(duration, measure_time=False, progress_bar=False, callbacks=True, net_id=0) #

Simulates the network for the given duration in milliseconds.

The number of simulation steps is computed relative to the discretization step dt declared in setup() (default: 1ms):

simulate(1000.0)

Parameters:

  • duration

    the duration in milliseconds.

  • measure_time

    defines whether the simulation time should be printed. Default: False.

  • progress_bar

    defines whether a progress bar should be printed. Default: False

  • callbacks

    defines if the callback method (decorator every should be called). Default: True.

Source code in ANNarchy/core/Simulate.py
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
def simulate(duration, measure_time=False, progress_bar=False, callbacks=True, net_id=0):
    """
    Simulates the network for the given duration in milliseconds. 

    The number of simulation steps is computed relative to the discretization step ``dt`` declared in ``setup()`` (default: 1ms):

    ```python
    simulate(1000.0)
    ```

    :param duration: the duration in milliseconds.
    :param measure_time: defines whether the simulation time should be printed. Default: False.
    :param progress_bar: defines whether a progress bar should be printed. Default: False
    :param callbacks: defines if the callback method (decorator ``every`` should be called). Default: True.
    """
    if Global._profiler:
        t0 = time.time()

    if not _network[net_id]['instance']:
        _error('simulate(): the network is not compiled yet.')

    # Compute the number of steps
    nb_steps = ceil(float(duration) / dt())

    if measure_time:
        tstart = time.time()

    if callbacks and _callbacks_enabled[net_id] and len(_callbacks[net_id]) > 0:
        _simulate_with_callbacks(duration, progress_bar, net_id)
    else:
        _network[net_id]['instance'].pyx_run(nb_steps, progress_bar)

    if measure_time:
        if net_id > 0:
            _print('Simulating', duration/1000.0, 'seconds of the network', net_id, 'took', time.time() - tstart, 'seconds.')
        else:
            _print('Simulating', duration/1000.0, 'seconds of the network took', time.time() - tstart, 'seconds.')

    # Store the Python and C++ timings. Please note, that the C++ core
    # measures in ms and Python measures in s
    if Global._profiler:
        t1 = time.time()
        Global._profiler.add_entry( t0, t1, "simulate", "simulate")

        # network single step
        overall_avg, _ = Global._profiler._cpp_profiler.get_timing("network", "step")
        Global._profiler.add_entry(overall_avg * nb_steps, 100.0, "overall", "cpp core")

        # single operations for populations
        for pop in _network[net_id]['populations']:
            for func in ["step", "rng", "delay", "spike"]:
                avg_time, _ = Global._profiler._cpp_profiler.get_timing(pop.name, func)
                Global._profiler.add_entry( avg_time * nb_steps, (avg_time/overall_avg)*100.0, pop.name+"_"+func, "cpp core")

        # single operations for projections
        for proj in _network[net_id]['projections']:
            for func in ["psp", "step", "post_event"]:
                avg_time, _ = Global._profiler._cpp_profiler.get_timing(proj.name, func)
                Global._profiler.add_entry( avg_time * nb_steps, (avg_time/overall_avg)*100.0, proj.name+"_"+func, "cpp core")

        monitor_avg, _ = Global._profiler._cpp_profiler.get_timing("network", "record")
        Global._profiler.add_entry( monitor_avg * nb_steps, (monitor_avg/overall_avg)*100.0, "record", "cpp core")

ANNarchy.simulate_until(max_duration, population, operator='and', measure_time=False, net_id=0) #

Runs the network for the maximal duration in milliseconds. If the stop_condition defined in the population becomes true during the simulation, it is stopped.

One can specify several populations. If the stop condition is true for any of the populations, the simulation will stop ('or' function).

Example:

pop1 = Population( ..., stop_condition = "r > 1.0 : any")
compile()
simulate_until(max_duration=1000.0, population=pop1)

Parameters:

  • max_duration

    the maximum duration of the simulation in milliseconds.

  • population

    the (list of) population whose stop_condition should be checked to stop the simulation.

  • operator

    operator to be used ('and' or 'or') when multiple populations are provided (default: 'and').

  • measure_time

    defines whether the simulation time should be printed (default=False).

Returns:

  • the actual duration of the simulation in milliseconds.

Source code in ANNarchy/core/Simulate.py
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
def simulate_until(max_duration, population, operator='and', measure_time = False, net_id=0):
    """
    Runs the network for the maximal duration in milliseconds. If the ``stop_condition`` defined in the population becomes true during the simulation, it is stopped.

    One can specify several populations. If the stop condition is true for any of the populations, the simulation will stop ('or' function).

    Example:

    ```python
    pop1 = Population( ..., stop_condition = "r > 1.0 : any")
    compile()
    simulate_until(max_duration=1000.0, population=pop1)
    ```

    :param max_duration: the maximum duration of the simulation in milliseconds.
    :param population: the (list of) population whose ``stop_condition`` should be checked to stop the simulation.
    :param operator: operator to be used ('and' or 'or') when multiple populations are provided (default: 'and').
    :param measure_time: defines whether the simulation time should be printed (default=False).
    :return: the actual duration of the simulation in milliseconds.
    """
    if not _network[net_id]['instance']:
        _error('simulate_until(): the network is not compiled yet.')


    nb_steps = ceil(float(max_duration) / dt())
    if not isinstance(population, list):
        population = [population]


    if measure_time:
        tstart = time.time()

    nb = _network[net_id]['instance'].pyx_run_until(nb_steps, [pop.id for pop in population], True if operator=='and' else False)

    sim_time = float(nb) / dt()
    if measure_time:
        _print('Simulating', nb/dt()/1000.0, 'seconds of the network took', time.time() - tstart, 'seconds.')
    return sim_time

ANNarchy.step(net_id=0) #

Performs a single simulation step (duration = dt).

Source code in ANNarchy/core/Simulate.py
122
123
124
125
126
127
128
129
130
def step(net_id=0):
    """
    Performs a single simulation step (duration = ``dt``).
    """
    if not _network[net_id]['instance']:
        _error('simulate_until(): the network is not compiled yet.')


    _network[net_id]['instance'].pyx_step()

ANNarchy.every #

Decorator to declare a callback method that will be called periodically during the simulation.

Example of setting increasing inputs to a population every 100 ms, with an offset of 90 ms (or -10 ms relative to the period):

@every(period=100., offset=-10.)
def step_input(n):
    pop.I = float(n) / 100.

simulate(10000.)

step_input() will be called at times 90, 190, ..., 9990 ms during the call to simulate().

The method must accept only n as parameter (an integer being 0 the first time the method is called, and incremented afterwards) and can not return anything.

The times at which the method is called are relative to the time when simulate() is called (if t is already 150 before calling simulate(), the first call will then be made at t=240 with the previous example).

If multiple callbacks are defined, they will be called in the order of their declaration if they occur at the same time.

Source code in ANNarchy/core/Simulate.py
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
class every :
    """
    Decorator to declare a callback method that will be called periodically during the simulation.

    Example of setting increasing inputs to a population every 100 ms, with an offset of 90 ms (or -10 ms relative to the period):

    ```python
    @every(period=100., offset=-10.)
    def step_input(n):
        pop.I = float(n) / 100.

    simulate(10000.)
    ```

    ``step_input()`` will be called at times 90, 190, ..., 9990 ms during the call to ``simulate()``.

    The method must accept only ``n`` as parameter (an integer being 0 the first time the method is called, and incremented afterwards) and can not return anything.

    The times at which the method is called are relative to the time when ``simulate()`` is called (if ``t`` is already 150 before calling ``simulate()``, the first call will then be made at ``t=240`` with the previous example).

    If multiple callbacks are defined, they will be called in the order of their declaration if they occur at the same time.

    """

    def __init__(self, period, offset=0., wait=0.0, net_id=0):
        """
        :param period: interval in ms between two calls to the function. If less than ``dt``, will be called every step.
        :param offset: by default, the first call to the method will be made at the start of the simulation. The offset delays the call within the period (default: 0.0). Can be negative, in which case it will be counted from the end of the period.
        :param wait: allows to wait for a certain amount of time (in ms) before starting to call the method.

        ``wait`` can be combined with ``offset``, so if ``period=100.``, ``offset=50.`` and ``wait=500.``, the first call will be made 550 ms after the call to ``simulate()``

        """
        self.period = max(float(period), dt())
        self.offset = min(float(offset), self.period)
        self.wait = max(float(wait), 0.0)
        _callbacks[net_id].append(self)

    def __call__(self, f):

        # If there are decorator arguments, __call__() is only called
        # once, as part of the decoration process! You can only give
        # it a single argument, which is the function object.

        self.func = f
        return f

__init__(period, offset=0.0, wait=0.0, net_id=0) #

Parameters:

  • period

    interval in ms between two calls to the function. If less than dt, will be called every step.

  • offset

    by default, the first call to the method will be made at the start of the simulation. The offset delays the call within the period (default: 0.0). Can be negative, in which case it will be counted from the end of the period.

  • wait

    allows to wait for a certain amount of time (in ms) before starting to call the method. wait can be combined with offset, so if period=100., offset=50. and wait=500., the first call will be made 550 ms after the call to simulate()

Source code in ANNarchy/core/Simulate.py
188
189
190
191
192
193
194
195
196
197
198
199
200
def __init__(self, period, offset=0., wait=0.0, net_id=0):
    """
    :param period: interval in ms between two calls to the function. If less than ``dt``, will be called every step.
    :param offset: by default, the first call to the method will be made at the start of the simulation. The offset delays the call within the period (default: 0.0). Can be negative, in which case it will be counted from the end of the period.
    :param wait: allows to wait for a certain amount of time (in ms) before starting to call the method.

    ``wait`` can be combined with ``offset``, so if ``period=100.``, ``offset=50.`` and ``wait=500.``, the first call will be made 550 ms after the call to ``simulate()``

    """
    self.period = max(float(period), dt())
    self.offset = min(float(offset), self.period)
    self.wait = max(float(wait), 0.0)
    _callbacks[net_id].append(self)

ANNarchy.enable_callbacks(net_id=0) #

Enables all declared callbacks for the network.

Source code in ANNarchy/core/Simulate.py
149
150
151
152
153
def enable_callbacks(net_id=0):
    """
    Enables all declared callbacks for the network.
    """
    _callbacks_enabled[net_id] = True

ANNarchy.disable_callbacks(net_id=0) #

Disables all callbacks for the network.

Source code in ANNarchy/core/Simulate.py
143
144
145
146
147
def disable_callbacks(net_id=0):
    """
    Disables all callbacks for the network.
    """
    _callbacks_enabled[net_id] = False

ANNarchy.clear_all_callbacks(net_id=0) #

Clears the list of declared callbacks for the network.

Cannot be undone!

Source code in ANNarchy/core/Simulate.py
155
156
157
158
159
160
161
def clear_all_callbacks(net_id=0):
    """
    Clears the list of declared callbacks for the network.

    Cannot be undone!
    """
    _callbacks[net_id].clear()

Reset the network#

If you want to run multiple experiments with the same network, or if your experiment setup requires a pre-learning phase, you can reset selectively neural or synaptic variables to their initial values.

ANNarchy.reset(populations=True, projections=False, synapses=False, monitors=True, net_id=0) #

Reinitialises the network to its state before the call to compile. The network time will be set to 0ms.

All monitors are emptied.

Parameters:

  • populations

    if True (default), the neural parameters and variables will be reset to their initial value.

  • projections

    if True, the synaptic parameters and variables (except the connections) will be reset (default=False).

  • synapses

    if True, the synaptic weights will be erased and recreated (default=False).

  • monitors

    if True, the monitors will be emptied and reset (default=True).

Source code in ANNarchy/core/Global.py
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
def reset(populations=True, projections=False, synapses=False, monitors=True, net_id=0):
    """
    Reinitialises the network to its state before the call to compile. The network time will be set to 0ms.

    All monitors are emptied.

    :param populations: if True (default), the neural parameters and variables will be reset to their initial value.
    :param projections: if True, the synaptic parameters and variables (except the connections) will be reset (default=False).
    :param synapses: if True, the synaptic weights will be erased and recreated (default=False).
    :param monitors: if True, the monitors will be emptied and reset (default=True).
    """

    _network[net_id]['instance'].set_time(0)

    if populations:
        for pop in _network[net_id]['populations']:
            pop.reset()

        # pop.reset only clears spike container with no or uniform delay
        for proj in _network[net_id]['projections']:
            if hasattr(proj.cyInstance, 'reset_ring_buffer'):
                proj.cyInstance.reset_ring_buffer()

    if synapses and not projections:
        _warning("reset(): if synapses is set to true this automatically enables projections==true")
        projections = True

    if projections:
        for proj in _network[net_id]['projections']:
            proj.reset(attributes=-1, synapses=synapses)

    if monitors:
        for monitor in _network[net_id]['monitors']:
            monitor.reset()

Access to populations#

ANNarchy.get_population(name, net_id=0) #

Returns the population with the given name.

Parameters:

  • name

    name of the population.

Returns:

  • The requested Population object if existing, None otherwise.

Source code in ANNarchy/core/Global.py
320
321
322
323
324
325
326
327
328
329
330
331
332
def get_population(name, net_id=0):
    """
    Returns the population with the given ``name``.

    :param name: name of the population.
    :return: The requested ``Population`` object if existing, ``None`` otherwise.
    """
    for pop in _network[net_id]['populations']:
        if pop.name == name:
            return pop

    _warning("get_population(): the population", name, "does not exist.")
    return None

ANNarchy.get_projection(name, net_id=0) #

Returns the projection with the given name.

Parameters:

  • name

    name of the projection.

Returns:

  • The requested Projection object if existing, None otherwise.

Source code in ANNarchy/core/Global.py
334
335
336
337
338
339
340
341
342
343
344
345
346
def get_projection(name, net_id=0):
    """
    Returns the projection with the given *name*.

    :param name: name of the projection.
    :return: The requested ``Projection`` object if existing, ``None`` otherwise.
    """
    for proj in _network[net_id]['projections']:
        if proj.name == name:
            return proj

    _warning("get_projection(): the projection", name, "does not exist.")
    return None

Functions#

ANNarchy.add_function(function) #

Defines a global function which can be used by all neurons and synapses.

The function must have only one return value and use only the passed arguments.

Examples of valid functions:

logistic(x) = 1 / (1 + exp(-x))

piecewise(x, a, b) =    if x < a:
                            a
                        else:
                            if x > b :
                                b
                            else:
                                x

Please refer to the manual to know the allowed mathematical functions.

Source code in ANNarchy/core/Global.py
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
def add_function(function):
    """
    Defines a global function which can be used by all neurons and synapses.

    The function must have only one return value and use only the passed arguments.

    Examples of valid functions:

    ```python
    logistic(x) = 1 / (1 + exp(-x))

    piecewise(x, a, b) =    if x < a:
                                a
                            else:
                                if x > b :
                                    b
                                else:
                                    x
    ```

    Please refer to the manual to know the allowed mathematical functions.
    """
    name = function.split('(')[0]
    _objects['functions'].append( (name, function))

ANNarchy.functions(name, net_id=0) #

Allows to access a global function defined with add_function and use it from Python using arrays after compilation.

The name of the function is not added to the global namespace to avoid overloading.

add_function("logistic(x) = 1. / (1. + exp(-x))") 

compile()  

result = functions('logistic')([0., 1., 2., 3., 4.])

Only lists or 1D Numpy arrays can be passed as arguments, not single values nor multidimensional arrays.

When passing several arguments, make sure they have the same size.

Source code in ANNarchy/core/Global.py
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
def functions(name, net_id=0):
    """
    Allows to access a global function defined with ``add_function`` and use it from Python using arrays **after compilation**.

    The name of the function is not added to the global namespace to avoid overloading.

    ```python
    add_function("logistic(x) = 1. / (1. + exp(-x))") 

    compile()  

    result = functions('logistic')([0., 1., 2., 3., 4.])
    ```

    Only lists or 1D Numpy arrays can be passed as arguments, not single values nor multidimensional arrays.

    When passing several arguments, make sure they have the same size.

    """
    try:
        func = getattr(_network[net_id]['instance'], 'func_' + name)
    except:
        _error('call to', name, ': the function is not compiled yet.')

    return func

Constants#

ANNarchy.Constant #

Bases: float

Constant parameter that can be used by all neurons and synapses.

The class Constant derives from float, so any legal operation on floats (addition, multiplication) can be used.

If a Neuron/Synapse defines a parameter with the same name, the constant parameters will not be visible.

Example:

tau = Constant('tau', 20)
factor = Constant('factor', 0.1)
real_tau = Constant('real_tau', tau*factor)

neuron = Neuron(
    equations='''
        real_tau*dr/dt + r =1.0
    '''
)

The value of the constant can be changed anytime with the set() method. Assignments will have no effect (e.g. tau = 10.0 only creates a new float).

The value of constants defined as combination of other constants (real_tau) is not updated if the value of these constants changes (changing tau with tau.set(10.0) will not modify the value of real_tau).

Source code in ANNarchy/core/Global.py
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
class Constant(float):
    """
    Constant parameter that can be used by all neurons and synapses.

    The class ``Constant`` derives from ``float``, so any legal operation on floats (addition, multiplication) can be used.

    If a Neuron/Synapse defines a parameter with the same name, the constant parameters will not be visible.

    Example:

    ```python

    tau = Constant('tau', 20)
    factor = Constant('factor', 0.1)
    real_tau = Constant('real_tau', tau*factor)

    neuron = Neuron(
        equations='''
            real_tau*dr/dt + r =1.0
        '''
    )
    ```

    The value of the constant can be changed anytime with the ``set()`` method. Assignments will have no effect (e.g. ``tau = 10.0`` only creates a new float).

    The value of constants defined as combination of other constants (``real_tau``) is not updated if the value of these constants changes (changing ``tau`` with ``tau.set(10.0)`` will not modify the value of ``real_tau``).

    """
    def __new__(cls, name, value, net_id=0):
        return float.__new__(cls, value)

    def __init__(self, name, value, net_id=0):
        """
        :param name: name of the constant (unique), which can be used in equations.
        :param value: the value of the constant, which must be a float, or a combination of Constants.
        """

        self.name = name
        self.value = value
        self.net_id = net_id
        for obj in _objects['constants']:
            if obj.name == name:
                _error('the constant', name, 'is already defined.')
        _objects['constants'].append(self)
    def __str__(self):
        return str(self.value)
    def __repr__(self):
        return self.__str__()
    def set(self, value):
        "Changes the value of the constant."
        self.value = value
        if _network[self.net_id]['compiled']:
            getattr(_network[self.net_id]['instance'], '_set_'+self.name)(self.value)

__init__(name, value, net_id=0) #

Parameters:

  • name

    name of the constant (unique), which can be used in equations.

  • value

    the value of the constant, which must be a float, or a combination of Constants.

Source code in ANNarchy/core/Global.py
488
489
490
491
492
493
494
495
496
497
498
499
500
def __init__(self, name, value, net_id=0):
    """
    :param name: name of the constant (unique), which can be used in equations.
    :param value: the value of the constant, which must be a float, or a combination of Constants.
    """

    self.name = name
    self.value = value
    self.net_id = net_id
    for obj in _objects['constants']:
        if obj.name == name:
            _error('the constant', name, 'is already defined.')
    _objects['constants'].append(self)

set(value) #

Changes the value of the constant.

Source code in ANNarchy/core/Global.py
505
506
507
508
509
def set(self, value):
    "Changes the value of the constant."
    self.value = value
    if _network[self.net_id]['compiled']:
        getattr(_network[self.net_id]['instance'], '_set_'+self.name)(self.value)

Learning#

ANNarchy.enable_learning(projections=None, period=None, offset=None, net_id=0) #

Enables learning for all projections. Optionally period and offset can be changed for all projections.

Parameters:

  • projections

    the projections whose learning should be enabled. By default, all the existing projections are enabled.

  • period

    determines how often the synaptic variables will be updated.

  • offset

    determines the offset at which the synaptic variables will be updated relative to the current time.

Source code in ANNarchy/core/Global.py
572
573
574
575
576
577
578
579
580
581
582
583
584
def enable_learning(projections=None, period=None, offset=None, net_id=0):
    """
    Enables learning for all projections. Optionally *period* and *offset* can be changed for all projections.

    :param projections: the projections whose learning should be enabled. By default, all the existing projections are enabled.
    :param period: determines how often the synaptic variables will be updated.
    :param offset: determines the offset at which the synaptic variables will be updated relative to the current time.

    """
    if not projections:
        projections = _network[net_id]['projections']
    for proj in projections:
        proj.enable_learning(period, offset)

ANNarchy.disable_learning(projections=None, net_id=0) #

Disables learning for all projections.

Parameters:

  • projections

    the projections whose learning should be disabled. By default, all the existing projections are disabled.

Source code in ANNarchy/core/Global.py
586
587
588
589
590
591
592
593
594
595
def disable_learning(projections=None, net_id=0):
    """
    Disables learning for all projections.

    :param projections: the projections whose learning should be disabled. By default, all the existing projections are disabled.
    """
    if not projections:
        projections = _network[net_id]['projections']
    for proj in projections:
        proj.disable_learning()

Access to simulation times#

ANNarchy.get_time(net_id=0) #

Returns the current time in ms.

Source code in ANNarchy/core/Global.py
600
601
602
603
604
605
606
def get_time(net_id=0):
    "Returns the current time in ms."
    try:
        t = _network[net_id]['instance'].get_time()*config['dt']
    except:
        t = 0.0
    return t

ANNarchy.set_time(t, net_id=0) #

Sets the current time in ms.

Warning: can be dangerous for some spiking models.

Source code in ANNarchy/core/Global.py
608
609
610
611
612
613
614
615
616
617
def set_time(t, net_id=0):
    """
    Sets the current time in ms.

    **Warning:** can be dangerous for some spiking models.
    """
    try:
        _network[net_id]['instance'].set_time(int(t/config['dt']))
    except:
        _warning('Time can only be set when the network is compiled.')

ANNarchy.get_current_step(net_id=0) #

Returns the current simulation step.

Source code in ANNarchy/core/Global.py
619
620
621
622
623
624
625
def get_current_step(net_id=0):
    "Returns the current simulation step."
    try:
        t = _network[net_id]['instance'].get_time()
    except:
        t = 0
    return t

ANNarchy.set_current_step(t, net_id=0) #

Sets the current simulation step (integer).

Warning: can be dangerous for some spiking models.

Source code in ANNarchy/core/Global.py
627
628
629
630
631
632
633
634
635
636
def set_current_step(t, net_id=0):
    """
    Sets the current simulation step (integer).

    **Warning:** can be dangerous for some spiking models.
    """
    try:
        _network[net_id]['instance'].set_time(int(t))
    except:
        _warning('Time can only be set when the network is compiled.')

ANNarchy.dt() #

Returns the simulation step size dt used in the simulation.

Source code in ANNarchy/core/Global.py
638
639
640
def dt():
    "Returns the simulation step size `dt` used in the simulation."
    return config['dt']