{ "cells": [ { "cell_type": "markdown", "id": "b0477c1f-ba3f-48bf-9510-c95a59f49da4", "metadata": {}, "source": [ "# Advanced Methods for Driving your Network with Synaptic Spike-trains" ] }, { "cell_type": "markdown", "id": "cacc6a76-0928-42dd-9257-009a3a628810", "metadata": {}, "source": [ "BMTK is designed to build and simulate large-scale, realistic models of the nervous system. Most of these realistic simulations require the ability to recreate the kinds of synaptic input you would expect to see in vivo. To achieve this, modelers need to be able to generate the relevant spike trains that drive the synaptic stimuli of our simulations.\n", "\n", "We have other tutorials demonstrating how to generate realistic stimuli using [FilterNet](https://alleninstitute.github.io/bmtk/tutorials/tutorial_07_filter_models.html). We have also shown how to use the [BMTK SpikeTrain and PoissonSpikeTrain classes](https://alleninstitute.github.io/bmtk/tutorials/tutorial_03_single_pop.html#Spike-Trains) to generate input spike trains. In these cases, users must generate SONATA spike-train files before running their simulations. However, BMTK has additional methods for users to generate and import spike-train stimuli into their simulations. It includes using other formats besides SONATA, importing experimental data, and more fine-grained control of how and where cells within a network receive synaptic stimuli.\n", "\n", "We will cover some of such methods in this tutorial.\n", "\n", "**Note** - scripts and files for running this tutorial can be found in the directory [03_opt_advanced_spiking_inputs/](https://github.com/AllenInstitute/bmtk/tree/develop/docs/tutorial/03_opt_advanced_spiking_inputs)" ] }, { "cell_type": "markdown", "id": "7e7cd5bb-39cb-4a78-99f1-0db8e4b15d19", "metadata": {}, "source": [ "## 1. Example: Using spikes from CSV " ] }, { "cell_type": "markdown", "id": "ee0fbbe4-28eb-466d-9173-05072374f05e", "metadata": {}, "source": [ "In [Tutorial 2](https://alleninstitute.github.io/bmtk/tutorials/tutorial_02_single_cell_syn.html), we demonstrated how to generate network spikes using the BMTK's built-in PoissonSpikeGenerator class, which will produce a series of spike trains using the distribution parameters/functions we give it and save it to a SONATA spikes file using to `to_sonata` method. But BMTK also allows input spikes to be saved and loaded using a simpler space-separated CSV file, which, in many cases, can be easier to analyze and use with other programs.\n", "\n", "For example, in the **network_simple_spikes/** folder (built using `build_network.simple_spikes.py`), we have a set of 10 virtual nodes that synaptically drive our simulation. If we want each one to fire at a constant 10Hz firing rate over a 5-second interval, we can use PoissonSpikeGenerator's `to_csv()` class to save the spikes as a CSV file." ] }, { "cell_type": "code", "execution_count": 1, "id": "cdaa014a-4da1-47ae-aa2c-1a71f4e7ed88", "metadata": {}, "outputs": [], "source": [ "from bmtk.utils.reports.spike_trains import PoissonSpikeGenerator\n", "\n", "psg = PoissonSpikeGenerator()\n", "psg.add(\n", " node_ids='network_csv_spikes/inputs_nodes.h5', \n", " firing_rate=10.0, \n", " times=(0.0, 5.0),\n", " population='inputs'\n", ")\n", "psg.to_csv('inputs/simple_spikes.csv')" ] }, { "cell_type": "markdown", "id": "ff9a62f1-46e3-406b-87a3-0cdd6f02f72a", "metadata": {}, "source": [ "Now, we can use any text editor or CSV reader (like pandas) to read in our spikes for verification and analysis." ] }, { "cell_type": "code", "execution_count": 2, "id": "a85348f1-2095-43aa-a986-2988b2968433", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Number of cells in spikes-file: 10 (expected: 5)\n", "Avg. number of spikes per cell: 50.1 (expected: 5sec x 10Hz ~ 50)\n", "Min spike-time: 17.593944539645307 ms\n", "Max spike-time: 4998.560456807771 ms\n" ] }, { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
timestampspopulationnode_ids
040.425085inputs0
1326.168408inputs0
2434.783000inputs0
3821.277923inputs0
4847.735538inputs0
\n", "
" ], "text/plain": [ " timestamps population node_ids\n", "0 40.425085 inputs 0\n", "1 326.168408 inputs 0\n", "2 434.783000 inputs 0\n", "3 821.277923 inputs 0\n", "4 847.735538 inputs 0" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import pandas as pd\n", "\n", "spikes_inputs = pd.read_csv('inputs/simple_spikes.csv', sep=' ')\n", "\n", "# Let's quickly check that our csv file makes sense\n", "n_nodes = spikes_inputs['node_ids'].unique().shape[0]\n", "n_spikes = spikes_inputs.shape[0]\n", "\n", "print(f'Number of cells in spikes-file: {n_nodes} (expected: 5)')\n", "print(f'Avg. number of spikes per cell: {n_spikes/n_nodes} (expected: 5sec x 10Hz ~ 50)')\n", "print(f'Min spike-time: {spikes_inputs[\"timestamps\"].min()} ms')\n", "print(f'Max spike-time: {spikes_inputs[\"timestamps\"].max()} ms')\n", "\n", "spikes_inputs.head()" ] }, { "cell_type": "markdown", "id": "27aca5aa-2136-4651-bbed-66981c132591", "metadata": {}, "source": [ "Then, when running the simulation, we can do so as we previously did with SONATA spike files, but the difference is that the **module** type for the given input must be changed from `sonata` to `csv`:\n", "\n", "```json\n", " \"inputs\": {\n", " \"csv_spikes\": {\n", " \"input_type\": \"spikes\",\n", " \"module\": \"csv\",\n", " \"input_file\": \"./inputs/simple_spikes.csv\",\n", " \"node_set\": \"inputs\"\n", " }\n", " }," ] }, { "cell_type": "markdown", "id": "c1efd9ab-888c-4b52-8caf-38f4744d2ba5", "metadata": {}, "source": [ "### Creating your own csv file" ] }, { "cell_type": "markdown", "id": "655dbe88-d071-48cc-a691-2802ef66a809", "metadata": {}, "source": [ "You can create your own spike-train CSV file if you don't want to use the `PoissonSpikeGenerator` class. As we can see from above, it needs to be a space-separated text file with columns **timestamps**, **population**, and **node_ids** (order doesn't matter). Each row indicates a separate spike, with the **population** + **node_ids** columns indicating the node/cell that fired and **timestamps** (in milliseconds) indicating when it fired.\n", "\n", "For example, we can use the Python CSV writer class to create an example input file where each cell has an increasing firing rate." ] }, { "cell_type": "code", "execution_count": 3, "id": "e3b0e902-dd4c-4468-ac43-a97bf372d08f", "metadata": {}, "outputs": [], "source": [ "import csv\n", "import numpy as np\n", "\n", "with open('inputs/custom_spikes.csv', 'w') as csvfile:\n", " csvwriter = csv.writer(csvfile, delimiter=' ', quotechar='#')\n", "\n", " # write the header\n", " csvwriter.writerow(['timestamps', 'population', 'node_ids'])\n", " \n", " # For node 0 we have it fire randomly at 1 Hz for 5 seconds, for node 1 at 2Hz, etc.\n", " for node_id in range(10):\n", " for timestamp in np.sort(np.random.uniform(0.0, 5000.0, size=(node_id+1)*5)):\n", " csvwriter.writerow([timestamp, 'inputs', node_id])" ] }, { "cell_type": "code", "execution_count": 4, "id": "019f03cf-18dc-4e88-985f-275c6ce4cb3b", "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjMAAAHHCAYAAABKudlQAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy80BEi2AAAACXBIWXMAAA9hAAAPYQGoP6dpAABAPUlEQVR4nO3deXxTVf7/8XcoNLRAF6CUIoWyCwUpgiKyC4KAOKjzc0dAUVEUC7hQRywM86UiLigqCs4AI6OMo6KOIzigLKJYsFAWdQDHgh0ti0JTdqQ9vz/6aGy6JmnS5JbX8/HII+Tec8/5nHNuej/c3JvYjDFGAAAAFlUr0AEAAABUBckMAACwNJIZAABgaSQzAADA0khmAACApZHMAAAASyOZAQAAlkYyAwAALI1kBgAAWBrJDBBkEhISNHbs2Gpt02azacaMGdXaZk2QkJCgq6++2id17du3TzabTUuWLPFJfcD5hGQGqMCSJUtks9lUt25d/fjjj6XWDxgwQJ07dw5AZOef2bNn67333gt0GD4zYMCAak9aPXHy5EnNmDFD69at82r7YO8fapbagQ4AsIIzZ87oySef1Pz58wMdil+cOnVKtWsH95+D2bNn6/e//71GjRoV6FD8omXLljp16pTq1KkT6FAkFSYzM2fOlFSYmADBjDMzgBuSkpK0aNEi/fTTT4EOxS/q1q0b9MlMMDl58qTP6yw6AxgSEuLzuoGajmQGcMNjjz2m/Px8Pfnkk5WWPXfunGbNmqU2bdrIbrcrISFBjz32mM6cOeNSzhijP/3pT2revLnCw8M1cOBAff3112XWmZubq+TkZMXHx8tut6tt27aaM2eOCgoKXMotX75c3bt3V4MGDRQREaEuXbro+eefrzTmktfMzJgxQzabTd99953Gjh2rqKgoRUZGaty4cW4dyIs+fvvmm280cOBAhYeH64ILLtBTTz1VquyZM2eUmpqqtm3bym63Kz4+Xo888ojLeNlsNp04cUJLly6VzWaTzWbT2LFjtWPHDtlsNn3wwQfOshkZGbLZbLr44otd2hk2bJh69uzpsuzll19WYmKi7Ha7mjVrpokTJyo3N7fMvmRkZKhfv34KDw/XY489Vm7fly5dqtq1a+vhhx+udJyKK+uambFjx6p+/fr68ccfNWrUKNWvX18xMTF66KGHlJ+fX2rbp59+Ws8995xatmypsLAw9e/fX7t27SrVn7LOtIwdO1YJCQnO+mJiYiRJM2fOdI550T5y4MABjRs3Ts2bN5fdbldcXJx+97vfad++fR71GfAVkhnADa1atdLtt9/u1tmZ8ePH64knntDFF1+s5557Tv3791daWppuuukml3JPPPGEpk+frq5du2ru3Llq3bq1hgwZohMnTriUO3nypPr3769ly5bp9ttv1wsvvKDevXsrJSVFU6ZMcZZbvXq1br75ZkVHR2vOnDl68sknNWDAAH3++ede9/uGG27QsWPHlJaWphtuuEFLlixxfvRQmaNHj+qqq65S165d9cwzz+jCCy/Uo48+qpUrVzrLFBQU6JprrtHTTz+tkSNHav78+Ro1apSee+453Xjjjc5yr7/+uux2u/r27avXX39dr7/+uu655x517txZUVFR2rBhg7PsZ599plq1amn79u3Ky8tztvPFF1+oX79+znIzZszQxIkT1axZMz3zzDO6/vrr9eqrr2rIkCH69ddfXfryyy+/aNiwYUpKStK8efM0cODAMvu8cOFCjRs3TtOmTdPcuXPdGqfK5Ofna+jQoWrUqJGefvpp9e/fX88884wWLlxYquxf//pXvfDCC5o4caJSUlK0a9cuXXHFFTp48KBHbcbExGjBggWSpGuvvdY55tddd50k6frrr9eKFSs0btw4vfzyy5o0aZKOHTumH374oeodBrxhAJRr8eLFRpLZsmWL+e9//2tq165tJk2a5Fzfv39/k5iY6HydmZlpJJnx48e71PPQQw8ZSebTTz81xhhz6NAhExoaakaMGGEKCgqc5R577DEjyYwZM8a5bNasWaZevXpmz549LnVOmzbNhISEmB9++MEYY8yDDz5oIiIizLlz5zzupySTmprqfJ2ammokmTvuuMOl3LXXXmsaNWpUaX39+/c3ksxf//pX57IzZ86Ypk2bmuuvv9657PXXXze1atUyn332mcv2r7zyipFkPv/8c+eyevXquYxLkREjRphLL73U+fq6664z1113nQkJCTErV640xhizdetWI8m8//77xpjfxn/IkCEmPz/fue2LL75oJJm//OUvpfryyiuvlGq7ZcuWZsSIEcYYY55//nljs9nMrFmzKh2fsmRlZRlJZvHixc5lY8aMMZLMH//4R5ey3bp1M927dy+1bVhYmPnf//7nXJ6enm4kmcmTJ7v0p3///qXaHzNmjGnZsqXz9eHDh0vtF8YYc/ToUSPJzJ0716t+Av7AmRnATa1bt9bo0aO1cOFC5eTklFnmo48+kiSXMyaSNHXqVEnSv/71L0nSmjVrdPbsWT3wwAOy2WzOcsnJyaXq/Mc//qG+ffsqOjpaP//8s/MxePBg5efnO89KREVF6cSJE1q9enWV+1pkwoQJLq/79u2rX375xXnGoyL169fXbbfd5nwdGhqqSy+9VN9//71z2T/+8Q917NhRF154oUvfrrjiCknS2rVrK22nb9++2rp1q/OM1saNGzV8+HAlJSXps88+k1R4tsZms6lPnz6Sfhv/5ORk1ar125/Bu+66SxEREc55KmK32zVu3LhyY3jqqaf04IMPas6cOXr88ccrjdlTZc1D8XEsMmrUKF1wwQXO15deeql69uzp3C99ISwsTKGhoVq3bp2OHj3qs3qBqiCZATzw+OOP69y5c+VeO7N//37VqlVLbdu2dVnetGlTRUVFaf/+/c5yktSuXTuXcjExMYqOjnZZtnfvXq1atUoxMTEuj8GDB0uSDh06JEm677771L59ew0bNkzNmzfXHXfcoVWrVlWpvy1atHB5XRSbOwex5s2buyRqRdsX33bv3r36+uuvS/Wtffv2Ln2rSN++fXXu3Dlt2rRJu3fv1qFDh9S3b1/169fPJZnp1KmTGjZsKOm38e/QoYNLXaGhoWrdurVzfZELLrhAoaGhZba/fv16Pfroo3r00Uc9vk7GHXXr1nVev1Kk5DgWKbk/SVL79u19ei2L3W7XnDlztHLlSsXGxqpfv3566qmndODAAZ+1AXiK2xcAD7Ru3Vq33XabFi5cqGnTppVbruRBvCoKCgp05ZVX6pFHHilzfdGBv0mTJsrMzNTHH3+slStXauXKlVq8eLFuv/12LV261Ku2y7uzxhjjk20LCgrUpUsXPfvss2WWjY+Pr7SdHj16qG7dutqwYYNatGihJk2aqH379urbt69efvllnTlzRp999pmuvfbaSusqT1hYWLnrEhMTlZub67yOp1WrVl63UxZf391ks9nKnL/iFxRXJjk5WSNHjtR7772njz/+WNOnT1daWpo+/fRTdevWzZfhAm4hmQE89Pjjj2vZsmWaM2dOqXUtW7ZUQUGB9u7dq44dOzqXHzx4ULm5uWrZsqWznFR4ZqJ169bOcocPHy71P+42bdro+PHjzjMxFQkNDdXIkSM1cuRIFRQU6L777tOrr76q6dOnlzpbFAzatGmj7du3a9CgQZUmgOWtL/r46rPPPlOLFi3Ut29fSYVnbM6cOaO//e1vOnjwoMvFv0Xjv3v3bpfxP3v2rLKystwa6yKNGzfW22+/rT59+mjQoEHauHGjmjVr5vb2vrR3795Sy/bs2eO8S0kqPKtT1kdUJc9GVTYfbdq00dSpUzV16lTt3btXSUlJeuaZZ7Rs2TLvggeqgI+ZAA+1adNGt912m1599dVSp9aHDx8uSZo3b57L8qIzDyNGjJAkDR48WHXq1NH8+fNd/pdccjup8I6iTZs26eOPPy61Ljc3V+fOnZNUeMdNcbVq1dJFF10kSaVuCw8WN9xwg3788UctWrSo1LpTp0653NlVr169UrdNF+nbt6/S09O1du1aZzLTuHFjdezY0Zl0Fi2XCsc/NDRUL7zwgsv4//nPf5bD4XDOk7uaN2+uNWvW6NSpU7ryyitLzUV1ee+991y+qXrz5s1KT0/XsGHDnMvatGmj//znPzp8+LBz2fbt20vd9RYeHi5Jpcb85MmTOn36tMuyNm3aqEGDBkG7n6Hm48wM4IU//OEPev3117V7924lJiY6l3ft2lVjxozRwoULlZubq/79+2vz5s1aunSpRo0a5bylt+i7QtLS0nT11Vdr+PDh2rZtm1auXKnGjRu7tPXwww/rgw8+0NVXX62xY8eqe/fuOnHihHbu3Km3335b+/btU+PGjTV+/HgdOXJEV1xxhZo3b679+/dr/vz5SkpKcjlLFExGjx6tt956SxMmTNDatWvVu3dv5efn6z//+Y/eeustffzxx+rRo4ckqXv37lqzZo2effZZNWvWTK1atXJ+b0zfvn31f//3f8rOznZJWvr166dXX31VCQkJat68uXN5TEyMUlJSNHPmTF111VW65pprtHv3br388su65JJLXC5cdlfbtm3173//WwMGDNDQoUP16aefKiIioooj5HkMffr00b333qszZ85o3rx5atSokctHlHfccYeeffZZDR06VHfeeacOHTqkV155RYmJiS4XdoeFhalTp076+9//rvbt26thw4bq3Lmzzp07p0GDBumGG25Qp06dVLt2ba1YsUIHDx4s9fUDQLUJ6L1UQJArfmt2SUW3zRa/NdsYY3799Vcz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tKnOnj2r3Nxcl/Il56OysS6vTEREBP/rLCE0NFRt27ZV9+7dlZaWpq5du+r5559nLgIgIyNDhw4d0sUXX6zatWurdu3aWr9+vV544QXVrl1bsbGxzEkNQjIDn2nVqpWaNm2qTz75xLksLy9P6enp6tWrlySpV69eys3NVUZGhrPMp59+qoKCAvXs2dNZZsOGDfr111+dZVavXq0OHTrwEVMxxhjdf//9WrFihT799NNSH811795dderUcZmP3bt364cffnCZj507d7okmKtXr1ZERIQ6derkLFO8jqIyRXWgfAUFBTpz5gxzEQCDBg3Szp07lZmZ6Xz06NFDt956q/PfzEkNEugrkGEtx44dM9u2bTPbtm0zksyzzz5rtm3bZvbv32+MKbw1Oyoqyrz//vtmx44d5ne/+12Zt2Z369bNpKenm40bN5p27dq53Jqdm5trYmNjzejRo82uXbvM8uXLTXh4OLdml3DvvfeayMhIs27dOpOTk+N8nDx50llmwoQJpkWLFubTTz81X331lenVq5fp1auXc33RradDhgwxmZmZZtWqVSYmJqbMW08ffvhh8+2335qXXnqJW0/LMG3aNLN+/XqTlZVlduzYYaZNm2ZsNpv597//bYxhLoJB8buZjGFOahKSGXhk7dq1RlKpx5gxY4wxhbdnT58+3cTGxhq73W4GDRpkdu/e7VLHL7/8Ym6++WZTv359ExERYcaNG2eOHTvmUmb79u2mT58+xm63mwsuuMA8+eST1dVFyyhrHiSZxYsXO8ucOnXK3HfffSY6OtqEh4eba6+91uTk5LjUs2/fPjNs2DATFhZmGjdubKZOnWp+/fVXlzJr1641SUlJJjQ01LRu3dqlDRS64447TMuWLU1oaKiJiYkxgwYNciYyxjAXwaBkMsOc1Bw2Y4wJzDkhAACAquOaGQAAYGkkMwAAwNJIZgAAgKWRzAAAAEsjmQEAAJZGMgMAACyNZAYAAFgayQxwHlm3bp1sNlup36OB56ZPn667777bb/X//PPPatKkif73v//5rQ2gpuBL84AaasCAAUpKStK8efOcy86ePasjR44oNjZWNpstIHGtW7dOAwcO1NGjRxUVFRWQGKrqwIEDat++vXbu3KmWLVv6rZ2HHnpIR48e1Z///Ge/tQHUBJyZAc4joaGhatq0acASmZritdde0+WXX+7XREaSxo0bp7/97W86cuSIX9sBrI5kBqiBxo4dq/Xr1+v555+XzWaTzWbTvn37Sn3MtGTJEkVFRenDDz9Uhw4dFB4ert///vc6efKkli5dqoSEBEVHR2vSpEnKz8931n/mzBk99NBDuuCCC1SvXj317NlT69atc67fv3+/Ro4cqejoaNWrV0+JiYn66KOPtG/fPg0cOFCSFB0dLZvNprFjx0qSVq1apT59+igqKkqNGjXS1Vdfrf/+97/OOvft2yebzaa33npLffv2VVhYmC655BLt2bNHW7ZsUY8ePVS/fn0NGzZMhw8fdhmLUaNGaebMmYqJiVFERIQmTJigs2fPOsu8/fbb6tKli8LCwtSoUSMNHjxYJ06cKHd8ly9frpEjR7osGzBggB544AElJycrOjpasbGxWrRokU6cOKFx48apQYMGatu2rVauXOnc5ujRo7r11lsVExOjsLAwtWvXTosXL3auT0xMVLNmzbRixQo3Zh04jwX2p6EA+ENubq7p1auXueuuu5y/pn3u3DnnD4UePXrUGGPM4sWLTZ06dcyVV15ptm7datavX28aNWpkhgwZYm644Qbz9ddfm3/+858mNDTULF++3Fn/+PHjzeWXX242bNhgvvvuOzN37lxjt9vNnj17jDHGjBgxwlx55ZVmx44d5r///a/55z//adavX2/OnTtn3nnnHSPJ7N692+Tk5Jjc3FxjjDFvv/22eeedd8zevXvNtm3bzMiRI02XLl1Mfn6+McaYrKwsI8lceOGFZtWqVeabb74xl112menevbsZMGCA2bhxo9m6datp27atmTBhgjPWMWPGmPr165sbb7zR7Nq1y3z44YcmJibGPPbYY8YYY3766SdTu3Zt8+yzzzp/8fqll14q9eOnRX755Rdjs9nMl19+6bK8f//+pkGDBmbWrFlmz549ZtasWSYkJMQMGzbMLFy40OzZs8fce++9plGjRubEiRPGGGMmTpxokpKSzJYtW0xWVpZZvXq1+eCDD1zqvfHGG50/5AqgbCQzQA1V8heCjTFlJjOSzHfffecsc88995jw8HCXg/nQoUPNPffcY4wxZv/+/SYkJMT8+OOPLnUPGjTIpKSkGGOM6dKli5kxY0aZcZWMoTyHDx82kszOnTuNMb8lM6+99pqzzJtvvmkkmU8++cS5LC0tzXTo0MH5esyYMaZhw4bOBMIYYxYsWGDq169v8vPzTUZGhpFk9u3bV2E8RbZt22YkmR9++MFlef/+/U2fPn2cr8+dO2fq1atnRo8e7VyWk5NjJJlNmzYZY4wZOXKkGTduXIXtTZ482QwYMMCt2IDzFR8zAee58PBwtWnTxvk6NjZWCQkJql+/vsuyQ4cOSZJ27typ/Px8tW/fXvXr13c+1q9f7/xYaNKkSfrTn/6k3r17KzU1VTt27Kg0jr179+rmm29W69atFRERoYSEBEnSDz/84FLuoosucolLkrp06VJmrEW6du2q8PBw5+tevXrp+PHjys7OVteuXTVo0CB16dJF/+///T8tWrRIR48eLTfOU6dOSZLq1q1bal3x2EJCQtSoUaNSsUlyxnfvvfdq+fLlSkpK0iOPPKIvvviiVJ1hYWE6efJkufEA4JoZ4LxXp04dl9c2m63MZQUFBZKk48ePKyQkRBkZGcrMzHQ+vv32Wz3//POSpPHjx+v777/X6NGjtXPnTvXo0UPz58+vMI6RI0fqyJEjWrRokdLT05Weni5JLte2lIy36ELmksuKYnVHSEiIVq9erZUrV6pTp06aP3++OnTooKysrDLLN27cWJLKTHgqG8uieIviGzZsmPbv36/Jkyfrp59+0qBBg/TQQw+51HHkyBHFxMS43R/gfEQyA9RQoaGhLhft+kq3bt2Un5+vQ4cOqW3bti6Ppk2bOsvFx8drwoQJevfddzV16lQtWrTIGZckl9h++eUX7d69W48//rgGDRqkjh07Vnh2xFPbt293nlGRpC+//FL169dXfHy8pMIko3fv3po5c6a2bdum0NDQci+6bdOmjSIiIvTNN9/4JLaYmBiNGTNGy5Yt07x587Rw4UKX9bt27VK3bt180hZQU5HMADVUQkKC0tPTtW/fPv38888ena2oSPv27XXrrbfq9ttv17vvvqusrCxt3rxZaWlp+te//iVJSk5O1scff6ysrCxt3bpVa9euVceOHSVJLVu2lM1m04cffqjDhw/r+PHjio6OVqNGjbRw4UJ99913+vTTTzVlyhSfxCsVnt2588479c033+ijjz5Samqq7r//ftWqVUvp6emaPXu2vvrqK/3www969913dfjwYWe8JdWqVUuDBw/Wxo0bqxzXE088offff1/fffedvv76a3344Ycu7Z48eVIZGRkaMmRIldsCajKSGaCGeuihhxQSEqJOnTopJiam1LUnVbF48WLdfvvtmjp1qjp06KBRo0Zpy5YtatGihaTCsy4TJ05Ux44dddVVV6l9+/Z6+eWXJUkXXHCBZs6cqWnTpik2NtaZVCxfvlwZGRnq3LmzJk+erLlz5/os3kGDBqldu3bq16+fbrzxRl1zzTWaMWOGJCkiIkIbNmzQ8OHD1b59ez3++ON65plnNGzYsHLrGz9+vJYvX17lBDE0NFQpKSm66KKL1K9fP4WEhGj58uXO9e+//75atGihvn37VqkdoKbjG4AB1Ghjx45Vbm6u3nvvPZ/VaYxRz549NXnyZN18880+q7ekyy67TJMmTdItt9zitzaAmoAzMwDgIZvNpoULF+rcuXN+a+Pnn3/Wdddd59dkCagpODMDoEbzx5kZAMGFZAYAAFgaHzMBAABLI5kBAACWRjIDAAAsjWQGAABYGskMAACwNJIZAABgaSQzAADA0khmAACApZHMAAAAS/v/JUqG/OtcY5QAAAAASUVORK5CYII=", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from bmtk.analyzer.spike_trains import plot_raster\n", "\n", "_ = plot_raster(spikes_file='inputs/custom_spikes.csv', with_histogram=False)" ] }, { "cell_type": "markdown", "id": "fdf47f53-740f-44b3-b167-aec0c3117b4c", "metadata": {}, "source": [ "**Remember**: Biophysical models contain customized ion channels that require compiling using the `nrnivmod` command before running Bionet (see [Tutorial 1](https://alleninstitute.github.io/bmtk/tutorials/tutorial_01_single_cell_clamped.html) for more details). Ion channels are stored in the **components/mechanisms/mod/** folder. In a shell or using Jupyter notebook, you'll need to run the following:" ] }, { "cell_type": "code", "execution_count": 5, "id": "4eac131f", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "/opt/conda/bin/nrnivmodl:10: DeprecationWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html\n", " from pkg_resources import working_set\n", "/home/shared/bmtk-workshop/docs/tutorial/03_opt_advanced_spiking_inputs/components/mechanisms\n", "Mod files: \"modfiles/modfiles/CaDynamics.mod\" \"modfiles/modfiles/Ca_HVA.mod\" \"modfiles/modfiles/Ca_LVA.mod\" \"modfiles/modfiles/Ih.mod\" \"modfiles/modfiles/Im.mod\" \"modfiles/modfiles/Im_v2.mod\" \"modfiles/modfiles/K_P.mod\" \"modfiles/modfiles/K_T.mod\" \"modfiles/modfiles/Kd.mod\" \"modfiles/modfiles/Kv2like.mod\" \"modfiles/modfiles/Kv3_1.mod\" \"modfiles/modfiles/NaTa.mod\" \"modfiles/modfiles/NaTs.mod\" \"modfiles/modfiles/NaV.mod\" \"modfiles/modfiles/Nap.mod\" \"modfiles/modfiles/SK.mod\" \"modfiles/modfiles/exp1isyn.mod\" \"modfiles/modfiles/exp1syn.mod\" \"modfiles/modfiles/stp1syn.mod\" \"modfiles/modfiles/stp2syn.mod\" \"modfiles/modfiles/stp3syn.mod\" \"modfiles/modfiles/stp4syn.mod\" \"modfiles/modfiles/stp5isyn.mod\" \"modfiles/modfiles/stp5syn.mod\" \"modfiles/modfiles/vecevent.mod\"\n", "\n", "Creating 'x86_64' directory for .o files.\n", "\n", " -> \u001b[32mCompiling\u001b[0m mod_func.cpp\n", " -> \u001b[32mNMODL\u001b[0m ../modfiles/CaDynamics.mod\n", " -> \u001b[32mNMODL\u001b[0m ../modfiles/Ca_HVA.mod\n", " -> \u001b[32mNMODL\u001b[0m ../modfiles/Ca_LVA.mod\n", "Translating Ca_HVA.mod into /home/shared/bmtk-workshop/docs/tutorial/03_opt_advanced_spiking_inputs/components/mechanisms/x86_64/Ca_HVA.c\n", "Translating Ca_LVA.mod into /home/shared/bmtk-workshop/docs/tutorial/03_opt_advanced_spiking_inputs/components/mechanisms/x86_64/Ca_LVA.c\n", "Translating CaDynamics.mod into /home/shared/bmtk-workshop/docs/tutorial/03_opt_advanced_spiking_inputs/components/mechanisms/x86_64/CaDynamics.c\n", "Thread Safe\n", "Thread Safe\n", "Thread Safe\n", " -> \u001b[32mNMODL\u001b[0m ../modfiles/Ih.mod\n", " -> \u001b[32mNMODL\u001b[0m ../modfiles/Im_v2.mod\n", " -> \u001b[32mNMODL\u001b[0m ../modfiles/Im.mod\n", "Translating Im_v2.mod into /home/shared/bmtk-workshop/docs/tutorial/03_opt_advanced_spiking_inputs/components/mechanisms/x86_64/Im_v2.c\n", "Translating Ih.mod into /home/shared/bmtk-workshop/docs/tutorial/03_opt_advanced_spiking_inputs/components/mechanisms/x86_64/Ih.c\n", "Translating Im.mod into /home/shared/bmtk-workshop/docs/tutorial/03_opt_advanced_spiking_inputs/components/mechanisms/x86_64/Im.c\n", "Thread Safe\n", " -> \u001b[32mNMODL\u001b[0m ../modfiles/K_P.mod\n", "Thread Safe\n", "Thread Safe\n", " -> \u001b[32mNMODL\u001b[0m ../modfiles/K_T.mod\n", " -> \u001b[32mNMODL\u001b[0m ../modfiles/Kd.mod\n", "Translating K_P.mod into /home/shared/bmtk-workshop/docs/tutorial/03_opt_advanced_spiking_inputs/components/mechanisms/x86_64/K_P.c\n", "Translating K_T.mod into /home/shared/bmtk-workshop/docs/tutorial/03_opt_advanced_spiking_inputs/components/mechanisms/x86_64/K_T.c\n", "Translating Kd.mod into /home/shared/bmtk-workshop/docs/tutorial/03_opt_advanced_spiking_inputs/components/mechanisms/x86_64/Kd.c\n", "Thread Safe\n", "Thread Safe\n", "Thread Safe\n", " -> \u001b[32mNMODL\u001b[0m ../modfiles/Kv2like.mod\n", " -> \u001b[32mNMODL\u001b[0m ../modfiles/Kv3_1.mod\n", " -> \u001b[32mNMODL\u001b[0m ../modfiles/NaTa.mod\n", "Translating Kv2like.mod into /home/shared/bmtk-workshop/docs/tutorial/03_opt_advanced_spiking_inputs/components/mechanisms/x86_64/Kv2like.c\n", "Translating Kv3_1.mod into /home/shared/bmtk-workshop/docs/tutorial/03_opt_advanced_spiking_inputs/components/mechanisms/x86_64/Kv3_1.c\n", "Translating NaTa.mod into /home/shared/bmtk-workshop/docs/tutorial/03_opt_advanced_spiking_inputs/components/mechanisms/x86_64/NaTa.c\n", "Thread Safe\n", "Thread Safe\n", "Thread Safe\n", " -> \u001b[32mNMODL\u001b[0m ../modfiles/NaTs.mod\n", " -> \u001b[32mNMODL\u001b[0m ../modfiles/NaV.mod\n", " -> \u001b[32mNMODL\u001b[0m ../modfiles/Nap.mod\n", "Translating NaTs.mod into /home/shared/bmtk-workshop/docs/tutorial/03_opt_advanced_spiking_inputs/components/mechanisms/x86_64/NaTs.c\n", "Translating NaV.mod into /home/shared/bmtk-workshop/docs/tutorial/03_opt_advanced_spiking_inputs/components/mechanisms/x86_64/NaV.c\n", "Translating Nap.mod into /home/shared/bmtk-workshop/docs/tutorial/03_opt_advanced_spiking_inputs/components/mechanisms/x86_64/Nap.c\n", "NEURON's CVode method ignores conservation\n", "Notice: LINEAR is not thread safe.\n", "Thread Safe\n", "Thread Safe\n", " -> \u001b[32mNMODL\u001b[0m ../modfiles/SK.mod\n", " -> \u001b[32mNMODL\u001b[0m ../modfiles/exp1syn.mod\n", " -> \u001b[32mNMODL\u001b[0m ../modfiles/exp1isyn.mod\n", "Translating SK.mod into /home/shared/bmtk-workshop/docs/tutorial/03_opt_advanced_spiking_inputs/components/mechanisms/x86_64/SK.c\n", "Translating exp1syn.mod into /home/shared/bmtk-workshop/docs/tutorial/03_opt_advanced_spiking_inputs/components/mechanisms/x86_64/exp1syn.c\n", "Translating exp1isyn.mod into /home/shared/bmtk-workshop/docs/tutorial/03_opt_advanced_spiking_inputs/components/mechanisms/x86_64/exp1isyn.c\n", "Thread Safe\n", "Thread Safe\n", "Thread Safe\n", " -> \u001b[32mNMODL\u001b[0m ../modfiles/stp1syn.mod\n", " -> \u001b[32mNMODL\u001b[0m ../modfiles/stp2syn.mod\n", " -> \u001b[32mNMODL\u001b[0m ../modfiles/stp3syn.mod\n", "Translating stp1syn.mod into /home/shared/bmtk-workshop/docs/tutorial/03_opt_advanced_spiking_inputs/components/mechanisms/x86_64/stp1syn.c\n", "Translating stp2syn.mod into /home/shared/bmtk-workshop/docs/tutorial/03_opt_advanced_spiking_inputs/components/mechanisms/x86_64/stp2syn.c\n", "Translating stp3syn.mod into /home/shared/bmtk-workshop/docs/tutorial/03_opt_advanced_spiking_inputs/components/mechanisms/x86_64/stp3syn.c\n", "Thread Safe\n", "Thread Safe\n", "Thread Safe\n", " -> \u001b[32mNMODL\u001b[0m ../modfiles/stp4syn.mod\n", " -> \u001b[32mNMODL\u001b[0m ../modfiles/stp5isyn.mod\n", " -> \u001b[32mNMODL\u001b[0m ../modfiles/stp5syn.mod\n", "Translating stp4syn.mod into /home/shared/bmtk-workshop/docs/tutorial/03_opt_advanced_spiking_inputs/components/mechanisms/x86_64/stp4syn.c\n", "Translating stp5isyn.mod into /home/shared/bmtk-workshop/docs/tutorial/03_opt_advanced_spiking_inputs/components/mechanisms/x86_64/stp5isyn.c\n", "Translating stp5syn.mod into /home/shared/bmtk-workshop/docs/tutorial/03_opt_advanced_spiking_inputs/components/mechanisms/x86_64/stp5syn.c\n", "Thread Safe\n", "Thread Safe\n", "Thread Safe\n", " -> \u001b[32mNMODL\u001b[0m ../modfiles/vecevent.mod\n", " -> \u001b[32mCompiling\u001b[0m CaDynamics.c\n", " -> \u001b[32mCompiling\u001b[0m Ca_HVA.c\n", "Translating vecevent.mod into /home/shared/bmtk-workshop/docs/tutorial/03_opt_advanced_spiking_inputs/components/mechanisms/x86_64/vecevent.c\n", "Notice: VERBATIM blocks are not thread safe\n", " -> \u001b[32mCompiling\u001b[0m Ca_LVA.c\n", " -> \u001b[32mCompiling\u001b[0m Ih.c\n", " -> \u001b[32mCompiling\u001b[0m Im.c\n", " -> \u001b[32mCompiling\u001b[0m Im_v2.c\n", " -> \u001b[32mCompiling\u001b[0m K_P.c\n", " -> \u001b[32mCompiling\u001b[0m K_T.c\n", " -> \u001b[32mCompiling\u001b[0m Kd.c\n", " -> \u001b[32mCompiling\u001b[0m Kv2like.c\n", " -> \u001b[32mCompiling\u001b[0m Kv3_1.c\n", " -> \u001b[32mCompiling\u001b[0m NaTa.c\n", " -> \u001b[32mCompiling\u001b[0m NaTs.c\n", " -> \u001b[32mCompiling\u001b[0m NaV.c\n", " -> \u001b[32mCompiling\u001b[0m Nap.c\n", " -> \u001b[32mCompiling\u001b[0m SK.c\n", " -> \u001b[32mCompiling\u001b[0m exp1isyn.c\n", " -> \u001b[32mCompiling\u001b[0m exp1syn.c\n", " -> \u001b[32mCompiling\u001b[0m stp1syn.c\n", " -> \u001b[32mCompiling\u001b[0m stp2syn.c\n", " -> \u001b[32mCompiling\u001b[0m stp3syn.c\n", " -> \u001b[32mCompiling\u001b[0m stp4syn.c\n", " -> \u001b[32mCompiling\u001b[0m stp5isyn.c\n", " -> \u001b[32mCompiling\u001b[0m stp5syn.c\n", " -> \u001b[32mCompiling\u001b[0m vecevent.c\n", " => \u001b[32mLINKING\u001b[0m shared library ./libnrnmech.so\n", " => \u001b[32mLINKING\u001b[0m executable ./special LDFLAGS are: -pthread\n", "Successfully created x86_64/special\n" ] } ], "source": [ "! cd components/mechanisms && nrnivmodl modfiles" ] }, { "cell_type": "markdown", "id": "33d7ba6b", "metadata": {}, "source": [ "We can now run the simulation with our custom CSV input file." ] }, { "cell_type": "code", "execution_count": 6, "id": "4836b12f-9f91-40d2-9031-5e1a927245ef", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2024-10-24 00:02:57,330 [INFO] Created log file\n", "2024-10-24 00:02:57,418 [INFO] Building cells.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "Warning: no DISPLAY environment variable.\n", "--No graphics will be displayed.\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "2024-10-24 00:02:58,097 [INFO] Building recurrent connections\n", "2024-10-24 00:02:58,102 [INFO] Building virtual cell stimulations for LGN_spikes_sonata\n", "2024-10-24 00:02:58,137 [INFO] Running simulation for 2000.000 ms with the time step 0.100 ms\n", "2024-10-24 00:02:58,138 [INFO] Starting timestep: 0 at t_sim: 0.000 ms\n", "2024-10-24 00:02:58,138 [INFO] Block save every 5000 steps\n", "2024-10-24 00:02:58,492 [INFO] step:5000 t_sim:500.00 ms\n", "2024-10-24 00:02:58,839 [INFO] step:10000 t_sim:1000.00 ms\n", "2024-10-24 00:02:59,176 [INFO] step:15000 t_sim:1500.00 ms\n", "2024-10-24 00:02:59,514 [INFO] step:20000 t_sim:2000.00 ms\n", "2024-10-24 00:02:59,549 [INFO] Simulation completed in 1.412 seconds \n" ] }, { "data": { "image/png": "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uybJHnvsMa/51157rblcLtu6datnmiSLiIiwjRs3erXdv39/kfEu1K9fP2vfvr0dP37ca9sXX3yxtWjRwqvtjTfeaLGxsbZ582Z7+umnTZInuAHhiI/MAB81bdpUN998s2bPnq2cnJxi27z//vuSpPHjx3tNnzBhgiTpn//8pyRpyZIlOnnypO6++265XC5Pu3HjxhVZ59///nf17NlTtWrV0g8//OC5paWlKT8/XytWrJAkJSQk6OjRo/rwww/L3ddCt99+u9ffPXv21IEDB5SXl1fqsjVq1NBvfvMbz99RUVHq2rWrvvvuO8+0v//972rdurXOP/98r75deumlkqRly5aVup2ePXtqzZo1Onr0qCTp008/1aBBg9SpUyd98sknkqRPPvlELpdLl1xyiaT/7f9x48YpIuJ/L4O33nqr4uLiPONUKDo6WiNHjjxrDU899ZTGjh2rJ598sswnp7/11luqW7eu7r777iLzCh8j77//viIjIzVmzBiv+RMmTJCZadGiRV7Te/furTZt2vi0/YMHD2rp0qW67rrrdPjwYc9YHDhwQAMGDNCWLVu8vmk5bdo0xcfH69prr9XkyZN1880368orrzzXbgMhg0AEnIOHH35Yp06dOuu5RDt27FBERISaN2/uNb1+/fpKSEjQjh07PO0kqUWLFl7tEhMTVatWLa9pW7Zs0eLFi5WYmOh1S0tLk3T6nA5JuvPOO9WyZUsNHDhQDRo00C233KLFixeXq78NGzb0+ruwtkOHDpW6bIMGDbzCXuHyP192y5Yt2rhxY5G+tWzZ0qtvJenZs6dOnTqllStXatOmTdq3b5969uypXr16eQWiNm3aqHbt2pL+t/9btWrlta6oqCg1bdrUM7/Qeeedp6ioqGK3//HHH+v+++/X/fffX6bzhgpt27ZNrVq1KvHk9h07diglJUU1a9b0mt66dWvP/J9r0qSJz9vfunWrzEyTJ08uMh7p6emSvMejdu3a+vOf/6z169crPj5ef/7zn33eFhCK+FoJcA6aNm2q3/zmN5o9e7YeeOCBs7Y7MwiUR0FBgX75y1/qvvvuK3Z+YXioV6+e1q1bpw8++ECLFi3SokWLNHfuXA0bNkzz5s0r07YjIyOLnW5nnMBb1mULCgrUvn17TZ06tdi2qamppW6nS5cuqlatmlasWKGGDRuqXr16atmypXr27KkZM2boxIkT+uSTT3T11VeXuq6ziYmJOeu8tm3bKjc3V6+88opuu+22cwohFa2kus9UeIL+xIkTNWDAgGLbnBn0P/jgA0mnA/J///tfJSQklK1QIAQQiIBz9PDDD2v+/Pl68skni8xr1KiRCgoKtGXLFs//2iVp7969ys3NVaNGjTztpNNHSJo2beppt3///iJHX5o1a6YjR454jgiVJCoqSkOGDNGQIUNUUFCgO++8U7NmzdLkyZOLvJmFgmbNmumrr75Sv379Sg2RZ5tf+FHcJ598ooYNG6pnz56STh85OnHihF599VXt3btXvXr18ixTuP83bdrktf9Pnjyp7Oxsn/Z1obp16+rNN9/UJZdcon79+unTTz9VSkqKz8sXatasmVatWqWffvpJVatWLbZNo0aNtGTJEh0+fNjrKNG3337r1a+SnG0/Fu6HqlWr+tT/xYsX68UXX9R9992nV199VcOHD9eqVau4fAPCFh+ZAeeoWbNm+s1vfqNZs2Zpz549XvMGDRokSXr22We9phceARk8eLAkKS0tTVWrVtXzzz/vdcTkzOUk6brrrtPKlSs9/xv/udzcXJ06dUqSdODAAa95ERER6tChgyQV+cp/qLjuuuv0/fffa86cOUXm/fjjj57zgiSpevXqRb4SX6hnz55atWqVli1b5glEdevWVevWrT3BtXC6dHr/R0VF6c9//rPX/v/LX/4it9vtGSdfNWjQQEuWLNGPP/6oX/7yl0XGwhe/+tWv9MMPP2jatGlF5hXWOGjQIOXn5xdp88wzz8jlcmngwIGlbic2NlaSiuzLevXqqU+fPpo1a1ax58jt37/f8+/c3FyNGjVKXbt21eOPP64XX3xRa9as0eOPP17q9oFQRZQHyuChhx7SK6+8ok2bNqlt27ae6R07dtTw4cM1e/Zs5ebmqnfv3lq9erXmzZunq666Sn379pV0+lyhiRMnKjMzU5dffrkGDRqktWvXatGiRapbt67Xtu6991794x//0OWXX64RI0aoc+fOOnr0qL7++mu9+eab2r59u+rWratRo0bp4MGDuvTSS9WgQQPt2LFDzz//vDp16uR1tCqU3HzzzXrjjTd0++23a9myZerRo4fy8/P17bff6o033tAHH3ygLl26SJI6d+6sJUuWaOrUqUpJSVGTJk081xXq2bOn/vCHP2jXrl1ewadXr16aNWuWGjdurAYNGnimJyYmatKkScrIyNBll12mK664Qps2bdKMGTN00UUXeZ0M7qvmzZvrX//6l/r06aMBAwZo6dKliouL83n5YcOG6a9//avGjx+v1atXq2fPnjp69KiWLFmiO++8U1deeaWGDBmivn376qGHHtL27dvVsWNH/etf/9LChQs1btw4NWvWrNTtxMTEqE2bNvrb3/6mli1bqnbt2mrXrp3atWun6dOn65JLLlH79u116623qmnTptq7d69Wrlyp//73v/rqq68kSWPHjtWBAwe0ZMkSRUZG6rLLLtOoUaP02GOP6corr1THjh3Pef8BQRfEb7gBIe/nX7s/U+H1hs68DtFPP/1kGRkZ1qRJE6tataqlpqbapEmTvL7KbHb62i0ZGRmWnJxsMTEx1qdPH9uwYYM1atSoyNfLDx8+bJMmTbLmzZtbVFSU1a1b1y6++GL74x//6Llmzptvvmn9+/e3evXqWVRUlDVs2NBuu+02y8nJKbWfOsvX7vfv31/s/sjOzi5xfcVdn8ns9D5r1KiR17STJ0/ak08+aW3btrXo6GirVauWde7c2TIyMjzXETIz+/bbb61Xr14WExNT5NIEeXl5FhkZaTVr1vS67MD8+fNNkt18883F1jlt2jQ7//zzrWrVqpaUlGR33HGHHTp0yKe+mBW9DpGZ2apVq6xmzZrWq1cvO3bsWLHLnc2xY8fsoYce8jx26tevb9dee61t27bN0+bw4cN2zz33WEpKilWtWtVatGhhTz/9tNflG8xOj+no0aOL3c5nn31mnTt3tqioqCJjv23bNhs2bJjVr1/fqlatauedd55dfvnl9uabb5qZ2cKFC02S/elPf/JaZ15enjVq1Mg6duzodR0nIFy4zHw4OxIAAKAS4xwiAADgeAQiAADgeAQiAADgeEENRCtWrNCQIUOUkpIil8uld99912u+memRRx5RcnKyYmJilJaWpi1btgSnWAAAUGkFNRAdPXpUHTt21PTp04ud/9RTT+nPf/6zXnjhBa1atUrVq1fXgAEDdPz48QBXCgAAKrOQ+ZaZy+XSO++8o6uuukrS6aNDKSkpmjBhgiZOnChJcrvdSkpK0ssvv6wbbrghiNUCAIDKJGQvzJidna09e/Z4XUI+Pj5e3bp108qVK88aiE6cOOF1Vd6CggIdPHhQderU8evvSwEAgIpjZjp8+LBSUlIUEVHxH2iFbCAq/EmEpKQkr+lJSUlFfi7h5zIzM5WRkVGhtQEAgMDYtWuX15XmK0rIBqKymjRpksaPH+/52+12q2HDhtq1a9c5XUYfAAAET15enlJTU71+yLgihWwgql+/vqTTvxKenJzsmb5371516tTprMtFR0crOjq6yPS4uDgCEQAAYSZQp7uE7HWImjRpovr16+ujjz7yTMvLy9OqVavUvXv3IFYGAAAqm6AeITpy5Ii2bt3q+Ts7O1vr1q1T7dq11bBhQ40bN06PPfaYWrRooSZNmmjy5MlKSUnxfBMNAADAH4IaiL788kv17dvX83fhuT/Dhw/Xyy+/rPvuu09Hjx7V7373O+Xm5uqSSy7R4sWLVa1atWCVDAAAKqGQuQ5RRcnLy1N8fLzcbjfnEAEAECYC/f4dsucQAQAABAqBCAAAOB6BCAAAOB6BCAAAOB6BCAAAOB6BCAAAOB6BCAAAOB6BCAAAOB6BCAAAOB6BCAAAOB6BCAAAOB6BCAAAOB6BCAAAOB6BCAAAOB6BCAAAOB6BCAAAOB6BCAAAOB6BCAAAOB6BCAAAOB6BKMzk5EhTppy+R8Uqbl+H0v4vqZbCeevWhU698J0vY1uWMQ2Vx29F1XHmekOlv/50tj7l5EgTJki33Xb6vjL1OWCsknO73SbJ3G53sEvxi6wsM+n0PSpWcfs6lPZ/SbUUzps/P3Tqhe98GduyjGmoPH4rqo4z1xsq/fWns/WpcHrhrTL0OdDv3xwhAgAAjkcgAgAAjlcl2AXg3CQnS+npp+9RsYrb16G0/0uqpXBe27ahUy9858vYlmVMQ+XxW1F1nLneUOmvP52tT8nJ0vjx0pEjUo0alavPgeIyMwt2ERUpLy9P8fHxcrvdiouLC3Y5AADAB4F+/+YjMwAA4HgEIgAA4HgEIgAA4HgEIgAA4HgEIgAA4HgEIgAA4HgEIgAA4HgEIgAA4HgEIgAA4HgEIgAA4HgEIgAA4HgEIgAA4HgEIgAA4HgEIgAA4HgEIgAA4HgEIgAA4HgEIgAA4HgEIgAA4HgEIgAA4HgEIgAA4HghHYjy8/M1efJkNWnSRDExMWrWrJkeffRRmVmwSwMAAJVIlWAXUJInn3xSM2fO1Lx589S2bVt9+eWXGjlypOLj4zVmzJhglwcAACqJkD5C9Nlnn+nKK6/U4MGD1bhxY1177bXq37+/Vq9eHezSSpWTI02Zcvq+PMuVdT2B4K/afFlPebcVyP0YiP4EYp2h/NjzlT/7UNy6zvX56o96SlpHsMcsWK9fwe63L8o7bsHqYzjsW7+xEPaHP/zBGjVqZJs2bTIzs3Xr1lm9evVs/vz5Z13m+PHj5na7Pbddu3aZJHO73YEq28zMsrLMpNP35VmurOsJBH/V5st6yrutQO7HQPQnEOsM5ceer/zZh+LWda7PV3/UU9I6gj1mwXr9Cna/fVHecQtWH4O5b91ud0Dfv0P6I7MHHnhAeXl5Ov/88xUZGan8/Hz94Q9/0NChQ8+6TGZmpjIyMgJYJQAACHch/ZHZG2+8oVdffVWvvfaa1qxZo3nz5umPf/yj5s2bd9ZlJk2aJLfb7bnt2rUrgBUDAIBwFNJHiO6991498MADuuGGGyRJ7du3144dO5SZmanhw4cXu0x0dLSio6MDWWaxkpOl9PTT9+VZrqzrCQR/1ebLesq7rUDux0D0JxDrDOXHnq/82Yfi1nWuz1d/1FPSOoI9ZsF6/Qp2v31R3nELVh/DYd/6i8ssdL/DXqdOHT322GO64447PNMyMzM1d+5cbd682ad15OXlKT4+Xm63W3FxcRVVKgAA8KNAv3+H9BGiIUOG6A9/+IMaNmyotm3bau3atZo6dapuueWWYJcGAAAqkZA+QnT48GFNnjxZ77zzjvbt26eUlBTdeOONeuSRRxQVFeXTOjhCBABA+An0+3dIByJ/IBABABB+Av3+HdLfMgMAAAgEAhEAAHA8AhEAAHA8AhEAAHA8AhEAAHA8AhEAAHA8AhEAAHA8AhEAAHA8AhEAAHA8AhEAAHA8AhEAAHA8AhEAAHA8AhEAAHA8AhEAAHA8AhEAAHA8AhEAAHA8AhEAAHA8AhEAAHA8AhEAAHA8AlEQ5ORIU6acvg/n7fmy3tLalDQ/0PvJyfy1rxmzkuXkSBMmnL4Fax8Fe4yCvX1/KWs/fr5cKDwefHFmzefS77Aab6vk3G63STK32x3sUjyyssyk0/fhvD1f1ltam5LmB3o/OZm/9jVjVrLC/RPMfRTsMQr29v2lrP34+XKh8HjwRXE1+1pvecY70O/fHCECAACORyACAACOVyXYBThRcrKUnn76Ppy358t6S2tT0vxA7ycn89e+ZsxKlpwsjR//v38Hq4ZgjlGwt+8vZe3HmcsF+/HgizNrPpd+h9N4u8zMgl1ERcrLy1N8fLzcbrfi4uKCXQ4AAPBBoN+/+cgMAAA4HoEIAAA4HoEIAAA4HoEIAAA4HoEIAAA4HoEIAAA4HoEIAAA4HoEIAAA4HoEIAAA4HoEIAAA4HoEIAAA4HoEIAAA4HoEIAAA4HoEIAAA4HoEIAAA4HoEIAAA4HoEIAAA4HoEIAAA4HoEIAAA4HoEIAAA4XsgHou+//16/+c1vVKdOHcXExKh9+/b68ssvg10WAACoRKoEu4CSHDp0SD169FDfvn21aNEiJSYmasuWLapVq1awSwMAAJVISB8hevLJJ5Wamqq5c+eqa9euatKkifr3769mzZoFu7SAysmRpkw5fV/c38W1O1ubQNRX1jbhpKz98ed+qGz7NNSUZf9W1JgEaqwLt7NuXdHthdL+8Ify1hbKfUMZWQhr3bq1jRs3zq699lpLTEy0Tp062ezZs0tc5vjx4+Z2uz23Xbt2mSRzu90Bqtr/srLMpNP3xf1dXLuztQlEfWVtE07K2h9/7ofKtk9DTVn2b0WNSaDGunA78+cX3V4o7Q9/KG9tody3ysLtdgf0/TukjxB99913mjlzplq0aKEPPvhAd9xxh8aMGaN58+addZnMzEzFx8d7bqmpqQGsGAAAhKOQDkQFBQW68MIL9fjjj+uCCy7Q7373O91666164YUXzrrMpEmT5Ha7Pbddu3YFsGIAABCOQvqk6uTkZLVp08ZrWuvWrfXWW2+ddZno6GhFR0dXdGkBlZwspaefvi/u77O1K65NIOora5twUtb++HM/VLZ9GmrKsn8rakwCNdaF22nbtuj2Qml/+EN5awvlvqFsXGZmwS7ibG666Sbt2rVLn3zyiWfaPffco1WrVumzzz7zaR15eXmKj4+X2+1WXFxcRZUKAAD8KNDv3yH9kdk999yjzz//XI8//ri2bt2q1157TbNnz9bo0aODXRoAAKhEQjoQXXTRRXrnnXf0+uuvq127dnr00Uf17LPPaujQocEuDQAAVCIh/ZGZP/CRGQAA4YePzAAAAAKsTIFo8eLF+vTTTz1/T58+XZ06ddJNN92kQ4cO+a04AACAQChTILr33nuVl5cnSfr66681YcIEDRo0SNnZ2Ro/frxfCwQAAKhoZboOUXZ2tuf6QG+99ZYuv/xyPf7441qzZo0GDRrk1wIBAAAqWpmOEEVFRenYsWOSpCVLlqh///6SpNq1a3uOHAEAAISLMh0huuSSSzR+/Hj16NFDq1ev1t/+9jdJ0ubNm9WgQQO/FggAAFDRynSEaNq0aapSpYrefPNNzZw5U+edd54kadGiRbrsssv8WiAAAEBF4zpEAAAg5AT6/dvnj8zO5dwgggcAAAgnPgeihIQEuVwun9rm5+eXuSAAAIBA8zkQLVu2zPPv7du364EHHtCIESPUvXt3SdLKlSs1b948ZWZm+r9KAACAClSmc4j69eunUaNG6cYbb/SaXvhr9MuXL/dXfeXGOUQAAISfsPgts5UrV6pLly5Fpnfp0kWrV68ud1EAAACBVKZAlJqaqjlz5hSZ/uKLLyo1NbXcRQEAAARSmS7M+Mwzz+hXv/qVFi1apG7dukmSVq9erS1btuitt97ya4EAAAAVrUxHiAYNGqTNmzdryJAhOnjwoA4ePKghQ4Zo8+bN/JYZAAAIO1yYEQAAhJyQvTDj+vXr1a5dO0VERGj9+vUltu3QoUO5CwMAAAgUnwNRp06dtGfPHtWrV0+dOnWSy+VScQeXXC4XF2YEAABhxedziLKzs5WYmOj593fffafs7Owit++++67CivWHnBxpypTT9xW5Ln9uJxDrDZXtBXu7wRSqfQ7Vus6VL/2oLH31p4reJ6Gwz0OhhmArbR8Uzl+3zrtdpdp3VoEGDRpku3fvrshNlMrtdpskc7vdZmaWlWUmnb4vr5LW5c/tBGK9obK9YG83mEK1z6Fa17nypR+Vpa/+VNH7JBT2eSjUEGyl7YPC+fPne7eryH135vt3RSvTt8x8tWLFCv34448VuQkAAIByq9BABAAAEA4cF4iSk6X09NP3Fbkuf24nEOsNle0Fe7vBFKp9DtW6zpUv/agsffWnit4nobDPQ6GGYCttHxTOb9vWu11l2ncVeh2imjVr6quvvlLTpk0rahOl4jpEAACEn7D4cVcAAIDKhEAEAAAcr0ID0YMPPqjatWtX5CYAAADKrcyB6JVXXlGPHj2UkpKiHTt2SJKeffZZLVy40NNm0qRJSkhIKHeRAAAAFalMgWjmzJkaP368Bg0apNzcXM9PdSQkJOjZZ5/1Z30AAAAVrkyB6Pnnn9ecOXP00EMPKTIy0jO9S5cu+vrrr/1WHAAAQCCUKRBlZ2frggsuKDI9OjpaR48eLXdRAAAAgVSmQNSkSROtW7euyPTFixerdevW5a0JAAAgoKqUZaHx48dr9OjROn78uMxMq1ev1uuvv67MzEy9+OKL/q4RAACgQpUpEI0aNUoxMTF6+OGHdezYMd10001KSUnRc889pxtuuMHfNQIAAFSocv90x7Fjx3TkyBHVq1fPXzX5FT/dAQBA+An0+3eZjhD9XGxsrGJjY/1RCwAAQFD4HIguuOACuVwun9quWbOmzAUBAAAEms+B6KqrrvL8+/jx45oxY4batGmj7t27S5I+//xzbdy4UXfeeaffiwQAAKhIPgei9PR0z79HjRqlMWPG6NFHHy3SZteuXf6rDgAAIADKdFJ1fHy8vvzyS7Vo0cJr+pYtW9SlSxe53W6/FVhenFQNAED4CfT7d5kuzBgTE6N///vfRab/+9//VrVq1cpdFAAAQCCV6Vtm48aN0x133KE1a9aoa9eukqRVq1bppZde0uTJk/1aIAAAQEUrUyB64IEH1LRpUz333HOaP3++JKl169aaO3eurrvuOr8WCAAAUNHKfWHGUMc5RAAAhJ+wOIeoUFZWlubPn6/58+dr7dq1/qrprJ544gm5XC6NGzeuwrcFAACco0wfme3bt0833HCDli9froSEBElSbm6u+vbtqwULFigxMdGfNUqSvvjiC82aNUsdOnTw+7oBAICzlekI0d13363Dhw9r48aNOnjwoA4ePKgNGzYoLy9PY8aM8XeNOnLkiIYOHao5c+aoVq1afl9/SXJypClTTt87gdP6Wx6hsq9KqiMUagyFGpwsXPb/mXWWVne49Ku8nNLPUFCmQLR48WLNmDFDrVu39kxr06aNpk+frkWLFvmtuEKjR4/W4MGDlZaWVmrbEydOKC8vz+tWHjk5UkaGcx6MTutveYTKviqpjlCoMRRqcLJw2f9n1lla3eHSr/JySj9DQZk+MisoKFDVqlWLTK9ataoKCgrKXdTPLViwQGvWrNEXX3zhU/vMzExlZGT4tQYAAFC5lekI0aWXXqqxY8dq9+7dnmnff/+97rnnHvXr189vxe3atUtjx47Vq6++6vMFHydNmiS32+258VMiAACgNGU6QjRt2jRdccUVaty4sVJTUyVJO3fuVPv27T3XJfKHrKws7du3TxdeeKFnWn5+vlasWKFp06bpxIkTioyM9FomOjpa0dHRfqshOVlKTz997wRO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Xr16XvOrVKmi2rVre7Vp0qRJkXUUzqtVq1aF1O8vx48f1/33368bb7zR68c9x4wZowsvvFC1a9fWZ599pkmTJiknJ0dTp06VFJ79vuyyy3TNNdeoSZMm2rZtmx588EENHDhQK1euVGRkpCPGe968eapZs6auueYar+nhPN7FvWf56/X7bG3y8vL0448/KiYmxqcaK20gquxGjx6tDRs26NNPP/Wa/rvf/c7z7/bt2ys5OVn9+vXTtm3b1KxZs0CX6RcDBw70/LtDhw7q1q2bGjVqpDfeeMPnB3q4+8tf/qKBAwcqJSXFM60yjjWK+umnn3TdddfJzDRz5kyveePHj/f8u0OHDoqKitJtt92mzMzMsP2ZhxtuuMHz7/bt26tDhw5q1qyZli9frn79+gWxssB56aWXNHToUFWrVs1rejiP99nes0JJpf3IrG7duoqMjCxytvrevXtVv379IFXlH3fddZfee+89LVu2TA0aNCixbbdu3SRJW7dulSTVr1+/2H1SOC8cJCQkqGXLltq6davq16+vkydPKjc316vNz8c53Pu8Y8cOLVmyRKNGjSqxXWUc68I6S3oe169fX/v27fOaf+rUKR08eDDsHwOFYWjHjh368MMPvY4OFadbt246deqUtm/fLil8+/1zTZs2Vd26db0e15V1vCXpk08+0aZNm0p9vkvhM95ne8/y1+v32drExcWd03+aK20gioqKUufOnfXRRx95phUUFOijjz5S9+7dg1hZ2ZmZ7rrrLr3zzjtaunRpkUOjxVm3bp0kKTk5WZLUvXt3ff31114vKIUvtG3atKmQuv3tyJEj2rZtm5KTk9W5c2dVrVrVa5w3bdqknTt3esY53Ps8d+5c1atXT4MHDy6xXWUc6yZNmqh+/fpe45uXl6dVq1Z5jW9ubq6ysrI8bZYuXaqCggJPSOzevbtWrFihn376ydPmww8/VKtWrUL245PCMLRlyxYtWbJEderUKXWZdevWKSIiwvORUjj2+0z//e9/deDAAa/HdWUc70J/+ctf1LlzZ3Xs2LHUtqE+3qW9Z/nr9bt79+5e6yhsc87v9ed+nnj4WLBggUVHR9vLL79s33zzjf3ud7+zhIQEr7PVw8kdd9xh8fHxtnz5cq+vXR47dszMzLZu3Wq///3v7csvv7Ts7GxbuHChNW3a1Hr16uVZR+FXGPv372/r1q2zxYsXW2JiYsh9FfvnJkyYYMuXL7fs7Gz797//bWlpaVa3bl3bt2+fmZ3+2mbDhg1t6dKl9uWXX1r37t2te/funuXDsc+F8vPzrWHDhnb//fd7Ta9MY3348GFbu3atrV271iTZ1KlTbe3atZ5vUz3xxBOWkJBgCxcutPXr19uVV15Z7NfuL7jgAlu1apV9+umn1qJFC6+vYefm5lpSUpLdfPPNtmHDBluwYIHFxsYG9WvYJfX75MmTdsUVV1iDBg1s3bp1Xs/3wm/WfPbZZ/bMM8/YunXrbNu2bTZ//nxLTEy0YcOGebYRbv0+fPiwTZw40VauXGnZ2dm2ZMkSu/DCC61FixZ2/Phxzzoq23gXcrvdFhsbazNnziyyfDiOd2nvWWb+ef0u/Nr9vffea//5z39s+vTpfO2+OM8//7w1bNjQoqKirGvXrvb5558Hu6Qyk1Tsbe7cuWZmtnPnTuvVq5fVrl3boqOjrXnz5nbvvfd6XZvGzGz79u02cOBAi4mJsbp169qECRPsp59+CkKPfHP99ddbcnKyRUVF2XnnnWfXX3+9bd261TP/xx9/tDvvvNNq1aplsbGxdvXVV1tOTo7XOsKtz4U++OADk2SbNm3yml6ZxnrZsmXFPq6HDx9uZqe/ej958mRLSkqy6Oho69evX5H9ceDAAbvxxhutRo0aFhcXZyNHjrTDhw97tfnqq6/skksusejoaDvvvPPsiSeeCFQXi1VSv7Ozs8/6fC+8DlVWVpZ169bN4uPjrVq1ata6dWt7/PHHvYKDWXj1+9ixY9a/f39LTEy0qlWrWqNGjezWW28t8p/YyjbehWbNmmUxMTGWm5tbZPlwHO/S3rPM/Pf6vWzZMuvUqZNFRUVZ06ZNvbbhK9f/LxoAAMCxKu05RAAAAL4iEAEAAMcjEAEAAMcjEAEAAMcjEAEAAMcjEAEAAMcjEAEAAMcjEAEOsnz5crlcriK/HYRzN3nyZK8f2PW3H374QfXq1dN///vfCtsGgP/hwoxAJdWnTx916tRJzz77rGfayZMndfDgQSUlJcnlcgWlruXLl6tv3746dOiQEhISglJDee3Zs0ctW7bU119/rUaNGlXYdiZOnKhDhw7pL3/5S4VtA8BpHCECHCQqKkr169cPWhiqLF588UVdfPHFFRqGJGnkyJF69dVXdfDgwQrdDgACEVApjRgxQh9//LGee+45uVwuuVwubd++vchHZi+//LISEhL03nvvqVWrVoqNjdW1116rY8eOad68eWrcuLFq1aqlMWPGKD8/37P+EydOaOLEiTrvvPNUvXp1devWTcuXL/fM37Fjh4YMGaJatWqpevXqatu2rd5//31t375dffv2lSTVqlVLLpdLI0aMkCQtXrxYl1xyiRISElSnTh1dfvnl2rZtm2ed27dvl8vl0htvvKGePXsqJiZGF110kTZv3qwvvvhCXbp0UY0aNTRw4EDt37/fa19cddVVysjIUGJiouLi4nT77bfr5MmTnjZvvvmm2rdvr5iYGNWpU0dpaWk6evToWffvggULNGTIEK9pffr00d13361x48apVq1aSkpK0pw5c3T06FGNHDlSNWvWVPPmzbVo0SLPMocOHdLQoUOVmJiomJgYtWjRQnPnzvXMb9u2rVJSUvTOO+/4MOoAyuWcf/0MQMjLzc217t2726233ur5helTp055fmDy0KFDZmY2d+5cq1q1qv3yl7+0NWvW2Mcff2x16tSx/v3723XXXWcbN260//u//7OoqChbsGCBZ/2jRo2yiy++2FasWGFbt261p59+2qKjo23z5s1mZjZ48GD75S9/aevXr7dt27bZ//3f/9nHH39sp06dsrfeesvzg7U5OTmeH7J888037a233rItW7bY2rVrbciQIda+fXvLz883M/P84On5559vixcvtm+++cZ+8YtfWOfOna1Pnz726aef2po1a6x58+Z2++23e2odPny41ahRw66//nrbsGGDvffee5aYmGgPPvigmZnt3r3bqlSpYlOnTrXs7Gxbv369TZ8+vciPhRY6cOCAuVyuIj8U3bt3b6tZs6Y9+uijtnnzZnv00UctMjLSBg4caLNnz7bNmzfbHXfcYXXq1LGjR4+amdno0aOtU6dO9sUXX1h2drZ9+OGH9o9//MNrvddff73XD4ACqBgEIqCS6t27t40dO9ZrWnGBSJJt3brV0+a2226z2NhYr0AwYMAAu+2228zMbMeOHRYZGWnff/+917r79etnkyZNMjOz9u3b25QpU4qt68wazmb//v0myb7++msz+18gevHFFz1tXn/9dZNkH330kWdaZmamtWrVyvP38OHDrXbt2p4QYmY2c+ZMq1GjhuXn51tWVpZJsu3bt5dYT6G1a9eaJNu5c6fX9N69e9sll1zi+fvUqVNWvXp1u/nmmz3TcnJyTJKtXLnSzMyGDBliI0eOLHF799xzj/Xp08en2gCUHR+ZAQ4XGxurZs2aef5OSkpS48aNVaNGDa9p+/btkyR9/fXXys/PV8uWLVWjRg3P7eOPP/Z8xDVmzBg99thj6tGjh9LT07V+/fpS69iyZYtuvPFGNW3aVHFxcWrcuLEkaefOnV7tOnTo4FWXJLVv377YWgt17NhRsbGxnr+7d++uI0eOaNeuXerYsaP69eun9u3b69e//rXmzJmjQ4cOnbXOH3/8UZJUrVq1IvN+XltkZKTq1KlTpDZJnvruuOMOLViwQJ06ddJ9992nzz77rMg6Y2JidOzYsbPWA8A/CESAw1WtWtXrb5fLVey0goICSdKRI0cUGRmprKwsrVu3znP7z3/+o+eee06SNGrUKH333Xe6+eab9fXXX6tLly56/vnnS6xjyJAhOnjwoObMmaNVq1Zp1apVkuR1rs+Z9RaeHH7mtMJafREZGakPP/xQixYtUps2bfT888+rVatWys7OLrZ93bp1JanY0FTaviyst7C+gQMHaseOHbrnnnu0e/du9evXTxMnTvRax8GDB5WYmOhzfwCUDYEIqKSioqK8ToT2lwsuuED5+fnat2+fmjdv7nWrX7++p11qaqpuv/12vf3225owYYLmzJnjqUuSV20HDhzQpk2b9PDDD6tfv35q3bp1iUdpztVXX33lObIjSZ9//rlq1Kih1NRUSaeDSo8ePZSRkaG1a9cqKirqrCcyN2vWTHFxcfrmm2/8UltiYqKGDx+u+fPn69lnn9Xs2bO95m/YsEEXXHCBX7YF4OwIREAl1bhxY61atUrbt2/XDz/8cE5HTUrSsmVLDR06VMOGDdPbb7+t7OxsrV69WpmZmfrnP/8pSRo3bpw++OADZWdna82aNVq2bJlat24tSWrUqJFcLpfee+897d+/X0eOHFGtWrVUp04dzZ49W1u3btXSpUs1fvx4v9QrnT7K9Nvf/lbffPON3n//faWnp+uuu+5SRESEVq1apccff1xffvmldu7cqbffflv79+/31HumiIgIpaWl6dNPPy13XY888ogWLlyorVu3auPGjXrvvfe8tnvs2DFlZWWpf//+5d4WgJIRiIBKauLEiYqMjFSbNm2UmJhY5Fyc8pg7d66GDRumCRMmqFWrVrrqqqv0xRdfqGHDhpJOH/0ZPXq0Wrdurcsuu0wtW7bUjBkzJEnnnXeeMjIy9MADDygpKckTTBYsWKCsrCy1a9dO99xzj55++mm/1duvXz+1aNFCvXr10vXXX68rrrhCU6ZMkSTFxcVpxYoVGjRokFq2bKmHH35Yf/rTnzRw4MCzrm/UqFFasGBBuUNmVFSUJk2apA4dOqhXr16KjIzUggULPPMXLlyohg0bqmfPnuXaDoDScaVqAJXaiBEjlJubq3fffddv6zQzdevWTffcc49uvPFGv633TL/4xS80ZswY3XTTTRW2DQCncYQIAM6Ry+XS7NmzderUqQrbxg8//KBrrrmmQgMXgP/hCBGASq0ijhABqHwIRAAAwPH4yAwAADgegQgAADgegQgAADgegQgAADgegQgAADgegQgAADgegQgAADgegQgAADgegQgAADje/wMnhqkGxbAuNAAAAABJRU5ErkJggg==", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from bmtk.simulator import bionet\n", "from bmtk.analyzer.spike_trains import plot_raster, to_dataframe\n", "\n", "bionet.reset()\n", "conf = bionet.Config.from_json('config.csv_spikes.json')\n", "conf.build_env()\n", "\n", "net = bionet.BioNetwork.from_config(conf)\n", "sim = bionet.BioSimulator.from_config(conf, network=net)\n", "sim.run()\n", "\n", "_ = plot_raster(config_file='config.csv_spikes.json')" ] }, { "cell_type": "markdown", "id": "76baf2be-28b2-4944-981b-d7e12fad5578", "metadata": {}, "source": [ "## 2. Example: Dynamically generating custom spike-trains " ] }, { "cell_type": "markdown", "id": "6e1860a4-4702-4e6c-b839-5d4372acd95b", "metadata": {}, "source": [ "Pregenerating spike trains for your simulations inside an hdf5 or CSV file is computationally efficient and makes your results more accessible to reproduce and share. However, at times, it may be beneficial for users to generate spike trains dynamically during each simulation. If you are doing quick simulations and spot-checks, it can be cumbersome having to regenerate a file beforehand. Or if a user is running thousands of simulations or doing some kind of gradient search, the cost of potentially creating thousands of spike files beforehand may not be reasonable.\n", "\n", "BMTK also allows modelers to create their own special function, which will generate new spike trains at the start of each simulation. To do so, you only need to make changes to the configuration for a \"spikes\" input so that the **module** is set to value `function`, and instead of spikes_input, you specify a **spikes_function** parameter that will be the name of your custom function.\n", "\n", "```json\n", "\"inputs\": {\n", " \"LGN_spikes_sonata\": {\n", " \"input_type\": \"spikes\",\n", " \"module\": \"function\",\n", " \"spikes_function\": \"my_spikes_generator\",\n", " \"node_set\": \"LGN\"\n", " }\n", "}\n", "```" ] }, { "cell_type": "markdown", "id": "2a677788-8993-4612-b595-51c4bff5ba30", "metadata": {}, "source": [ "For BMTK to know where to find the `my_spikes_generator`, you must then use the `@spikes_generator` at the top of a given function in your run_bmtk.py script (or any python file imported into the run script). In the below example, we use the following to return spike trains for every cell in the `LGN` node_set to fire at a constant rate (although different rates for different models)." ] }, { "cell_type": "code", "execution_count": 7, "id": "8014e00c-b6b8-42c9-a37b-13df612ff431", "metadata": {}, "outputs": [], "source": [ "from bmtk.simulator.bionet.io_tools import io\n", "from bmtk.simulator.bionet import spikes_generator\n", "import numpy as np\n", "\n", "@spikes_generator\n", "def my_spikes_generator(node, sim):\n", " io.log_info(f'Generating custom spike trains for node {node.node_id} from {node.population_name}')\n", " if node['pop_name'] == 'tON':\n", " return np.arange(100.0, sim.tstop, step=sim.dt*10)\n", " elif node['pop_name'] == 'tOFF':\n", " return np.arange(100.0, sim.tstop, step=sim.dt*20)\n", " else:\n", " return []\n" ] }, { "cell_type": "markdown", "id": "07f07bf1-fc89-46cb-b23f-35fe33c0a041", "metadata": {}, "source": [ "* All `spikes_generator` functions must have parameters `node` and `sim`.\n", " * `node` allows you to access information about each node/cell like a dictionary.\n", " * `sim` is a class containing information about a current simulation, including information like start time (`sim.tstart`), stop_time (`sim.tstop`), step size (`sim.dt`), among other properties.\n", "* The `spikes_generator` should return either a list or array of timestamps, in milliseconds, for each node.\n", "* We include a logging statement for good measure. This is not required, but it is good for debugging and checking that our custom function is being called.\n", "\n", "When the simulation is running, the `my_spikes_generator` function will be called once for each node in the specified **node_set**. " ] }, { "cell_type": "code", "execution_count": 8, "id": "36732033-c4f4-4c36-994c-b2ec5ef44c86", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2024-10-24 00:02:59,673 [INFO] Created log file\n", "Mechanisms already loaded from path: ./components/mechanisms. Aborting.\n", "2024-10-24 00:02:59,707 [INFO] Building cells.\n", "2024-10-24 00:03:06,517 [INFO] Building recurrent connections\n", "2024-10-24 00:03:06,532 [INFO] Building virtual cell stimulations for LGN_spikes_sonata\n", "2024-10-24 00:03:06,545 [INFO] Generating custom spike trains for 0 from LGN\n", "2024-10-24 00:03:06,549 [INFO] Generating custom spike trains for 28 from LGN\n", "2024-10-24 00:03:06,550 [INFO] Generating custom spike trains for 27 from LGN\n", "2024-10-24 00:03:06,551 [INFO] Generating custom spike trains for 14 from LGN\n", "2024-10-24 00:03:06,552 [INFO] Generating custom spike trains for 2 from LGN\n", "2024-10-24 00:03:06,553 [INFO] Generating custom spike trains for 38 from LGN\n", "2024-10-24 00:03:06,554 [INFO] Generating custom spike trains for 26 from LGN\n", "2024-10-24 00:03:06,555 [INFO] Generating custom spike trains for 15 from LGN\n", "2024-10-24 00:03:06,556 [INFO] Generating custom spike trains for 25 from LGN\n", "2024-10-24 00:03:06,557 [INFO] Generating custom spike trains for 16 from LGN\n", "2024-10-24 00:03:06,558 [INFO] Generating custom spike trains for 24 from LGN\n", "2024-10-24 00:03:06,568 [INFO] Generating custom spike trains for 17 from LGN\n", "2024-10-24 00:03:06,572 [INFO] Generating custom spike trains for 1 from LGN\n", "2024-10-24 00:03:06,573 [INFO] Generating custom spike trains for 39 from LGN\n", "2024-10-24 00:03:06,577 [INFO] Generating custom spike trains for 23 from LGN\n", "2024-10-24 00:03:06,578 [INFO] Generating custom spike trains for 18 from LGN\n", "2024-10-24 00:03:06,580 [INFO] Generating custom spike trains for 12 from LGN\n", "2024-10-24 00:03:06,581 [INFO] Generating custom spike trains for 22 from LGN\n", "2024-10-24 00:03:06,582 [INFO] Generating custom spike trains for 29 from LGN\n", "2024-10-24 00:03:06,583 [INFO] Generating custom spike trains for 11 from LGN\n", "2024-10-24 00:03:06,584 [INFO] Generating custom spike trains for 5 from LGN\n", "2024-10-24 00:03:06,585 [INFO] Generating custom spike trains for 35 from LGN\n", "2024-10-24 00:03:06,586 [INFO] Generating custom spike trains for 6 from LGN\n", "2024-10-24 00:03:06,587 [INFO] Generating custom spike trains for 36 from LGN\n", "2024-10-24 00:03:06,588 [INFO] Generating custom spike trains for 34 from LGN\n", "2024-10-24 00:03:06,589 [INFO] Generating custom spike trains for 7 from LGN\n", "2024-10-24 00:03:06,590 [INFO] Generating custom spike trains for 4 from LGN\n", "2024-10-24 00:03:06,591 [INFO] Generating custom spike trains for 33 from LGN\n", "2024-10-24 00:03:06,592 [INFO] Generating custom spike trains for 8 from LGN\n", "2024-10-24 00:03:06,593 [INFO] Generating custom spike trains for 32 from LGN\n", "2024-10-24 00:03:06,594 [INFO] Generating custom spike trains for 9 from LGN\n", "2024-10-24 00:03:06,595 [INFO] Generating custom spike trains for 37 from LGN\n", "2024-10-24 00:03:06,596 [INFO] Generating custom spike trains for 31 from LGN\n", "2024-10-24 00:03:06,597 [INFO] Generating custom spike trains for 10 from LGN\n", "2024-10-24 00:03:06,598 [INFO] Generating custom spike trains for 30 from LGN\n", "2024-10-24 00:03:06,599 [INFO] Generating custom spike trains for 3 from LGN\n", "2024-10-24 00:03:06,599 [INFO] Generating custom spike trains for 19 from LGN\n", "2024-10-24 00:03:06,601 [INFO] Generating custom spike trains for 13 from LGN\n", "2024-10-24 00:03:06,602 [INFO] Generating custom spike trains for 21 from LGN\n", "2024-10-24 00:03:06,602 [INFO] Generating custom spike trains for 20 from LGN\n", "2024-10-24 00:03:07,466 [INFO] Running simulation for 2000.000 ms with the time step 0.100 ms\n", "2024-10-24 00:03:07,466 [INFO] Starting timestep: 0 at t_sim: 0.000 ms\n", "2024-10-24 00:03:07,467 [INFO] Block save every 5000 steps\n", "2024-10-24 00:03:17,745 [INFO] step:5000 t_sim:500.00 ms\n", "2024-10-24 00:03:28,232 [INFO] step:10000 t_sim:1000.00 ms\n", "2024-10-24 00:03:38,876 [INFO] step:15000 t_sim:1500.00 ms\n", "2024-10-24 00:03:49,440 [INFO] step:20000 t_sim:2000.00 ms\n", "2024-10-24 00:03:49,465 [INFO] Simulation completed in 42.0 seconds \n" ] } ], "source": [ "from bmtk.simulator import bionet\n", "\n", "bionet.reset()\n", "conf = bionet.Config.from_json('config.spikes_generator.json')\n", "conf.build_env()\n", "\n", "net = bionet.BioNetwork.from_config(conf)\n", "sim = bionet.BioSimulator.from_config(conf, network=net)\n", "sim.run()" ] }, { "cell_type": "markdown", "id": "ce4e0aca-0600-4b82-87f0-151f168e2de9", "metadata": {}, "source": [ "## 3. Example: Incorporating real data from NWB files " ] }, { "cell_type": "markdown", "id": "7a0a55bc-a592-4778-9f6d-0862da876721", "metadata": {}, "source": [ "You can use tools like FilterNet or PoissonSpikeGenerator to create theoretical-to-realistic synaptic stimuli onto a network from various modes. But better yet, when actual experimental data is available, it is often possible to use just that. Especially as more and more experimental electrophysiological data sets are being made publicly available through resources like [DANDI](https://dandiarchive.org/) or [The Allen Brain Observatory](https://portal.brain-map.org/circuits-behavior/visual-coding-neuropixels), we will want not only to use such data as a base-line for validating our models and comparing them to experiments, but also to use the data within specific simulations. For example, when modeling a network of one population and/or region, we will want to use recordings of surrounding cells to help excite and inhibit our cells more realistically.\n", "\n", "Traditionally a major issue with encorporating experimental electrophysiology data into simulations is trying to parse the wide variety of different ways the data was stored. Luckily, the [Neurodata Without Borders (NWB)](https://www.nwb.org/) has developed a format for storing experimental data, which has seen a substantial amount of adoption in the field. BMTK can take these files and automatically insert them into simulations.\n", "\n", "In this example, we will take the previous model of the Mouse Primary Visual Cortex and add inputs that we know come from higher cortical regions (in this case, just the VisL and subcortical regions) along with the input from the LGN. For these added regions, we will use actual Neuropixels recordings of activity from these regions during presentation of drifting gratings." ] }, { "cell_type": "markdown", "id": "fd7df1db-fa11-45e9-ba96-f803a2e7d210", "metadata": {}, "source": [ "### Step 1: Download the data" ] }, { "cell_type": "markdown", "id": "d183688f-c1fd-477d-ad34-cb91106b0b9b", "metadata": {}, "source": [ "The first step is to find experimental NWB that includes spiking events. For our example, we will use data from [Allen Institute Visual Coding dataset](https://observatory.brain-map.org/visualcoding/) downloaded using the AllenSDK. We will get three experimental sessions that we know contain recordings of the VisL and hippocampus." ] }, { "cell_type": "code", "execution_count": 1, "id": "7f79d70f-b028-4e17-8991-26f54ae130db", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "WARNING:root:downloading a 2723.916MiB file from http://api.brain-map.org//api/v2/well_known_file_download/1026124469\n" ] }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "d5560d86f71246e2902164419c8fd3ff", "version_major": 2, "version_minor": 0 }, "text/plain": [ "Downloading: 0%| | 0.00/2.86G [00:00" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from allensdk.brain_observatory.ecephys.ecephys_project_cache import EcephysProjectCache\n", "\n", "cache = EcephysProjectCache.from_warehouse(\n", " manifest='./ecephys_cache_dir/neuropixels.manifest.json'\n", ")\n", "cache.get_session_data(715093703)\n", "cache.get_session_data(798911424)\n", "cache.get_session_data(754829445)" ] }, { "cell_type": "markdown", "id": "7dc957f1-abf5-4f0e-8304-89f207db88e4", "metadata": {}, "source": [ "By default, the NWB files will be downloaded into the *ecephys_cache_dir*. Since nwb files are essentially just structured HDF5 files, you can use tools like [HDFView](https://www.hdfgroup.org/downloads/hdfview/) or [h5py](https://www.h5py.org/) to read them once they have been downloaded. " ] }, { "cell_type": "markdown", "id": "f99daefa-2859-491c-8226-2edc181e8afd", "metadata": {}, "source": [ "### Step 2: Connecting VISL and sub-cortical area onto our V1 cells." ] }, { "cell_type": "markdown", "id": "1ba9ede7-b667-4038-ba9a-3f46076e8a1e", "metadata": {}, "source": [ "To simulate synaptic stimulation from the VisL and Hippocampal cell recordings onto our V1 model, we will need to create a population of virtual cells representing the new cells and synapses. Unfortunately, the electrophysiology data doesn't include information about network geometry, so it is up to the modeler to decide how to connect the experimental data to our network.\n", "\n", "As we did before, we will separate node populations called 'VISl' and 'Hippocampus' and use the NetworkBuilder to create feedforward synaptic connections.\n", "\n", "```python\n", "visl = NetworkBuilder('VISl')\n", "visl.add_nodes(\n", " N=n_visl_units,\n", " model_type='virtual',\n", " ...\n", ")\n", "visl.add_edges(\n", " source=visal.nodes(),\n", " target=visp.nodes(ei='e'), \n", " connection_rule=connection_rule_e2e,\n", " dynamics_params='AMPA_ExcToExc.json',\n", " model_template='Exp2Syn',\n", " ...\n", ")\n", "\n", "```\n", "\n", "See the *./build_network.nwb_inputs.py* for the full script that builds the SONATA network found in *./network_nwb_inputs/*" ] }, { "cell_type": "markdown", "id": "d0d7297f-d370-44c4-aa80-eb111367c040", "metadata": {}, "source": [ "### Step 3: Updating the configuration file to include NWB data." ] }, { "cell_type": "markdown", "id": "3598b866-32db-4f70-974d-fe7d59abe2e7", "metadata": {}, "source": [ "Before we can run the simulation, we must update the SONATA configuration file so that the simulation:\n", "1. Knows which .nwb files to fetch spiking data from.\n", "2. Knows how to map cells (e.g., NWB units) from our experimental data to cells (e.g., SONATA nodes) in our 'VISl' and 'hippocampus' populations.\n", "3. Know which time interval in the experimental data to use in our simulation.\n", "\n", "The most straightforward way of doing this is to add the following to our configuration file (*config.nwb_inputs.json*) in the \"inputs\" section:\n", "\n", "```json\n", "\"inputs\": {\n", " \"hippo_spikes\": {\n", " \"input_type\": \"spikes\",\n", " \"module\": \"ecephys_probe\",\n", " \"node_set\": \"hippocampus\",\n", " \"input_file\": \"./ecephys_cache_dir/session_715093703/session_715093703.nwb\",\n", " \"units\": {\n", " \"location\": [\"CA1\", \"CA3\", \"Po\"]\n", " }\n", " \"mapping\": \"sample\",\n", " \"interval\": {\n", " \"interval_name\": \"drifting_gratings\",\n", " \"temporal_frequency\": 4.0,\n", " \"orientation\": 90\n", " }\n", "\n", " },\n", " \"visl_spikes\": {\n", " \"input_type\": \"spikes\",\n", " \"module\": \"ecephys_probe\",\n", " \"node_set\": \"VISl\",\n", " \"input_file\": \"./ecephys_cache_dir/session_715093703/session_715093703.nwb\",\n", " \"mapping\": \"sample\",\n", " \"units\": {\n", " \"location\": \"VISl\",\n", " }\n", " \"interval\": {\n", " \"interval_name\": \"drifting_gratings\",\n", " \"temporal_frequency\": 4.0,\n", " \"orientation\": 90\n", " },\n", " }\n", "}\n", "```\n", "* When importing extracellular electrophysiology NWB files into your simulation, the **input_type** and **module** will always be set to `spikes` and `ecephys_probe`, respectively.\n", "* The **node_set** is the subset of cells in our network used as virtual cells that generate spikes.\n", "* The **input_file** in the name of the nwb file(s) to use for spikes. To use data from multiple sessions, just use a list of files:\n", "```json\n", " \"input_file\": [\n", " \"./ecephys_cache_dir/session_715093703/session_715093703.nwb\",\n", " \"./ecephys_cache_dir/session_798911424/session_798911424.nwb\",\n", " \"./ecephys_cache_dir/session_754829445/session_754829445.nwb\"\n", " ]\n", "```\n", "* The **units** field tells us which units from the nwb file to take their spiking data from based on specific keywords and/or unit-id. In the Neuropixels NWB files, each unit has a field called \"location\" to determine which region the data came from, which we can use here to tell that our model's \"hippocampus\" cells use any data coming from either the CA1, CA3 or Po regions.\n", "* **mapping** tells how to map NWB **units** -> SONATA **node_set**. Setting the value to `sample` will result in a random mapping without replacement. You can also use option `sample_with_replacement`, which is useful if your model has more nodes than units in your data. Or if you have a specific mapping from NWB unit_ids to SONATA node_ids, you can use option `units_map` (in which case **units** will point to a CSV file).\n", "* **interval** tells the simulation which time interval to fetch spikes from. Inside the NWB file, there is a stimulus table that marks the stimuli at any given epoch. We use this table to get only spikes recorded in which a \"drifting grating\" stimulus was present with a given orientation and frequency. You can also use the following option if you know the specific time.\n", "\n", "```json\n", " \"interval\": [\"start_time_ms\", \"end_time_ms\"]\n", "```" ] }, { "cell_type": "markdown", "id": "ef2aadb1-2d31-4d26-8574-591229cd570c", "metadata": {}, "source": [ "And finally, we are ready to run our simulation." ] }, { "cell_type": "code", "execution_count": 1, "id": "f77bfceb-64f0-4cd1-91a8-83aac4acfc83", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "Warning: no DISPLAY environment variable.\n", "--No graphics will be displayed.\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "2024-10-24 01:15:34,915 [INFO] Created log file\n", "2024-10-24 01:15:35,070 [INFO] Building cells.\n", "2024-10-24 01:15:41,349 [INFO] Building recurrent connections\n", "2024-10-24 01:15:41,362 [INFO] Building virtual cell stimulations for LGN_spikes_sonata\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "/opt/conda/lib/python3.12/site-packages/hdmf/spec/namespace.py:535: UserWarning: Ignoring cached namespace 'hdmf-common' version 1.1.3 because version 1.8.0 is already loaded.\n", " warn(\"Ignoring cached namespace '%s' version %s because version %s is already loaded.\"\n", "/opt/conda/lib/python3.12/site-packages/hdmf/spec/namespace.py:535: UserWarning: Ignoring cached namespace 'core' version 2.2.2 because version 2.7.0 is already loaded.\n", " warn(\"Ignoring cached namespace '%s' version %s because version %s is already loaded.\"\n", "/opt/conda/lib/python3.12/site-packages/hdmf/spec/namespace.py:535: UserWarning: Ignoring cached namespace 'hdmf-common' version 1.1.3 because version 1.8.0 is already loaded.\n", " warn(\"Ignoring cached namespace '%s' version %s because version %s is already loaded.\"\n", "/opt/conda/lib/python3.12/site-packages/hdmf/spec/namespace.py:535: UserWarning: Ignoring cached namespace 'core' version 2.2.2 because version 2.7.0 is already loaded.\n", " warn(\"Ignoring cached namespace '%s' version %s because version %s is already loaded.\"\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "2024-10-24 01:15:45,144 [INFO] Building virtual cell stimulations for VISl_spikes_nwb\n", "2024-10-24 01:15:48,042 [INFO] Building virtual cell stimulations for Hipp_spikes_nwb\n", "2024-10-24 01:15:49,677 [INFO] Running simulation for 2000.000 ms with the time step 0.100 ms\n", "2024-10-24 01:15:49,678 [INFO] Starting timestep: 0 at t_sim: 0.000 ms\n", "2024-10-24 01:15:49,679 [INFO] Block save every 5000 steps\n", "2024-10-24 01:16:09,188 [INFO] step:5000 t_sim:500.00 ms\n", "2024-10-24 01:16:28,971 [INFO] step:10000 t_sim:1000.00 ms\n", "2024-10-24 01:16:48,778 [INFO] step:15000 t_sim:1500.00 ms\n", "2024-10-24 01:17:08,752 [INFO] step:20000 t_sim:2000.00 ms\n", "2024-10-24 01:17:08,814 [INFO] Simulation completed in 79.14 seconds \n" ] } ], "source": [ "from bmtk.simulator import bionet\n", "\n", "bionet.reset()\n", "conf = bionet.Config.from_json('config.nwb_inputs.json')\n", "conf.build_env()\n", "\n", "net = bionet.BioNetwork.from_config(conf)\n", "sim = bionet.BioSimulator.from_config(conf, network=net)\n", "sim.run()" ] }, { "cell_type": "markdown", "id": "448dfd35-f226-471c-98e5-929d5bc71571", "metadata": {}, "source": [ "## 4. Example: Forcing spontaneous synaptic activity within a network " ] }, { "cell_type": "markdown", "id": "5b18e4ca-aba8-4f41-ab52-8e19bfebf6c4", "metadata": {}, "source": [ "So far, in this tutorial, we've focused on generating stimuli using synaptic inputs from outside our main modeled network. In other tutorials, we have used different types of input to drive a simulation, including current-clamps, voltage-clamps, and extracellular stimulation. While these can generate the kinds of stimuli we might see in experiments and living brains, they tend not to be very granular, especially when we want to study the secondary effects of activity within a network.\n", "\n", "One option that BMTK offers for having more granular control of internal network activity is forcing certain synapses to spontaneously fire at pre-determined times. This cannot only give us more control of network dynamics, which would be much harder to achieve using current clamps or feedforward spike trains, but it also lets us isolate external activity from recurrent activity." ] }, { "cell_type": "markdown", "id": "463087a0-380e-459a-9abb-d70d659e94b2", "metadata": {}, "source": [ "In BMTK, this is done by adding a new input type to the \"inputs\" section of the SONATA config with **input_type** and **module** called `syn_activity`. At the minimum, we must define the pre-synaptic cells that will spontaneously fire and a list of firing times:\n", "\n", "```json\n", "\"syn_activity\": {\n", " \"input_type\": \"syn_activity\",\n", " \"module\": \"syn_activity\",\n", " \"precell_filter\": {\n", " \"population\": \"VISp\",\n", " \"ei\": \"e\"\n", " },\n", " \"timestamps\": [500.0, 1000.0, 1500.0, 2000.0, 2500.0, 3000.0, 3500.0]\n", "}\n", "```\n", "* **precell_filter** determines the synapses to activate based on the presynaptic/source cell spontaneously. In this case we tell BMTK spontaneous activity to apply to synapses with a source-cell that has attributes `population==VISp` and `ei==e`. If you know exactly which cells you want to use, you can filter by `node_id`:\n", "```json\n", " \"node_id\": [0, 1, 2, 3],\n", "```\n", "* **timestamps** is a list of timestamps, in milliseconds, to activate the neuron following startup. If you have too many timestamps to add to the JSON directly, you can also pass in a string path to a txt file where each line is a timestamp.\n", "\n", "\n", "In the above example, all the synapses with VISp excitatory pre-synaptic connections will fire at the given timestamp. For further granular control, you can all set the **postcell_filter** too for filtering out synapses based on post-synaptic cells. For example, if you want spontaneous firing in exc -> inh connections (the above example would also include exc -> exc synapses:\n", "\n", "```json\n", "\"syn_activity\": {\n", " \"input_type\": \"syn_activity\",\n", " \"module\": \"syn_activity\",\n", " \"precell_filter\": {\n", " \"population\": \"VISp\",\n", " \"ei\": \"e\"\n", " },\n", " \"postcell_filter\": {\n", " \"population\": \"VISp\",\n", " \"ei\": \"i\"\n", " },\n", " \"timestamps\": [500.0, 1000.0, 1500.0, 2000.0, 2500.0, 3000.0, 3500.0]\n", "}\n", "```\n", "\n" ] }, { "cell_type": "code", "execution_count": 11, "id": "957112fc-f8ae-4841-95dd-0a0bd81be884", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2024-10-24 00:05:52,474 [INFO] Created log file\n", "Mechanisms already loaded from path: ./components/mechanisms. Aborting.\n", "2024-10-24 00:05:52,522 [INFO] Building cells.\n", "2024-10-24 00:06:09,970 [INFO] Building recurrent connections\n", "2024-10-24 00:06:11,573 [INFO] Running simulation for 2000.000 ms with the time step 0.100 ms\n", "2024-10-24 00:06:11,574 [INFO] Starting timestep: 0 at t_sim: 0.000 ms\n", "2024-10-24 00:06:11,574 [INFO] Block save every 5000 steps\n", "2024-10-24 00:06:49,734 [INFO] step:5000 t_sim:500.00 ms\n", "2024-10-24 00:07:28,517 [INFO] step:10000 t_sim:1000.00 ms\n", "2024-10-24 00:08:07,476 [INFO] step:15000 t_sim:1500.00 ms\n", "2024-10-24 00:08:46,555 [INFO] step:20000 t_sim:2000.00 ms\n", "2024-10-24 00:08:46,576 [INFO] Simulation completed in 2.0 minutes, 35.0 seconds \n" ] } ], "source": [ "from bmtk.simulator import bionet\n", "\n", "bionet.reset()\n", "conf = bionet.Config.from_json('config.spont_syns.json')\n", "conf.build_env()\n", "\n", "net = bionet.BioNetwork.from_config(conf)\n", "sim = bionet.BioSimulator.from_config(conf, network=net)\n", "sim.run()" ] }, { "cell_type": "code", "execution_count": null, "id": "efdd66b3-53a0-479b-bbc4-af03a704028a", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "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.10.16" } }, "nbformat": 4, "nbformat_minor": 5 }