1# -*- coding: utf-8 -*-
2#
3# multimeter_file.py
4#
5# This file is part of NEST.
6#
7# Copyright (C) 2004 The NEST Initiative
8#
9# NEST is free software: you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation, either version 2 of the License, or
12# (at your option) any later version.
13#
14# NEST is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with NEST.  If not, see <http://www.gnu.org/licenses/>.
21
22"""
23Example of multimeter recording to file
24---------------------------------------
25
26This file demonstrates recording from an ``iaf_cond_alpha`` neuron using a
27multimeter and writing data to file.
28
29"""
30
31###############################################################################
32# First, we import the necessary modules to simulate and plot this example.
33# The simulation kernel is put back to its initial state using ``ResetKernel``.
34
35import nest
36import numpy
37import matplotlib.pyplot as plt
38
39nest.ResetKernel()
40
41###############################################################################
42# Global properties of the simulation kernel can be set via attributes
43# of the nest module. The following properties are related to writing to file:
44#
45# * ``overwrite_files`` can be set True to permit overwriting of existing files.
46# * ``data_path`` is the path to which all data is written. It is given relative
47#   to  the current working directory.
48# * ``data_prefix`` allows to specify a common prefix for all data files.
49
50nest.overwrite_files = True
51nest.data_path = ""
52nest.data_prefix = ""
53
54###############################################################################
55# For illustration, the recordables of the ``iaf_cond_alpha`` neuron model are
56# displayed. This model is an implementation of a spiking neuron using
57# integrate-and-fire dynamics with conductance-based synapses. Incoming spike
58# events induce a postsynaptic change of conductance modeled by an alpha
59# function.
60
61print("iaf_cond_alpha recordables: {0}".format(
62      nest.GetDefaults("iaf_cond_alpha")["recordables"]))
63
64###############################################################################
65# A neuron, a multimeter as recording device, and two spike generators for
66# excitatory and inhibitory stimulation are instantiated. The command ``Create``
67# expects a model type and, optionally, the desired number of nodes and a
68# dictionary of parameters to overwrite the default values of the model.
69#
70#  * For the neuron, the rise time of the excitatory synaptic alpha function
71#    (`tau_syn_ex`, in ms) and the reset potential of the membrane
72#    (`V_reset`, in mV) are specified.
73#  * For the ``multimeter``, the time interval for recording (`interval`, in
74#    ms) and the measures to record (membrane potential `V_m` in mV and
75#    excitatory and inhibitory synaptic conductances `g_ex` and`g_in` in nS)
76#    are set.
77#
78#  In addition, more parameters can be modified for writing to file:
79#
80#  - `record_to` indicates where to put recorded data. All possible values are
81#    available by inspecting the keys of the dictionary obtained from the
82#    kernel attribute ``recording_backends``.
83#  - `label` specifies an arbitrary label for the device. If writing to files,
84#    it used in the file name instead of the model name.
85#
86#  * For the spike generators, the spike times in ms (`spike_times`) are given
87#    explicitly.
88
89n = nest.Create("iaf_cond_alpha",
90                params={"tau_syn_ex": 1.0, "V_reset": -70.0})
91
92m = nest.Create("multimeter",
93                params={"interval": 0.1,
94                        "record_from": ["V_m", "g_ex", "g_in"],
95                        "record_to": "ascii",
96                        "label": "my_multimeter"})
97
98s_ex = nest.Create("spike_generator",
99                   params={"spike_times": numpy.array([10.0, 20.0, 50.0])})
100s_in = nest.Create("spike_generator",
101                   params={"spike_times": numpy.array([15.0, 25.0, 55.0])})
102
103###############################################################################
104# Next, we connect the spike generators to the neuron with ``Connect``. Synapse
105# specifications can be provided in a dictionary. In this example of a
106# conductance-based neuron, the synaptic weight ``weight`` is given in nS.
107# Note that the values are  positive for excitatory stimulation and negative
108# for inhibitor connections.
109
110nest.Connect(s_ex, n, syn_spec={"weight": 40.0})
111nest.Connect(s_in, n, syn_spec={"weight": -20.0})
112nest.Connect(m, n)
113
114###############################################################################
115# A network simulation with a duration of 100 ms is started with ``Simulate``.
116
117nest.Simulate(100.)
118
119###############################################################################
120# After the simulation, the recordings are obtained from the file the
121# multimeter wrote to, accessed with the `filenames` property of the
122# multimeter. After three header rows, the data is formatted in columns. The
123# first column is the ID of the sender node. The second column is the time
124# of the recording, in ms. Subsequent rows are values of properties specified
125# in the `record_from` property of the multimeter.
126
127data = numpy.loadtxt(m.filenames[0], skiprows=3)
128sender, t, v_m, g_ex, g_in = data.T
129
130###############################################################################
131# Finally, the time courses of the membrane voltage and the synaptic
132# conductance are displayed.
133
134plt.clf()
135
136plt.subplot(211)
137plt.plot(t, v_m)
138plt.axis([0, 100, -75, -53])
139plt.ylabel("membrane potential (mV)")
140
141plt.subplot(212)
142plt.plot(t, g_ex, t, g_in)
143plt.axis([0, 100, 0, 45])
144plt.xlabel("time (ms)")
145plt.ylabel("synaptic conductance (nS)")
146plt.legend(("g_exc", "g_inh"))
147plt.show()
148