{
  "cells": [
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "%matplotlib inline"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\n# Clopath Rule: Spike pairing experiment\n\nThis script simulates one ``aeif_psc_delta_clopath`` neuron that is connected with\na Clopath connection [1]_. The synapse receives pairs of a pre- and a postsynaptic\nspikes that are separated by either 10 ms (pre before post) or -10 ms (post\nbefore pre). The change of the synaptic weight is measured after five of such\npairs. This experiment is repeated five times with different rates of the\nsequence of the spike pairs: 10Hz, 20Hz, 30Hz, 40Hz, and 50Hz.\n\n## References\n\n.. [1] Clopath C, B\u00fcsing L, Vasilaki E, Gerstner W (2010). Connectivity reflects coding:\n       a model of voltage-based STDP with homeostasis.\n       Nature Neuroscience 13:3, 344--352\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "import numpy as np\nimport matplotlib.pyplot as plt\nimport nest"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "First we specify the neuron parameters. To enable voltage dependent\nprefactor ``A_LTD(u_bar_bar)`` add ``A_LTD_const: False`` to the dictionary.\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "nrn_params = {'V_m': -70.6,\n              'E_L': -70.6,\n              'C_m': 281.0,\n              'theta_minus': -70.6,\n              'theta_plus': -45.3,\n              'A_LTD': 14.0e-5,\n              'A_LTP': 8.0e-5,\n              'tau_minus': 10.0,\n              'tau_plus': 7.0,\n              'delay_u_bars': 4.0,\n              'a': 4.0,\n              'b': 0.0805,\n              'V_reset': -70.6 + 21.0,\n              'V_clamp': 33.0,\n              't_clamp': 2.0,\n              't_ref': 0.0,\n              }"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Hardcoded spike times of presynaptic spike generator\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "spike_times_pre = [\n    # Presynaptic spike before the postsynaptic\n    [20.,  120.,  220.,  320.,  420.],\n    [20.,   70.,  120.,  170.,  220.],\n    [20.,   53.3,   86.7,  120.,  153.3],\n    [20.,   45.,   70.,   95.,  120.],\n    [20.,   40.,   60.,   80.,  100.],\n    # Presynaptic spike after the postsynaptic\n    [120.,  220.,  320.,  420.,  520.,  620.],\n    [70.,  120.,  170.,  220.,  270.,  320.],\n    [53.3,   86.6,  120.,  153.3,  186.6,  220.],\n    [45.,   70.,   95.,  120.,  145.,  170.],\n    [40.,   60.,   80.,  100.,  120.,  140.]]"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Hardcoded spike times of postsynaptic spike generator\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "spike_times_post = [\n    [10.,  110.,  210.,  310.,  410.],\n    [10.,   60.,  110.,  160.,  210.],\n    [10.,   43.3,   76.7,  110.,  143.3],\n    [10.,   35.,   60.,   85.,  110.],\n    [10.,  30.,  50.,  70.,  90.],\n    [130.,  230.,  330.,  430.,  530.,  630.],\n    [80.,  130.,  180.,  230.,  280.,  330.],\n    [63.3,   96.6,  130.,  163.3,  196.6,  230.],\n    [55.,   80.,  105.,  130.,  155.,  180.],\n    [50.,   70.,   90.,  110.,  130.,  150.]]\ninit_w = 0.5\nsyn_weights = []\nresolution = 0.1"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Loop over pairs of spike trains\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "for (s_t_pre, s_t_post) in zip(spike_times_pre, spike_times_post):\n    nest.ResetKernel()\n    nest.SetKernelStatus({\"resolution\": resolution})\n\n    # Create one neuron\n    nrn = nest.Create(\"aeif_psc_delta_clopath\", 1, nrn_params)\n\n    # We need a parrot neuron since spike generators can only\n    # be connected with static connections\n    prrt_nrn = nest.Create(\"parrot_neuron\", 1)\n\n    # Create and connect spike generators\n    spike_gen_pre = nest.Create(\"spike_generator\", 1, {\n                                \"spike_times\": s_t_pre})\n\n    nest.Connect(spike_gen_pre, prrt_nrn,\n                 syn_spec={\"delay\": resolution})\n\n    spike_gen_post = nest.Create(\"spike_generator\", 1, {\n                                 \"spike_times\": s_t_post})\n\n    nest.Connect(spike_gen_post, nrn, syn_spec={\n                 \"delay\": resolution, \"weight\": 80.0})\n\n    # Create weight recorder\n    wr = nest.Create('weight_recorder', 1)\n\n    # Create Clopath connection with weight recorder\n    nest.CopyModel(\"clopath_synapse\", \"clopath_synapse_rec\",\n                   {\"weight_recorder\": wr})\n    syn_dict = {\"synapse_model\": \"clopath_synapse_rec\",\n                \"weight\": init_w, \"delay\": resolution}\n    nest.Connect(prrt_nrn, nrn, syn_spec=syn_dict)\n\n    # Simulation\n    simulation_time = (10.0 + max(s_t_pre[-1], s_t_post[-1]))\n    nest.Simulate(simulation_time)\n\n    # Extract and save synaptic weights\n    weights = wr.get(\"events\", \"weights\")\n    syn_weights.append(weights[-1])\n\nsyn_weights = np.array(syn_weights)\n# scaling of the weights so that they are comparable to [1]\nsyn_weights = 100.0*15.0*(syn_weights - init_w)/init_w + 100.0\n\n# Plot results\nfig1, axA = plt.subplots(1, sharex=False)\naxA.plot([10., 20., 30., 40., 50.], syn_weights[5:], color='b', lw=2.5, ls='-',\n         label=\"pre-post pairing\")\naxA.plot([10., 20., 30., 40., 50.], syn_weights[:5], color='g', lw=2.5, ls='-',\n         label=\"post-pre pairing\")\naxA.set_ylabel(\"normalized weight change\")\naxA.set_xlabel(\"rho (Hz)\")\naxA.legend()\naxA.set_title(\"synaptic weight\")\n\nplt.show()"
      ]
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.6.12"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}