Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extended parrot_neuron to allow connections onto port 0 and 1, not repeating spikes on port 1 #118

Merged
merged 11 commits into from
Nov 3, 2015

Conversation

flinz
Copy link
Contributor

@flinz flinz commented Oct 3, 2015

This allows setting pre- and postsynaptic spike times for STDP protocols by connecting two parrot neurons onto port 1 postsynaptically by, e.g., a stdp_synapse. Thanks to @heplesser for your advice.

Here is a short test/demonstration

import nest
import pylab as pl
import numpy as np
nest.set_verbosity("M_WARNING")
nest.ResetKernel()

# set pre and postsynaptic spike times
dt = 50.
pre_times = np.arange(100, 1101, 200., float)
post_times = pre_times + dt

# create spike_generators with these times
pre_spikes = nest.Create("spike_generator", 1, {"spike_times": pre_times})
post_spikes = nest.Create("spike_generator", 1, {"spike_times": post_times})

# create parrot neurons and connect spike_generators
pre_parrot = nest.Create("parrot_neuron", 1)
post_parrot = nest.Create("parrot_neuron", 1)
nest.Connect(pre_spikes, pre_parrot)
nest.Connect(post_spikes, post_parrot)

# connect both parrot neurons with a stdp synapse onto port 1
# thereby spikes transmitted through the stdp connection are
# not repeated postsynaptically.
syn_spec = {
   "model": "stdp_synapse",
   "receptor_type": 1  # set receptor 1 postsynaptically, to not generate extra spikes
}
conn_spec = {
   "rule": "one_to_one",
}
nest.Connect(pre_parrot, post_parrot, syn_spec=syn_spec, conn_spec=conn_spec)

# simulate for ~1s and print connection weights every 100ms
nest.Simulate(75)
for _ in range(5):
   nest.Simulate(200)
   print nest.GetStatus(nest.GetConnections(source=pre_parrot))[0]['weight']

…s incoming on port 1 will not be repeated.

This allows setting pre- and postsynaptic spike times for STDP protocols by connecting two parrot neurons onto port 1 postsynaptically by, e.g., a stdp_synapse.
@@ -48,6 +48,10 @@ example a poisson generator with a high firing rate is connected
to a parrot neuron, the communication cost associated with outgoing
spikes is much bigger for the latter.

Only spikes incoming on connections to port 0 will be repeated.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

incoming -> arriving

@heplesser
Copy link
Contributor

@flinz : Nice work!

Could you turn the example script you included above into a proper test? The main point would be to test that the synaptic weight changes, and that only the spikes from the post_spikes generator are parroted by the post neuron, not those coming from the pre neuron. If you feel like writing the test in SLI, it should go into testsuite/unittests, otherwise into pynest/nest/testsuite. In that case you also have to add your test module to test_all.py in that directory.

@flinz
Copy link
Contributor Author

flinz commented Oct 9, 2015

@heplesser Ok, good idea. Will add the test shortly.

Tests for:
- correct repetition of spikes that arrive at port 0 (I could not find tests for this in the SLI nor the python testsuites)
- ignoring of spikes that arrive at port 1
- running a STDP protocol between parrot neurons to elicit weight_changes through exactly determined spike times
@flinz
Copy link
Contributor Author

flinz commented Oct 9, 2015

I wrote a python test for parrot_neuron, including also testing for the basic functionality of repeating spikes at correct times (I could not find any tests for parrot_neuron, both in the SLI and python tests).

* master:
  Local variabels now initiatlized on definition, const where applicable.
  Changes in variable definition and comment format
  Formatted nest_names.h with clang
  Changed Growth Curve creation scheme in order to have a GrowthCurveFactory to easily register new ones as needed. Also added minor changes in private variable naming.
  Formatted files using clang
  Added MSP names and group for MSP_functions
  Added corrections for formatting with clang and variable name oder
  Corrections after code review by heplesser and gewaltig
  Changes in documentation and style suggested by Alex after second Pull request
  Added test_msp module for automatic test run during installcheck
  First patch including functionality and tests for synaptic elements, growth curves and update in calcium concentration.
  All kernel level functionality for synaptic elements

Conflicts:
	pynest/nest/tests/test_all.py
@flinz flinz closed this Oct 10, 2015
@flinz flinz reopened this Oct 10, 2015
@flinz flinz closed this Oct 10, 2015
@flinz flinz reopened this Oct 10, 2015
@flinz flinz closed this Oct 12, 2015
@flinz flinz reopened this Oct 12, 2015
@flinz
Copy link
Contributor Author

flinz commented Oct 12, 2015

Just for your info, travis CI is having weird problems - to restart the build process I have/had to open/close the pull request.

@jougs
Copy link
Contributor

jougs commented Oct 12, 2015

@flinz: re-opening and closing unfortunately restarts all jobs, which brings a certain likelihood that one of them fails again. I can instead monitor the jobs and restart them individually if they fail.

@flinz
Copy link
Contributor Author

flinz commented Oct 12, 2015

@jougs: ah, sorry for the travis load then. I'll just not touch it anymore.

@tammoippen
Copy link
Contributor

Very nice work! 👍 from my side!


nest.Simulate(1000)

# check that the STDP protocol has elicited a weight change.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer that it checks that it is the correct weight change, to make sure the delays are properly accounted for etc.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, this is not totally clear to me.. could you be more precise which delays you are referring to?

As i see it, all I should need to check here, is that the parrot_neuron actually spikes at times that are as intended (which is generator_spiketimes+synaptic delays between the generators and the parrots).

Should the actual weight change, given some intended pre- and postsynaptic spiketimes of the parrots, not be part of the STDP model, and its tests?


Edit: One could implement a test like this, where I would replicate the exact functionality of the stdp_synapse, and compare to simulation results. But I think this misses the point of testing the parrot_neuron functionality. What do you think?

import nest
from math import exp

nest.set_verbosity("M_WARNING")
nest.ResetKernel()

# set pre and postsynaptic spike times
dt = 5.
delay = 1.  # delay for connections
dspike = 100.  # ISI

pre_times = [100., 100.+dspike]
post_times = [t + dt for t in pre_times]

# set the correct real spike times for generators (correcting for delay)
pre_times_gen = [k-delay for k in pre_times]
post_times_gen = [k+dt for k in pre_times_gen]

# create spike_generators with these times
pre_spikes = nest.Create("spike_generator", 1, {"spike_times": pre_times_gen})
post_spikes = nest.Create("spike_generator", 1, {"spike_times": post_times_gen})

# create parrot neurons and connect spike_generators
pre_parrot = nest.Create("parrot_neuron", 1)
post_parrot = nest.Create("parrot_neuron", 1)

nest.Connect(pre_spikes, pre_parrot, syn_spec={"delay": delay})
nest.Connect(post_spikes, post_parrot, syn_spec={"delay": delay})

# create spike detector
spikes = nest.Create("spike_detector")
nest.Connect(pre_parrot, spikes)
nest.Connect(post_parrot, spikes)

# connect both parrot neurons with a stdp synapse onto port 1
# thereby spikes transmitted through the stdp connection are
# not repeated postsynaptically.
syn_spec = {
   "model": "stdp_synapse",
   "receptor_type": 1,  # set receptor 1 postsynaptically, to not generate extra spikes
}
conn_spec = {
   "rule": "one_to_one",
}
nest.Connect(pre_parrot, post_parrot, syn_spec=syn_spec, conn_spec=conn_spec)

# get STDP synapse and initial weight
syn = nest.GetConnections(source=pre_parrot, synapse_model="stdp_synapse")
syn_status = nest.GetStatus(syn)[0]
initial_weight = syn_status['weight']

nest.Simulate(1000)

# check that postsynaptic spikes are only and exactly those received
# by the spike_generator.
gid_pre_parrot = nest.GetStatus(pre_parrot)[0]["global_id"]
gid_post_parrot = nest.GetStatus(post_parrot)[0]["global_id"]
events = nest.GetStatus(spikes)[0]["events"]
pre_spiketimes = events['times'][events['senders'] == gid_pre_parrot]
post_spiketimes = events['times'][events['senders'] == gid_post_parrot]

assert (
    len(post_spiketimes) == len(post_times_gen) and all(post_spiketimes - post_times_gen == delay)
), "Parrot neuron failed to ignore transmitted spikes"

# check that the STDP protocol has elicited the correct weight change.
parrot_status = nest.GetStatus(post_parrot)[0]

# calculate expected weight changes to compare with protocol
syn_status = nest.GetStatus(syn)[0]
final_weight = syn_status['weight']
tau_plus = syn_status["tau_plus"]
tau_minus = parrot_status["tau_minus"]
delay_dendr = syn_status['delay']
Wmax = syn_status["Wmax"]
mu_minus = syn_status["mu_minus"]
mu_plus = syn_status["mu_plus"]
alpha = syn_status["alpha"]
lamb = syn_status["lambda"]

# Kplus gets updated every presynaptic spike
e_dendr = exp(-delay_dendr/tau_plus)
e_dt = exp(-dt/tau_plus)
e_isi = exp(-dspike/tau_plus)
kplus_tpost = [e_dt*e_dendr, e_dt*e_dendr*(1. + e_isi)]

# Kminus gets updated every postsynaptic spike
e_dendr = exp(-delay_dendr/tau_minus)
e_dt = exp(-dt/tau_minus)
e_isi = exp(-dspike/tau_minus)
kminus_tpre = [0., e_isi/e_dt/e_dendr]

def facilitate(w, kplus):
    """stdp_synapse::facilitate_"""
    norm_w = w/Wmax + (lamb * (1. - w/Wmax)**mu_plus * kplus)
    return min(norm_w, 1.) * Wmax

def depress(w, kminus):
    """stdp_synapse::depress_"""
    norm_w = w/Wmax - (alpha * lamb * (w/Wmax)**mu_minus * kminus)
    return max(norm_w, 0.) * Wmax

# iteratively update w the same way it is done in the STDP synapse
w = initial_weight
w = depress(w, kminus_tpre[0])  # first pre spike
w = facilitate(w, kplus_tpost[0])  # first post spike
w = depress(w, kminus_tpre[1])  # 2nd pre spike

# in the STDP synapse, due to presynaptic-event based updates,
# this second facilitation step never gets evaluated.

# w = facilitate(w, kplus_tpost[1])  # 2nd post spike

assert abs(w-final_weight) < 1e-10, "Parrot neuron STDP protocol failed to elicit weight changes"

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@flinz I think this is exactly what @abigailm was asking for: an explicit check that the correct weight change occurs. This is the same thing done as in testsuite/unittest/test_stdp_synapse.sli.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@flinz makes a good point about the proper place for testing the stdp_synapse being in the test for that synapse (which already exists). Adding this test would indeed be redundant. I think it would be sufficiently reassuring to check that the change of weight is in the expected direction.

@abigailm
Copy link
Contributor

happy to merge once my comment has been addressed

@flinz
Copy link
Contributor Author

flinz commented Oct 19, 2015

@jougs this commit gave me some interesting travis fails. pynestkernel.so throws some errors, which I didn't change. Might be caused by building/checking against python built without some unicode flag.

@lekshmideepu
Copy link
Contributor

There is an issue with Python 2.6.9 on Travis worker systems after releasing the new Trusty beta image. I'm working on this problem.

@lekshmideepu
Copy link
Contributor

travis-ci/travis-ci#4948

"""Check parrot_neuron spike repetition properties"""

def setUp(self):
nest.set_verbosity(100)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would not recommend shutting the kernel up so brutally. A bit of output makes it easier to find out what went wrong when a test fails. nest.set_verbosity('M_WARNING') should do fine.

"""Check parrot_neuron ignores spikes on port 1"""

# connect with arbitrary delay to port 1
nest.Connect(self.source, self.parrot, syn_spec={"receptor_type": 1})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would explicitly specify a delay here as well, just to make it definite that the spike would arrive within the simulated time. Now, you rely on the default delay being 1 ms, but that could in principle change.

@heplesser
Copy link
Contributor

@flinz I added some minor comments to the code. We had some problems with Travis lately which are now fixed. To apply that fix to your PR, please pull the recent changes from master into your PR. This will automatically trigger Travis. Once you have updated your test as you suggest above, your PR should be ready for merging.

* master:
  Apply @lekshmideepu suggestions
  Filter out empty entries in changed files
  some cleanup
  Modify travis.yml
  Implemented two fixes for the K computer:
  Print status about uploading to S3
  Remove cppcheck files after static analysis.
  Adjust comment and have starting and ending line at summary
  Correct copyright header.
  Add a script to parse travis log and give a nice summary.
  Removed superfluous and outdated files
* master:
  Import GetStatus/SetStatus from the info component, where they were moved in a3ec4d4.
  Fix the stop condition of process_static_analysis.
  Added explanation for recursive import code.
  Moved Get/SetStatus from node to info component of HL API.
  Added information on steps to execute after creating the release tarball.
  Validate parameter values in setters of tsodyks synapses
  Added empty __init__.py to make the lib directory a module.
  Split Python high-level API into multiple files and made loading of the submodules dynamic
  Tsodyks synapse model with common properties
flinz added a commit to flinz/nest-simulator that referenced this pull request Nov 3, 2015
* parrot-multiport:
  Added tests for STDP protocols between parrot neurons to potentiate and depress connection; Accounted for delays in simulation times; Addresses https://github.com/nest/nest-simulator/pull/118/files#r43736299 and https://github.com/nest/nest-simulator/pull/118/files#r43702948; Fixes https://github.com/nest/nest-simulator/pull/118/files#r43702538 and nest#118 (comment);
  Import GetStatus/SetStatus from the info component, where they were moved in a3ec4d4.
  Fix the stop condition of process_static_analysis.
  Added explanation for recursive import code.
  Moved Get/SetStatus from node to info component of HL API.
  Added information on steps to execute after creating the release tarball.
  Validate parameter values in setters of tsodyks synapses
  Added empty __init__.py to make the lib directory a module.
  Split Python high-level API into multiple files and made loading of the submodules dynamic
  Tsodyks synapse model with common properties
@flinz
Copy link
Contributor Author

flinz commented Nov 3, 2015

@heplesser thanks for the helpful feedback and comments on the code.

As @abigailm pointed out here I chose to not include a reproduction of the full stdp_synapse model here, and instead test for causality in the weight change, i.e. pre-post -> potentiation, post-pre -> depression.

PR is updated with your suggested improvements and this newer version of the test.

nest.Connect(self.source, self.spikes)
nest.Connect(self.parrot, self.spikes)

self.gid_source = self.source[0]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this needed? I don't see where.

@abigailm
Copy link
Contributor

abigailm commented Nov 3, 2015

I like the new version. I think the assignation of gid_source is unnecessary but I might have overlooked something. 👍 when it is removed or I see the line where it is used.

@flinz
Copy link
Contributor Author

flinz commented Nov 3, 2015

@abigailm you are right about the unused self.gid_source. also, i removed the explicit self.gid_parrot variable and just call self.parrot[0] now, it's a little cleaner.

@abigailm
Copy link
Contributor

abigailm commented Nov 3, 2015

merging.

abigailm added a commit that referenced this pull request Nov 3, 2015
Extended parrot_neuron to allow connections onto port 0 and 1, not repeating spikes on port 1
@abigailm abigailm merged commit ce63c55 into nest:master Nov 3, 2015
@jougs
Copy link
Contributor

jougs commented Nov 3, 2015

Many thanks for your contribution!

flinz added a commit to flinz/nest-simulator that referenced this pull request Nov 3, 2015
commit b840820
Merge: 4668ea2 ce63c55
Author: Alex Seeholzer <seeholzer@gmail.com>
Date:   Tue Nov 3 15:53:36 2015 +0100

    Merge branch 'master' into issue-parrot_neuron-multiplicity

    * master:

commit 4668ea2
Author: Alex Seeholzer <seeholzer@gmail.com>
Date:   Tue Nov 3 15:29:13 2015 +0100

    Updated tests to conform to changes in parrot-multipart branch;

commit 1b8ddac
Merge: bce4bf9 9c4c2f3
Author: Alex Seeholzer <seeholzer@gmail.com>
Date:   Tue Nov 3 15:27:01 2015 +0100

    Merge branch 'parrot-multiport' into issue-parrot_neuron-multiplicity

    * parrot-multiport:
      removed unnecessary variables gid_source and gid_parrot;

commit bce4bf9
Merge: ef31ab0 3d8da20
Author: Alex Seeholzer <seeholzer@gmail.com>
Date:   Tue Nov 3 13:20:45 2015 +0100

    Merge branch 'parrot-multiport' into issue-parrot_neuron-multiplicity

    * parrot-multiport:
      Added tests for STDP protocols between parrot neurons to potentiate and depress connection; Accounted for delays in simulation times; Addresses https://github.com/nest/nest-simulator/pull/118/files#r43736299 and https://github.com/nest/nest-simulator/pull/118/files#r43702948; Fixes https://github.com/nest/nest-simulator/pull/118/files#r43702538 and nest#118 (comment);
      Import GetStatus/SetStatus from the info component, where they were moved in a3ec4d4.
      Fix the stop condition of process_static_analysis.
      Added explanation for recursive import code.
      Moved Get/SetStatus from node to info component of HL API.
      Added information on steps to execute after creating the release tarball.
      Validate parameter values in setters of tsodyks synapses
      Added empty __init__.py to make the lib directory a module.
      Split Python high-level API into multiple files and made loading of the submodules dynamic
      Tsodyks synapse model with common properties

commit ef31ab0
Merge: ca70656 9425619
Author: Alex Seeholzer <seeholzer@gmail.com>
Date:   Tue Nov 3 10:19:25 2015 +0100

    Merge branch 'parrot-multiport' into issue-parrot_neuron-multiplicity

    * parrot-multiport:

commit ca70656
Merge: 48a9feb c80a8be
Author: Alex Seeholzer <seeholzer@gmail.com>
Date:   Tue Nov 3 10:18:11 2015 +0100

    Merge branch 'master' into issue-parrot_neuron-multiplicity

    * master:
      Apply @lekshmideepu suggestions
      Filter out empty entries in changed files
      some cleanup
      Modify travis.yml
      Implemented two fixes for the K computer:
      Print status about uploading to S3
      Remove cppcheck files after static analysis.
      Adjust comment and have starting and ending line at summary
      Correct copyright header.
      Add a script to parse travis log and give a nice summary.
      Removed superfluous and outdated files

commit 48a9feb
Merge: 0b96cd1 4d939e5
Author: Alex Seeholzer <seeholzer@gmail.com>
Date:   Mon Oct 19 10:14:01 2015 +0200

    Merge branch 'parrot-multiport' into issue-parrot_neuron-multiplicity

    * parrot-multiport:
      Added superclass (archiving_node) get_status to parrot_neuron;

commit 0b96cd1
Author: Alex Seeholzer <seeholzer@gmail.com>
Date:   Fri Oct 16 16:08:11 2015 +0200

    added test for parrot neuron multiplicity.

commit ff0cb6d
Author: Alex Seeholzer <seeholzer@gmail.com>
Date:   Fri Oct 16 15:39:45 2015 +0200

    Changed parrot neuron to emit multiple spikes via spike multiplicity instead of a loop; Addresses nest#82
@flinz flinz deleted the parrot-multiport branch November 6, 2015 11:57
hakonsbm pushed a commit to hakonsbm/nest-simulator that referenced this pull request Jul 17, 2018
Add docstrings to c++ test cases
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants