====== sim_isp_orig ======
This simulation is the adapted from the network used to generate Figure 4 in [1]. It simulates a balanced network of 10,000 sparsely connected integrate-and-fire neurons[2] and features
plastic inhibitory-exciatory synapses.
{{:examples:isp_fig4.png?300|}}
[1] Vogels, T.P., Abbott, L.F., 2005. Signal propagation and logic gating in networks of integrate-and-fire neurons. J Neurosci 25, 10786.
[[http://www.ncbi.nlm.nih.gov/pubmed/16291952|PubMed]]
[2] Vogels, T.P., Sprekeler, H., Zenke, F., Clopath, C., Gerstner, W., 2011. Inhibitory Plasticity Balances Excitation and Inhibition in Sensory Pathways and Memory Networks. Science 334, 1569 –1573.
[[http://www.ncbi.nlm.nih.gov/pubmed/22075724|PubMed]]
===== Running the program =====
To run the program after [[manual:start#first steps|compilation]] it suffices to call it as follows
./sim_isp_orig
this will trigger a 1000s simulation which creates the following output files
4 -rw-r--r-- 1 zenke lcn1 954 Jan 20 10:52 out.0.log
5456 -rw-r--r-- 1 zenke lcn1 5555044 Jan 20 10:52 out.0_e.ras
1412 -rw-r--r-- 1 zenke lcn1 1433909 Jan 20 10:52 out.0_i.ras
936 -rw-r--r-- 1 zenke lcn1 951025 Jan 20 10:52 out.0.volt
888 -rw-r--r-- 1 zenke lcn1 901395 Jan 20 10:52 out.0.ampa
928 -rw-r--r-- 1 zenke lcn1 942420 Jan 20 10:52 out.0.gaba
To see inhibitory plasticity in action the network can be initialized with small inithal I-E inhibitory weights. Try running the network with the following parameter
./sim_isp_orig --winh 0.01
if you then plot the spiking activity recorded in ''out.0_e.ras'' after a couple of seconds it will look highly synchronous and pathologic as in the following
{{:examples:isp_orig_out1.png?300|}}
if you wait for roughly a minute this type of activity will give way to asynchronous irregular activity of the following type
{{:examples:isp_orig_out2.png?300|}}
==== Running in parallel ====
This version of the simulation can be run in parallel like any other Auryn simulation. See [[manual:parallel_execution|Running simulations in parallel]] for details.
===== The important bits =====
The following snipped of code first initializes two [[manual:NeuronGroup|NeuronGroups]] of type [[manual:TIFGroup]] and then initializes the neuronal membrane potentials to random values that follow a Gaussian distribution centered at -60mV with a standard deviation of 5mV. It furthermore creates an array of Poisson neurons called [[manual:PoissonGroup]], before moving on to set up the inhibitory and excitatory connections. Note that the connections from the inhibitory to the excitatory population is of type [[manual:SymmetricSTDPConnection]] which implements inhibitory synaptic plasticity as specified in Vogels et al. 2011.
logger->msg("Setting up neuron groups ...",PROGRESS,true);
TIFGroup * neurons_e = new TIFGroup(NE);
TIFGroup * neurons_i = new TIFGroup(NI);
neurons_e->random_mem(-60e-3,5e-3);
neurons_i->random_mem(-60e-3,5e-3);
PoissonGroup * poisson = new PoissonGroup(NP,poisson_rate);
logger->msg("Setting up connections ...",PROGRESS,true);
SparseConnection * con_ei = new SparseConnection(neurons_e,neurons_i,wei*w,sparseness,GLUT);
SparseConnection * con_ii = new SparseConnection(neurons_i,neurons_i,gamma*w,sparseness,GABA);
SparseConnection * con_exte = new SparseConnection(poisson,neurons_e,0,sparseness_afferents,GLUT);
SparseConnection * con_ee = new SparseConnection(neurons_e,neurons_e,w,sparseness,GLUT);
SymmetricSTDPConnection * con_ie = new SymmetricSTDPConnection(neurons_i,neurons_e,
gamma*w,sparseness,
gamma*eta,kappa,tau_stdp,wmax,
GABA);
Note also that in the above code the [[manual:PoissonGroup]] is connected with zero weights only. Certain of the these random sparse zero weights can be changed to non-zero values later in the simulation thus providing external input to the network. By default external input is given by external input currents and the [[manual:PoissonGroup]] is simply dragged along (it would indeed be more efficient to not define it at all in this case). The actual setting up of a stimulus happens here
// stimulus
if (!stimfile.empty()) {
char ch;
NeuronID counter = 0;
ifstream fin(stimfile.c_str());
while (!fin.eof() && counterset(i,counter,w_ext);
} else {
neurons_e->set_bg_current(counter,chi*bg_current);
}
}
counter++;
}
fin.close();
}
To run the network and keep activity alive even in the case of highly synchronized activity all cells in the network receive depolarizing external currents. This is set up here
for ( int j = 0; j < NE ; j++ ) {
neurons_e->set_bg_current(j,bg_current);
}
for ( int j = 0; j < NI ; j++ ) {
neurons_i->set_bg_current(j,bg_current);
}
note however that ''set_bg_current'' is not a generic function of [[manual:NeuronGroup]], but a pecularity of the neuron model implemented as [[manual:TIFGroup]]. To give currents to arbitrary [[manual:NeuronGroup|NeuronGroups]] a [[manual:CurrentInjector]] has to be used.
===== The full program =====
/*
* Copyright 2014 Friedemann Zenke
*
* This file is part of Auryn, a simulation package for plastic
* spiking neural networks.
*
* Auryn is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Auryn is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Auryn. If not, see .
*/
#include
#include
#include
#include
#include
#include "auryn_global.h"
#include "auryn_definitions.h"
#include "System.h"
#include "Logger.h"
#include "NeuronGroup.h"
#include "TIFGroup.h"
#include "PoissonGroup.h"
#include "SparseConnection.h"
#include "SymmetricSTDPConnection.h"
#include "StateMonitor.h"
#include "SpikeMonitor.h"
#include "RateChecker.h"
#define NE 8000
#define NI 2000
#define NP 1000
#define NSTIM 20
using namespace std;
namespace po = boost::program_options;
int main(int ac, char* av[])
{
double w = 0.3 ;
double w_ext = w ;
double gamma = 10. ;
double wmax = 10*gamma*w;
double sparseness = 0.02 ;
double eta = 1e-4 ;
double kappa = 3. ;
double tau_stdp = 20e-3 ;
bool stdp_active = true;
bool poisson_stim = false;
double winh = -1;
double wei = 1;
double chi = 10.;
double bg_current = 2e-2;
double poisson_rate = 100.;
double sparseness_afferents = 0.05;
bool quiet = false;
double simtime = 1000. ;
NeuronID record_neuron = 30;
// handle command line options
string infilename = "";
string outputfile = "out";
string stimfile = "";
string strbuf ;
int errcode = 0;
try {
po::options_description desc("Allowed options");
desc.add_options()
("help", "produce help message")
("quiet", "quiet mode")
("load", po::value(), "input weight matrix")
("out", po::value(), "output filename")
("stimfile", po::value(), "stimulus file")
("eta", po::value(), "learning rate")
("kappa", po::value(), "target rate")
("simtime", po::value(), "simulation time")
("active", po::value(), "toggle learning")
("poisson", po::value(), "toggle poisson stimulus")
("winh", po::value(), "inhibitory weight multiplier")
("wei", po::value(), "ei weight multiplier")
("chi", po::value(), "chi current multiplier")
;
po::variables_map vm;
po::store(po::parse_command_line(ac, av, desc), vm);
po::notify(vm);
if (vm.count("help")) {
cout << desc << "\n";
return 1;
}
if (vm.count("quiet")) {
quiet = true;
}
if (vm.count("load")) {
cout << "input weight matrix "
<< vm["load"].as() << ".\n";
infilename = vm["load"].as();
}
if (vm.count("out")) {
cout << "output filename "
<< vm["out"].as() << ".\n";
outputfile = vm["out"].as();
}
if (vm.count("stimfile")) {
cout << "stimfile filename "
<< vm["stimfile"].as() << ".\n";
stimfile = vm["stimfile"].as();
}
if (vm.count("eta")) {
cout << "eta set to "
<< vm["eta"].as() << ".\n";
eta = vm["eta"].as();
}
if (vm.count("kappa")) {
cout << "kappa set to "
<< vm["kappa"].as() << ".\n";
kappa = vm["kappa"].as();
}
if (vm.count("simtime")) {
cout << "simtime set to "
<< vm["simtime"].as() << ".\n";
simtime = vm["simtime"].as();
}
if (vm.count("active")) {
cout << "stdp active : "
<< vm["active"].as() << ".\n";
stdp_active = vm["active"].as();
}
if (vm.count("poisson")) {
cout << "poisson active : "
<< vm["poisson"].as() << ".\n";
poisson_stim = vm["poisson"].as();
}
if (vm.count("winh")) {
cout << "inhib weight multiplier : "
<< vm["winh"].as() << ".\n";
winh = vm["winh"].as();
}
if (vm.count("wei")) {
cout << "ei weight multiplier : "
<< vm["wei"].as() << ".\n";
wei = vm["wei"].as();
}
if (vm.count("chi")) {
cout << "chi multiplier : "
<< vm["chi"].as() << ".\n";
chi = vm["chi"].as();
}
}
catch(exception& e) {
cerr << "error: " << e.what() << "\n";
return 1;
}
catch(...) {
cerr << "Exception of unknown type!\n";
}
// BEGIN Global definitions
mpi::environment env(ac, av);
mpi::communicator world;
communicator = &world;
stringstream oss;
oss << outputfile << "." << world.rank();
outputfile = oss.str();
oss << ".log";
string logfile = oss.str();
logger = new Logger(logfile,world.rank());
sys = new System(&world);
// END Global definitions
logger->msg("Setting up neuron groups ...",PROGRESS,true);
TIFGroup * neurons_e = new TIFGroup(NE);
TIFGroup * neurons_i = new TIFGroup(NI);
neurons_e->random_mem(-60e-3,5e-3);
neurons_i->random_mem(-60e-3,5e-3);
PoissonGroup * poisson = new PoissonGroup(NP,poisson_rate);
logger->msg("Setting up connections ...",PROGRESS,true);
SparseConnection * con_ei = new SparseConnection(neurons_e,neurons_i,wei*w,sparseness,GLUT);
SparseConnection * con_ii = new SparseConnection(neurons_i,neurons_i,gamma*w,sparseness,GABA);
SparseConnection * con_exte = new SparseConnection(poisson,neurons_e,0,sparseness_afferents,GLUT);
SparseConnection * con_ee = new SparseConnection(neurons_e,neurons_e,w,sparseness,GLUT);
SymmetricSTDPConnection * con_ie = new SymmetricSTDPConnection(neurons_i,neurons_e,
gamma*w,sparseness,
gamma*eta,kappa,tau_stdp,wmax,
GABA);
if (!infilename.empty()) {
sys->load_network_state(infilename);
}
if (winh>=0)
con_ie->set_all(winh);
logger->msg("Setting up monitors ...",PROGRESS,true);
strbuf = outputfile;
strbuf += "_e.ras";
SpikeMonitor * smon_e = new SpikeMonitor( neurons_e , strbuf.c_str() );
strbuf = outputfile;
strbuf += "_i.ras";
SpikeMonitor * smon_i = new SpikeMonitor( neurons_i, strbuf.c_str() );
smon_i->set_offset(NE);
strbuf = outputfile;
strbuf += ".volt";
StateMonitor * vmon = new StateMonitor( neurons_e, record_neuron, "mem", strbuf.c_str() );
strbuf = outputfile;
strbuf += ".ampa";
StateMonitor * amon = new StateMonitor( neurons_e, record_neuron, "g_ampa", strbuf.c_str() );
strbuf = outputfile;
strbuf += ".gaba";
StateMonitor * gmon = new StateMonitor( neurons_e, record_neuron, "g_gaba", strbuf.c_str() );
RateChecker * chk = new RateChecker( neurons_e , 0.1 , 1000. , 100e-3);
for ( int j = 0; j < NE ; j++ ) {
neurons_e->set_bg_current(j,bg_current);
}
for ( int j = 0; j < NI ; j++ ) {
neurons_i->set_bg_current(j,bg_current);
}
// stimulus
if (!stimfile.empty()) {
char ch;
NeuronID counter = 0;
ifstream fin(stimfile.c_str());
while (!fin.eof() && counterset(i,counter,w_ext);
} else {
neurons_e->set_bg_current(counter,chi*bg_current);
}
}
counter++;
}
fin.close();
}
logger->msg("Simulating ...",PROGRESS,true);
con_ie->stdp_active = stdp_active;
sys->run(simtime);
logger->msg("Saving network state ...",PROGRESS,true);
sys->save_network_state(outputfile);
logger->msg("Freeing ...",PROGRESS,true);
delete sys;
logger->msg("Exiting ...",PROGRESS,true);
return errcode;
}