{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Tutorial 2: Single cell simulation with external feedfoward input (with BioNet)\n",
    "\n",
    "In the previous tutorial we built a single cell and stimulated it with a current injection. In this example we will keep our single-cell network, but instead of stimulation by a step current, we'll set-up an external network that synapses onto our cell.\n",
    "\n",
    "**Note** - scripts and files for running this tutorial can be found in the directory [sources/chapter02/](https://github.com/AllenInstitute/bmtk/tree/develop/docs/tutorial/sources/chapter02)\n",
    "\n",
    "**Requirements:**\n",
    "* Python 2.7 or 3.6+\n",
    "* bmtk\n",
    "* NEURON 7.4+"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Step 1: Building the network.\n",
    "\n",
    "Similar to the previous tutorial, we want to build and save a network consisting of a single biophysically detailed cell. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "from bmtk.builder.networks import NetworkBuilder\n",
    "\n",
    "\n",
    "cortex = NetworkBuilder('mcortex')\n",
    "cortex.add_nodes(cell_name='Scnn1a_473845048',\n",
    "                 potental='exc',\n",
    "                 model_type='biophysical',\n",
    "                 model_template='ctdb:Biophys1.hoc',\n",
    "                 model_processing='aibs_perisomatic',\n",
    "                 dynamics_params='472363762_fit.json',\n",
    "                 morphology='Scnn1a_473845048_m.swc')\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "cortex.build()\n",
    "cortex.save_nodes(output_dir='sim_ch02/network')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "But we will also want a collection of external spike-generating cells that will synapse onto our cell. To do this we create a second network which can represent thalamic input. We will call our network \"mthalamus\", and it will consist of 10 cells. These cells are not biophysical but instead \"virtual\" cells. Virtual cells don't have a morphology or the normal properties of a neuron, but rather act as spike generators."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "thalamus = NetworkBuilder('mthalamus')\n",
    "thalamus.add_nodes(N=10,\n",
    "                   pop_name='tON',\n",
    "                   potential='exc',\n",
    "                   model_type='virtual')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now that we built our nodes, we want to create a connection between our 10 thalamic cells onto our cortex cell. To do so we use the add_edges function like so:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<bmtk.builder.connection_map.ConnectionMap at 0x7f71d3f59438>"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "thalamus.add_edges(source={'pop_name': 'tON'}, target=cortex.nodes(),\n",
    "                   connection_rule=5,\n",
    "                   syn_weight=0.001,\n",
    "                   delay=2.0,\n",
    "                   weight_function=None,\n",
    "                   target_sections=['basal', 'apical'],\n",
    "                   distance_range=[0.0, 150.0],\n",
    "                   dynamics_params='AMPA_ExcToExc.json',\n",
    "                   model_template='exp2syn')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let us break down how this method call works:\n",
    "```python\n",
    "thalamus.add_edges(source={'pop_name': 'tON'}, target=cortex.nodes(),\n",
    "```\n",
    "* Here we specify which set of nodes to use as sources and targets. Our source/pre-synaptic cells are all thamalus cells with the property \"pop_name=tON\", which in this case is every thalmus cell (We could also use source=thalamus.nodes(), or source={'level_of_detail': 'filter'}). The target/post-synaptic is all cell(s) of the \"cortex\" network.\n",
    "\n",
    "```python\n",
    "connection_rule=5,\n",
    "```\n",
    "* The connection_rule parameter determines how many synapses exists between every source/target pair. In this very trivial case we are indicating that between every thamalic --> cortical cell connection, there are 5 synapatic connections. In future tutorials we will show how we can create more complex customized rules.\n",
    "\n",
    "```python\n",
    "syn_weight=0.001,\n",
    "delay=2.0,\n",
    "weight_function=None,\n",
    "```\n",
    "* Here we are specifying the connection weight. For every connection in this edge-type, there is a connection strength of 5e-05 (units) and a connection delay of 2 ms. The weight function is used to adjust the weights before runtime. Later we will show how to create customized weight functions.\n",
    "\n",
    "```python\n",
    "   target_sections=['basal', 'apical'],\n",
    "   distance_range=[0.0, 150.0],\n",
    "```\n",
    "* This is used by BioNet to determine where on the post-synaptic cell to place the synapse. By default placement is random within the given section and range.\n",
    "```python\n",
    "dynamics_params='AMPA_ExcToExc.json',  \n",
    "model_template='exp2syn')\n",
    "```\n",
    "* The params_file give the parameters of the synpase, including the time constant and potential. Here we are using an AMPA type synaptic model with an Excitatory connection. The set_params_function is used by BioNet to convert the model into a valid NEURON synaptic object.\n",
    "\n",
    "Finally we are ready to build the model and save the thalamic nodes and edges."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "thalamus.build()\n",
    "thalamus.save_nodes(output_dir='sim_ch02/network')\n",
    "thalamus.save_edges(output_dir='sim_ch02/network')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The network/ directory will contain multiple nodes and edges files. It should have nodes (and node-types) files for both the thalamus and cortex network. And edges (and edge-types) files for the thalamus --> cortex connections. Nodes and edges for different networks and their connections are spread out across different files which allows us in the future to rebuild, edit or replace part of setup in a piecemeal and efficent manner."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Spike Trains\n",
    "\n",
    "We need to give our 10 thalamic cells spike trains. There are multiple ways to do this, but an easy way to use a sonata hdf5 file. The following function will create a file to provide the spikes for our 10 cells.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "from bmtk.utils.reports.spike_trains import PoissonSpikeGenerator\n",
    "\n",
    "psg = PoissonSpikeGenerator(population='mthalamus')\n",
    "psg.add(node_ids=range(10),  # Have 10 nodes to match mthalamus\n",
    "        firing_rate=10.0,    # 10 Hz, we can also pass in a nonhomoegenous function/array\n",
    "        times=(0.0, 3.0))    # Firing starts at 0 s up to 3 s\n",
    "psg.to_sonata('sim_ch02/inputs/mthalamus_spikes.h5')\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The spikes files are save as a [Sonata formated spikes train](https://github.com/AllenInstitute/sonata/blob/master/docs/SONATA_DEVELOPER_GUIDE.md#spike-file). BMTK also allow us to use csv files and NWB files to set the spike train - we just have to tell the configuration file the appropiate format to read."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Number of spikes: 294\n",
      "Units: ms\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>node_ids</th>\n",
       "      <th>timestamps</th>\n",
       "      <th>population</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>0</td>\n",
       "      <td>17.496766</td>\n",
       "      <td>mthalamus</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>0</td>\n",
       "      <td>125.003370</td>\n",
       "      <td>mthalamus</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>0</td>\n",
       "      <td>262.061478</td>\n",
       "      <td>mthalamus</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>0</td>\n",
       "      <td>321.393195</td>\n",
       "      <td>mthalamus</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>0</td>\n",
       "      <td>380.575289</td>\n",
       "      <td>mthalamus</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   node_ids  timestamps population\n",
       "0         0   17.496766  mthalamus\n",
       "1         0  125.003370  mthalamus\n",
       "2         0  262.061478  mthalamus\n",
       "3         0  321.393195  mthalamus\n",
       "4         0  380.575289  mthalamus"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "print('Number of spikes: {}'.format(psg.n_spikes()))\n",
    "print('Units: {}'.format(psg.units()))\n",
    "\n",
    "psg.to_dataframe().head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Step 2: Setting up BioNet environment.\n",
    "#### file structure.\n",
    "\n",
    "Before running a simulation, we will need to create the runtime environment, including parameter files, run-script and configuration files. If using the tutorial these files will already be in place, however you should run the following anyway in a command-line:\n",
    "\n",
    "```bash\n",
    "$ python -m bmtk.utils.sim_setup  \\\n",
    "   --report-vars v,cai            \\                             \n",
    "   --network sim_ch02/network     \\                              \n",
    "   --spikes-inputs mthalamus:sim_ch02/inputs/mthalamus_spikes.h5 \\\n",
    "   --dt 0.1             \\\n",
    "   --tstop 3000.0       \\  \n",
    "   --include-examples   \\\n",
    "   --compile-mechanisms \\ \n",
    "   bionet sim_ch02\n",
    "```\n",
    "\n",
    "Or call the function directly in python\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "from bmtk.utils.sim_setup import build_env_bionet\n",
    "\n",
    "build_env_bionet(base_dir='sim_ch02',      \n",
    "                 network_dir='sim_ch02/network',\n",
    "                 tstop=3000.0, dt=0.1,\n",
    "                 report_vars=['v', 'cai'],     # Record membrane potential and calcium (default soma)\n",
    "                 spikes_inputs=[('mthalamus',   # Name of population which spikes will be generated for\n",
    "                                'sim_ch02/inputs/mthalamus_spikes.h5')],\n",
    "                 include_examples=True,    # Copies components files\n",
    "                 compile_mechanisms=True   # Will try to compile NEURON mechanisms\n",
    "                )"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The last thing that we need to do is to update the configuration file to read \"thalamus_spikes.csv\". To do so we open simulation_config.json in a text editor and add the following to the **input** section.\n",
    "\n",
    "```json\n",
    "{\n",
    "  \"inputs\": {\n",
    "    \"mthalamus_spikes\": {\n",
    "      \"input_type\": \"spikes\",\n",
    "      \"module\": \"sonata\",\n",
    "      \"input_file\": \"${BASE_DIR}/input/mthalamus_spikes.csv\",\n",
    "      \"node_set\": \"mthalamus\"\n",
    "    }\n",
    "  }\n",
    "}\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3. Running the simulation\n",
    "\n",
    "Once our config file is setup we can run a simulation either through the command line:\n",
    "```bash\n",
    "$ python run_bionet.py simulation_config.json\n",
    "```\n",
    "\n",
    "or through the script"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2020-08-25 13:48:11,754 [INFO] Created log file\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:NEURONIOUtils:Created log file\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2020-08-25 13:48:11,850 [INFO] Building cells.\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:NEURONIOUtils:Building cells.\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2020-08-25 13:48:12,026 [INFO] Building recurrent connections\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:NEURONIOUtils:Building recurrent connections\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2020-08-25 13:48:12,028 [INFO] Building virtual cell stimulations for mthalamus_spikes\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:NEURONIOUtils:Building virtual cell stimulations for mthalamus_spikes\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2020-08-25 13:48:12,127 [INFO] Running simulation for 3000.000 ms with the time step 0.100 ms\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:NEURONIOUtils:Running simulation for 3000.000 ms with the time step 0.100 ms\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2020-08-25 13:48:12,128 [INFO] Starting timestep: 0 at t_sim: 0.000 ms\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:NEURONIOUtils:Starting timestep: 0 at t_sim: 0.000 ms\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2020-08-25 13:48:12,129 [INFO] Block save every 5000 steps\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:NEURONIOUtils:Block save every 5000 steps\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2020-08-25 13:48:12,526 [INFO]     step:5000 t_sim:500.00 ms\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:NEURONIOUtils:    step:5000 t_sim:500.00 ms\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2020-08-25 13:48:12,991 [INFO]     step:10000 t_sim:1000.00 ms\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:NEURONIOUtils:    step:10000 t_sim:1000.00 ms\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2020-08-25 13:48:13,520 [INFO]     step:15000 t_sim:1500.00 ms\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:NEURONIOUtils:    step:15000 t_sim:1500.00 ms\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2020-08-25 13:48:14,028 [INFO]     step:20000 t_sim:2000.00 ms\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:NEURONIOUtils:    step:20000 t_sim:2000.00 ms\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2020-08-25 13:48:14,403 [INFO]     step:25000 t_sim:2500.00 ms\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:NEURONIOUtils:    step:25000 t_sim:2500.00 ms\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2020-08-25 13:48:14,838 [INFO]     step:30000 t_sim:3000.00 ms\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:NEURONIOUtils:    step:30000 t_sim:3000.00 ms\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2020-08-25 13:48:14,851 [INFO] Simulation completed in 2.724 seconds \n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:NEURONIOUtils:Simulation completed in 2.724 seconds \n"
     ]
    }
   ],
   "source": [
    "from bmtk.simulator import bionet\n",
    "\n",
    "\n",
    "conf = bionet.Config.from_json('sim_ch02/simulation_config.json')\n",
    "conf.build_env()\n",
    "net = bionet.BioNetwork.from_config(conf)\n",
    "sim = bionet.BioSimulator.from_config(conf, network=net)\n",
    "sim.run()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 4. Analyzing the run"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Number of Spikes: 49\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/kael/Workspace/bmtk/bmtk/simulator/utils/config.py:4: UserWarning: Please use bmtk.simulator.core.simulation_config instead.\n",
      "  warnings.warn('Please use bmtk.simulator.core.simulation_config instead.')\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>timestamps</th>\n",
       "      <th>node_ids</th>\n",
       "      <th>population</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>15.1</td>\n",
       "      <td>0</td>\n",
       "      <td>mcortex</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>1441.6</td>\n",
       "      <td>0</td>\n",
       "      <td>mcortex</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>1457.0</td>\n",
       "      <td>0</td>\n",
       "      <td>mcortex</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>1483.0</td>\n",
       "      <td>0</td>\n",
       "      <td>mcortex</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>1523.2</td>\n",
       "      <td>0</td>\n",
       "      <td>mcortex</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   timestamps  node_ids population\n",
       "0        15.1         0    mcortex\n",
       "1      1441.6         0    mcortex\n",
       "2      1457.0         0    mcortex\n",
       "3      1483.0         0    mcortex\n",
       "4      1523.2         0    mcortex"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from bmtk.analyzer.spike_trains import to_dataframe\n",
    "\n",
    "results_df = to_dataframe(config_file='sim_ch02/simulation_config.json')\n",
    "print('Number of Spikes: {}'.format(len(results_df)))\n",
    "results_df.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 24552 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 20928 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "from bmtk.analyzer.compartment import plot_traces\n",
    "\n",
    "_ = plot_traces(config_file='sim_ch01/simulation_config.json', node_ids=[0], report_name='v_report')\n",
    "_ = plot_traces(config_file='sim_ch01/simulation_config.json', node_ids=[0], report_name='cai_report')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 5. Additional things to do:\n",
    "\n",
    "#### Changing edge properties\n",
    "\n",
    "When using the Network Builder add_edges method, we gave all the edges the same parameter values (delay, weight, target_section, etc.). All connection created by this method call constitute an single edge-type that share the same parameters, and are specified in the mthalamic_edge_type.csv file"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>edge_type_id</th>\n",
       "      <th>target_query</th>\n",
       "      <th>source_query</th>\n",
       "      <th>target_sections</th>\n",
       "      <th>weight_function</th>\n",
       "      <th>model_template</th>\n",
       "      <th>distance_range</th>\n",
       "      <th>delay</th>\n",
       "      <th>syn_weight</th>\n",
       "      <th>dynamics_params</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>100</td>\n",
       "      <td>*</td>\n",
       "      <td>pop_name=='tON'</td>\n",
       "      <td>['basal', 'apical']</td>\n",
       "      <td>NaN</td>\n",
       "      <td>exp2syn</td>\n",
       "      <td>[0.0, 150.0]</td>\n",
       "      <td>2.0</td>\n",
       "      <td>0.001</td>\n",
       "      <td>AMPA_ExcToExc.json</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   edge_type_id target_query     source_query      target_sections  \\\n",
       "0           100            *  pop_name=='tON'  ['basal', 'apical']   \n",
       "\n",
       "   weight_function model_template distance_range  delay  syn_weight  \\\n",
       "0              NaN        exp2syn   [0.0, 150.0]    2.0       0.001   \n",
       "\n",
       "      dynamics_params  \n",
       "0  AMPA_ExcToExc.json  "
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import pandas as pd\n",
    "pd.read_csv('sim_ch02/network/mthalamus_mcortex_edge_types.csv', sep=' ')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "(if in the build script we called add_edges multiple times, we'd have multiple edge-types). \n",
    "\n",
    "Using a simple text-editor we can modify this file directly, change parameters before a simulation run without having to rebuild the entire network (although for a network this small it may not be beneficial).\n",
    "\n",
    "#### weight_function\n",
    "\n",
    "By default BioNet uses the value in syn_weight to set a synaptic weight, which is a constant stored in the network files. Often we will want to adjust the synaptic weight between simulations, but don't want to have to regenerate the network. BioNet allows us to specify custom synaptic weight functions that will calculate synaptic weight before each simulation. \n",
    "\n",
    "To do so first we must set the value of 'weight_function' column. Either we can open up the file mthalamus_mcortex_edge_types.csv with a text-editor and change the column. \n",
    "\n",
    "\n",
    "|edge_type_id | target_query | source_query   | ... | weight_function |\n",
    "|-------------|--------------|----------------|-----|-----------------|\n",
    "|100          | *            |pop_name=='tON' | ... |*adjusted_weight*  |\n",
    "\n",
    "or we can rebuild the edges\n",
    "```python\n",
    "thalamus.add_edges(source={'pop_name': 'tON'}, target=cortex.nodes(),\n",
    "                   connection_rule=5,\n",
    "                   syn_weight=0.001,\n",
    "                   weight_function=adjusted_weight,\n",
    "                   delay=2.0,\n",
    "                   target_sections=['basal', 'apical'],\n",
    "                   distance_range=[0.0, 150.0],\n",
    "                   dynamics_params='AMPA_ExcToExc.json',\n",
    "                   model_template='exp2syn')\n",
    "```\n",
    "\n",
    "Then we write a custom weight function. The weight functions will be called during the simulation when building each synapse, and requires three parameters - target_cell, source_cell, and edge_props. These three parameters are dictionaries which can be used to access properties of the source node, target node, and edge, respectively. The function must return a floating point number which will be used to set the synaptic weight\n",
    "\n",
    "```python\n",
    "def adjusted_weights(target_cell, source_cell, edge_props):\n",
    "    if target_cell['cell_name'] == 'Scnn1a':\n",
    "        return edge_prop[\"weight_max\"]*0.5\n",
    "    elif target_cell['cell_name'] == 'Rorb'\n",
    "        return edge_prop[\"weight_max\"]*1.5\n",
    "    else:\n",
    "        ...\n",
    "```\n",
    "\n",
    "Finally we must tell BioNet where to access the function which we can do by using the add_weight_function.\n",
    "```python\n",
    "from bmtk.simulator import bionet\n",
    "\n",
    "bionet.nrn.add_weight_function(adjusted_weights)\n",
    "\n",
    "conf = bionet.Config.from_json('config.json')\n",
    "...\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Using NWB for spike trains\n",
    "\n",
    "Instead of using csv files to set the spike trains of our external network, we can also use nwb files. The typical setup would look like the following in the config file:\n",
    "\n",
    "```json\n",
    "{\n",
    "  \"inputs\": {\n",
    "    \"LGN_spikes\": {\n",
    "      \"input_type\": \"spikes\",\n",
    "      \"module\": \"nwb\",\n",
    "      \"input_file\": \"$INPUT_DIR/lgn_spikes.nwb\",\n",
    "      \"node_set\": \"lgn\",\n",
    "      \"trial\": \"trial_0\"\n",
    "    },\n",
    "  }\n",
    "}\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "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.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
