{ "cells": [ { "cell_type": "markdown", "id": "b1331599", "metadata": { "tags": [] }, "source": [ "# Down-scaled multi-area model" ] }, { "cell_type": "markdown", "id": "edec8345-aec1-419e-b9e3-7f612aff8262", "metadata": {}, "source": [ "<img src=\"model_construction.png\" alt=\"Model overview\" width=\"1000\"/>" ] }, { "cell_type": "markdown", "id": "f4a649cc-3b68-49e4-b2b6-6f29f13a6d9c", "metadata": {}, "source": [ "The code in this notebook implements the down-scaled version of spiking network model of macaque visual cortex developed at the Institute of Neuroscience and Medicine (INM-6), Research Center Jülich. The full-scale model has been documented in the following publications:\n", "\n", "1. Schmidt M, Bakker R, Hilgetag CC, Diesmann M & van Albada SJ\n", " Multi-scale account of the network structure of macaque visual cortex\n", " Brain Structure and Function (2018), 223: 1409 [https://doi.org/10.1007/s00429-017-1554-4](https://doi.org/10.1007/s00429-017-1554-4)\n", "\n", "2. Schuecker J, Schmidt M, van Albada SJ, Diesmann M & Helias M (2017)\n", " Fundamental Activity Constraints Lead to Specific Interpretations of the Connectome.\n", " PLOS Computational Biology, 13(2): e1005179. [https://doi.org/10.1371/journal.pcbi.1005179](https://doi.org/10.1371/journal.pcbi.1005179)\n", "\n", "3. Schmidt M, Bakker R, Shen K, Bezgin B, Diesmann M & van Albada SJ (2018)\n", " A multi-scale layer-resolved spiking network model of\n", " resting-state dynamics in macaque cortex. PLOS Computational Biology, 14(9): e1006359. [https://doi.org/10.1371/journal.pcbi.1006359](https://doi.org/10.1371/journal.pcbi.1006359)\n", "<br>" ] }, { "cell_type": "markdown", "id": "b952d0ea", "metadata": { "tags": [] }, "source": [ "#### Notebook structure <a class=\"anchor\" id=\"toc\"></a>\n", "* [S0. Configuration](#section_0)\n", "* [S1. Parameterization](#section_1)\n", " * [1.1. Parameters to tune](#section_1_1)\n", " * [1.2. Default parameters](#section_1_2)\n", "* [S2. Multi-Area Model Instantiation and Simulation](#section_2)\n", " * [2.1. Instantiate a multi-area model](#section_2_1)\n", " * [2.2. Predict firing rates from theory](#section_2_2)\n", " * [2.3. Extract and visualize interareal connectivity](#section_2_3)\n", " * [2.4. Run a simulation](#section_2_4)\n", "* [S3. Simulation Results Visualization](#section_3) \n", " * [3.1. Instantaneous and mean firing rate across all populations](#section_3_1)\n", " * [3.2. Resting state plots](#section_3_2)\n", " * [3.3. Time-averaged population rates](#section_3_3)" ] }, { "cell_type": "markdown", "id": "d782e527", "metadata": { "tags": [] }, "source": [ "## S0. Configuration <a class=\"anchor\" id=\"section_0\"></a>" ] }, { "cell_type": "code", "execution_count": 1, "id": "9d6cc7d9-3110-4d96-9f9a-9ec7dee6d145", "metadata": {}, "outputs": [], "source": [ "# Create config file\n", "with open('config.py', 'w') as fp:\n", " fp.write(\n", "'''import os\n", "base_path = os.path.abspath(\".\")\n", "data_path = os.path.abspath(\"simulations\")\n", "jobscript_template = \"python {base_path}/run_simulation.py {label}\"\n", "submit_cmd = \"bash -c\"\n", "''')" ] }, { "cell_type": "code", "execution_count": 2, "id": "96517739", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", " -- N E S T --\n", " Copyright (C) 2004 The NEST Initiative\n", "\n", " Version: 3.5\n", " Built: Jul 12 2023 06:25:27\n", "\n", " This program is provided AS IS and comes with\n", " NO WARRANTY. See the file LICENSE for details.\n", "\n", " Problems or suggestions?\n", " Visit https://www.nest-simulator.org\n", "\n", " Type 'nest.help()' to find out more about NEST.\n", "\n" ] }, { "ename": "SyntaxError", "evalue": "invalid syntax (M2E_visualize_time_ave_pop_rates.py, line 2)", "output_type": "error", "traceback": [ "Traceback \u001b[0;36m(most recent call last)\u001b[0m:\n", "\u001b[0m File \u001b[1;32m/srv/main-spack-instance-2305/spack/var/spack/environments/ebrains-23-06/.spack-env/view/lib/python3.8/site-packages/IPython/core/interactiveshell.py:3378\u001b[0m in \u001b[1;35mrun_code\u001b[0m\n exec(code_obj, self.user_global_ns, self.user_ns)\u001b[0m\n", "\u001b[0;36m Cell \u001b[0;32mIn [2], line 17\u001b[0;36m\n\u001b[0;31m from M2E_visualize_time_ave_pop_rates import plot_time_averaged_population_rates\u001b[0;36m\n", "\u001b[0;36m File \u001b[0;32m~/MAM2EBRAINS/./figures/MAM2EBRAINS/M2E_visualize_time_ave_pop_rates.py:2\u001b[0;36m\u001b[0m\n\u001b[0;31m An overview over time-averaged population rates encoded in colors with areas along x-axis and populations along y-axis.\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m invalid syntax\n" ] } ], "source": [ "%matplotlib inline\n", "import numpy as np\n", "import os\n", "import nest\n", "import json\n", "import sys\n", "from IPython.display import display, HTML\n", "import warnings\n", "\n", "sys.path.append('./figures/MAM2EBRAINS')\n", "\n", "from multiarea_model import MultiAreaModel\n", "from multiarea_model import Analysis\n", "from M2E_visualize_interareal_connectivity import visualize_interareal_connectivity\n", "from M2E_visualize_instantaneous_and_mean_firing_rates import plot_instan_mean_firing_rate\n", "from M2E_visualize_resting_state import plot_resting_state\n", "from M2E_visualize_time_ave_pop_rates import plot_time_averaged_population_rates\n", "from config import base_path, data_path" ] }, { "cell_type": "code", "execution_count": null, "id": "7e07b0d0", "metadata": { "tags": [] }, "outputs": [], "source": [ "%%capture captured\n", "!pip install nested_dict dicthash" ] }, { "cell_type": "code", "execution_count": null, "id": "1d440c07-9b69-4e52-8573-26b13493bc5a", "metadata": { "tags": [] }, "outputs": [], "source": [ "# Jupyter notebook display format setting\n", "style = \"\"\"\n", "<style>\n", "table {float:left}\n", "</style>\n", "\"\"\"\n", "display(HTML(style))\n", "\n", "warnings.filterwarnings('ignore')" ] }, { "cell_type": "markdown", "id": "27160ba8", "metadata": {}, "source": [ "Go back to [Notebook structure](#toc)" ] }, { "cell_type": "markdown", "id": "df83f5ea-1c4b-44d3-9926-01786aa46e14", "metadata": { "tags": [] }, "source": [ "## S1. Parameterization <a class=\"anchor\" id=\"section_1\"></a>" ] }, { "cell_type": "markdown", "id": "30655817", "metadata": {}, "source": [ "### 1.1. Parameters to tune <a class=\"anchor\" id=\"section_1_1\"></a>" ] }, { "cell_type": "markdown", "id": "4f67c1ba", "metadata": {}, "source": [ "|Parameter|Default value|Value range/options|Value assigned|Description|\n", "|:-------:|:-----------:|:-----------------:|:------------:|:---------:|\n", "|scale_down_to|1. |(0, 1.0] |0.005 |$^1$ |\n", "|cc_weights_factor|1. |[1.0, 2.5] |1. |$^2$ |\n", "|areas_simulated|complete_area_list|Sublists of complete_area_list|complete_area_list|$^3$|\n", "|replace_non_simulated_areas|None|None, 'hom_poisson_stat', 'het_poisson_stat', 'het_current_nonstat'|'het_poisson_stat'|$^4$ |" ] }, { "cell_type": "markdown", "id": "a2161477", "metadata": {}, "source": [ "1. `scale_down_to` <br>\n", "scale_down_to is the down-scaling factor which defines the the ratio of the full scale multi-area model being down-scaled to a model with fewer neurons and indegrees so as to be simulated on machines with lower computational ability and the simulation results can be obtained within relative shorter period of time. <br> Its deafualt value if `1.` meaning full scale simulation. <br> In the pre-set downscale version, it's set as `0.005`, where the numer of neurons and indegrees are both scaled down to 0.5% of its full scale amount, where the model can usually be simulated on a local machine. <br> **Warning**: This will not yield reasonable dynamical results from the network and is only meant to demonstrate the simulation workflow <br> \n", "2. `cc_weights_factor` <br>\n", "This scaling factor controls the cortico-cortical synaptic strength. <br> By default it's set as `1.0`, where the inter-area synaptic strength is the same as the intra-areal. <br> **Important**: This factor changes the network activity from ground state to metastable state. <br>\n", "3. `areas_simulated` <br>\n", "This parameter specifies the cortical areas included in the simulation process. Its default value is `complete_area_list` meaning all the areas in the complete_area_list will be actually simulated. <br>\n", "complete_area_list = `['V1', 'V2', 'VP', 'V3', 'V3A', 'MT', 'V4t', 'V4', 'VOT', 'MSTd', 'PIP', 'PO', 'DP', 'MIP', 'MDP', 'VIP', 'LIP', 'PITv', 'PITd', 'MSTl', 'CITv', 'CITd', 'FEF', 'TF', 'AITv', 'FST', '7a', 'STPp', 'STPa', '46', 'AITd', 'TH']` <br>\n", "The value assigned to simulation_areas can be any sublist of the compete_area_list specifying areas a user want to include in his/her simulation. <br>\n", "4. `replace_non_simulated_areas` <br>\n", "The paramter replace_non_simulated_areas defines how non-simulated areas will be replaced. <br> It's set as `None` by default when the parameter areas_simulated is set as full_area_list where all areas will be simulated so that no areas need to be replaced. <br> Other options are: `'hom_poisson_stat'`, `'het_poisson_stat'`, and `'het_current_nonstat'`. `'hom_poisson_stat'` is a manually set parameter which can be tuned. When it's set as 'het_poisson_stat' or 'het_current_nonstat', the data to replace the cortico-cortical input is loaded from 'replace_cc_input_source' which is the firing rates of our full scale simulation results. The differenc between 'het_poisson_stat' and 'het_current_nonstat' is that 'het_poisson_stat' is the mean of the time-series firing rate so that it's static, yet 'het_current_nonstat' is time-varying specific current, which is varying by time. " ] }, { "cell_type": "code", "execution_count": null, "id": "60265d52", "metadata": {}, "outputs": [], "source": [ "# Downscaling factor\n", "# Value range/options: (0, 1.]\n", "# Value assgined: 0.005\n", "scale_down_to = 0.005 # Change it to 1. for running the fullscale network\n", "\n", "# Scaling factor for cortico-cortical connections (chi) \n", "# Value range/options: [1., 2.5]\n", "# Value assgined: 1.0\n", "cc_weights_factor = 1.0\n", "\n", "# Cortical areas included in the simulation\n", "# Value range/options: any sublist of complete_ares_list\n", "# Value assgined: complete_ares_list\n", "areas_simulated = ['V1', 'V2', 'VP', 'V3', 'V3A', 'MT', 'V4t', 'V4', 'VOT', 'MSTd', 'PIP', 'PO', 'DP', 'MIP', 'MDP', 'VIP', 'LIP', 'PITv', 'PITd', 'MSTl', 'CITv', 'CITd', 'FEF', 'TF', 'AITv', 'FST', '7a', 'STPp', 'STPa', '46', 'AITd', 'TH']\n", "\n", "# Firing rates used to replace the non-simulated areas\n", "# Value range/options: None, 'hom_poisson_stat', 'het_poisson_stat', 'het_current_nonstat'\n", "# Value assgined: 'het_poisson_stat'\n", "replace_non_simulated_areas = 'het_poisson_stat'" ] }, { "cell_type": "markdown", "id": "de11b07f", "metadata": {}, "source": [ "### 1.2. Default parameters <a class=\"anchor\" id=\"section_1_2\"></a>\n", "We try our best not to confuse users with too many parameters. However, if you want to change more parameters and explore the model, you can do so by passing a dictionary to the `default_params` argument of the `MultiAreaModel` class." ] }, { "cell_type": "code", "execution_count": null, "id": "6e4bed8d", "metadata": {}, "outputs": [], "source": [ "# Connection parameters\n", "conn_params = {\n", " 'replace_non_simulated_areas': 'het_poisson_stat', # Whether to replace non-simulated areas by Poisson sources with the same global rate, by default: None\n", " 'g': -11., # It sets the relative inhibitory synaptic strength, by default: -16.\n", " 'K_stable': 'K_stable.npy', # Whether to apply the stabilization method of Schuecker, Schmidt et al. (2017), by default: None\n", " 'fac_nu_ext_TH': 1.2, # Increase the external input to 2/3E and 5E in area TH\n", " 'fac_nu_ext_5E': 1.125, # Increase the external Poisson indegree onto 5E\n", " 'fac_nu_ext_6E': 1.41666667, # Increase the external Poisson indegree onto 6E\n", " 'av_indegree_V1': 3950. # Adjust the average indegree in V1 based on monkey data\n", "}\n", "\n", "# Input parameters\n", "input_params = {\n", " 'rate_ext': 10. # Rate of the Poissonian spike generator (in spikes/s)\n", "} \n", "\n", "# Neuron parameters\n", "neuron_params = {\n", " 'V0_mean': -150., # Mean for the distribution of initial membrane potentials, by default: -100.\n", " 'V0_sd': 50.} # Standard deviation for the distribution of initial membrane potentials, by default: 50.\n", "\n", "# Network parameters\n", "network_params = {\n", " 'N_scaling': scale_down_to, # Scaling of population sizes, by default: 1.\n", " 'K_scaling': scale_down_to, # Scaling of indegrees, by default: 1.\n", " 'fullscale_rates': 'tests/fullscale_rates.json', # Absolute path to the file holding full-scale rates for scaling synaptic weights, by default: None\n", " 'input_params': input_params, # Input parameters\n", " 'connection_params': conn_params, # Connection parameters\n", " 'neuron_params': neuron_params # Neuron parameters\n", "} \n", "\n", "# Simulation parameters\n", "sim_params = {\n", " 'areas_simulated': areas_simulated,\n", " 't_sim': 2000., # Simulated time (in ms), by default: 10.0\n", " # 't_sim': 1500., # Simulated time (in ms), by default: 10.0\n", " 'num_processes': 1, # The number of MPI processes, by default: 1\n", " 'local_num_threads': 1, # The number of threads per MPI process, by default: 1\n", " 'recording_dict': {'record_vm': False},\n", " 'rng_seed': 1 # global random seed\n", "}\n", "\n", "# Theory paramters (theory_params)\n", "theory_params = {\n", " 'dt': 0.1 # The time step of the mean-field theory integration, by default: 0.01\n", "} " ] }, { "cell_type": "markdown", "id": "1472e9c5", "metadata": {}, "source": [ "Go back to [Notebook structure](#toc)" ] }, { "cell_type": "markdown", "id": "de4a6703", "metadata": { "tags": [] }, "source": [ "## S2. Multi-Area Model Instantiation and Simulation <a class=\"anchor\" id=\"section_2\"></a>" ] }, { "cell_type": "markdown", "id": "1fd58841", "metadata": { "tags": [] }, "source": [ "### 2.1. Instantiate a multi-area model <a class=\"anchor\" id=\"section_2_1\"></a>" ] }, { "cell_type": "code", "execution_count": null, "id": "ab25f9f8", "metadata": {}, "outputs": [], "source": [ "# %%capture captured\n", "M = MultiAreaModel(network_params, \n", " simulation=True,\n", " sim_spec=sim_params,\n", " theory=True,\n", " theory_spec=theory_params)" ] }, { "cell_type": "markdown", "id": "91649c30", "metadata": {}, "source": [ "### 2.2. Predict firing rates from theory <a class=\"anchor\" id=\"section_2_2\"></a>" ] }, { "cell_type": "code", "execution_count": null, "id": "6a7ddf0e", "metadata": {}, "outputs": [], "source": [ "p, r = M.theory.integrate_siegert()\n", "print(\"Mean-field theory predicts an average \"\n", " \"firing rate of {0:.3f} spikes/s across all populations.\".format(np.mean(r[:, -1])))" ] }, { "cell_type": "markdown", "id": "2062ddf3", "metadata": {}, "source": [ "### 2.3. Extract and visualize interareal connectivity <a class=\"anchor\" id=\"section_2_3\"></a>" ] }, { "cell_type": "markdown", "id": "8a7c09e0", "metadata": {}, "source": [ "The connectivity and neuron numbers are stored in the attributes of the model class. Neuron numbers are stored in `M.N` as a dictionary (and in `M.N_vec` as an array), indegrees in `M.K` as a dictionary (and in `M.K_matrix` as an array). Number of synapses can also be access via `M.synapses` (and in `M.syn_matrix` as an array). <br>" ] }, { "cell_type": "code", "execution_count": null, "id": "6316ac24", "metadata": {}, "outputs": [], "source": [ "# Neuron numbers\n", "\n", "# Dictionary of neuron numbers\n", "# print(M.N)\n", "\n", "# Array of neuron numbers\n", "# (M.N_vec)" ] }, { "cell_type": "code", "execution_count": null, "id": "8408d463-557b-481b-afc1-5fbbbd67306d", "metadata": {}, "outputs": [], "source": [ "# Indegrees\n", "\n", "# Dictionary of nodes indegrees organized as:\n", "# {<source_area>: {<source_pop>: {<target_area>: {<target_pop>: indegree_values}}}}\n", "# M.K\n", "\n", "# Array of nodes indegrees\n", "# M.K_matrix.shape" ] }, { "cell_type": "code", "execution_count": null, "id": "445a722a", "metadata": {}, "outputs": [], "source": [ "# Synapses\n", "\n", "# Dictionary of synapses that target neurons receive, it is organized as:\n", "# {<source_area>: {<source_pop>: {<target_area>: {<target_pop>: number_of_synapses}}}}\n", "# M.synapses\n", "\n", "# Array of \n", "# M.syn_matrix" ] }, { "cell_type": "code", "execution_count": null, "id": "05512922-26e5-425f-90a4-0df7c2279ccf", "metadata": {}, "outputs": [], "source": [ "visualize_interareal_connectivity(M)" ] }, { "cell_type": "markdown", "id": "bae85d86-157c-47a2-9826-860b410a440e", "metadata": {}, "source": [ "Comparable figure in our publications: <br>\n", "1. Schmidt M, Bakker R, Hilgetag CC, Diesmann M & van Albada SJ\n", " Multi-scale account of the network structure of macaque visual cortex\n", " Brain Structure and Function (2018), 223: 1409 [https://doi.org/10.1007/s00429-017-1554-4](https://doi.org/10.1007/s00429-017-1554-4) <br>\n", " **Fig. 4 D Area-level connectivity of the model, based on data in a–c, expressed as relative indegrees for each target area**" ] }, { "cell_type": "markdown", "id": "e67f37e9-ec8d-4bb1-bd21-45e966f47ab6", "metadata": {}, "source": [ "Go back to [Notebook structure](#toc)" ] }, { "cell_type": "markdown", "id": "0c1cad59-81d0-4e24-ac33-13c4ca8c6dec", "metadata": {}, "source": [ "### 2.4. Run a simulation <a class=\"anchor\" id=\"section_2_4\"></a>" ] }, { "cell_type": "code", "execution_count": null, "id": "15778e9c", "metadata": {}, "outputs": [], "source": [ "# %%capture captured\n", "# run the simulation, depending on the model parameter and downscale ratio, the running time varies largely.\n", "M.simulation.simulate()" ] }, { "cell_type": "markdown", "id": "fd6e3232", "metadata": {}, "source": [ "Go back to [Notebook structure](#toc)" ] }, { "cell_type": "markdown", "id": "bb71c922", "metadata": { "tags": [] }, "source": [ "## S3. Simulation Results Visualziation <a class=\"anchor\" id=\"section_3\"></a>" ] }, { "cell_type": "code", "execution_count": null, "id": "c1d7aa61-e85a-4e6a-9e01-e018413a572b", "metadata": {}, "outputs": [], "source": [ "# Instantiate an analysis class and load spike data\n", "A = Analysis(network=M, \n", " simulation=M.simulation, \n", " data_list=['spikes'],\n", " load_areas=None)" ] }, { "cell_type": "markdown", "id": "38ddd973", "metadata": { "tags": [] }, "source": [ "### 3.1. Instantaneous and mean firing rate across all populations <a class=\"anchor\" id=\"section_3_1\"></a>" ] }, { "cell_type": "code", "execution_count": null, "id": "bea30fc8", "metadata": {}, "outputs": [], "source": [ "plot_instan_mean_firing_rate(M)" ] }, { "cell_type": "markdown", "id": "e91c436e-db94-4cd7-a531-29c032efeeae", "metadata": {}, "source": [ "### 3.2 Resting state plots <a class=\"anchor\" id=\"section_3_2\"></a>" ] }, { "cell_type": "markdown", "id": "aeae56a4", "metadata": {}, "source": [ "Comparable figure in our publications: <br>\n", "3. Schmidt M, Bakker R, Shen K, Bezgin B, Diesmann M & van Albada SJ (2018)\n", " A multi-scale layer-resolved spiking network model of\n", " resting-state dynamics in macaque cortex. PLOS Computational Biology, 14(9): e1006359. [https://doi.org/10.1371/journal.pcbi.1006359](https://doi.org/10.1371/journal.pcbi.1006359)\n", " **Fig 5. Resting state of the model with χ =1.9.**" ] }, { "cell_type": "code", "execution_count": null, "id": "ae19bcc3", "metadata": { "tags": [] }, "outputs": [], "source": [ "# Choose 3 areas from the complete_area_list to show their sipking activity\n", "# By default, it's set as ['V1', 'V2', 'FEF']\n", "raster_areas = ['V4', 'V1', 'FEF']\n", "plot_resting_state(M, A, data_path, raster_areas)" ] }, { "cell_type": "markdown", "id": "473d0882-8e45-4330-bfa2-2c7e1af0dac4", "metadata": { "tags": [] }, "source": [ "### 3.3 Time-averaged population rates <a class=\"anchor\" id=\"section_4_3\"></a>\n", "An overview over time-averaged population rates encoded in colors with areas along x-axis and populations along y-axis." ] }, { "cell_type": "code", "execution_count": null, "id": "721d1f03-df25-468d-8075-a807025a9c58", "metadata": {}, "outputs": [], "source": [ "plot_time_averaged_population_rates(A)" ] }, { "cell_type": "markdown", "id": "b03d44e8-2216-44ff-ada4-83e9c3e6d30a", "metadata": {}, "source": [ "|Area index|0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|\n", "|:--------:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|\n", "|Area |V1|V2|VP|V3|PIP|V3A|MT|V4t|V4|PO|VOT|DP|MIP|MDP|MSTd|VIP|LIP|PITv|PITd|AITv|MSTl|FST|CITv|CITd|7a|STPp|STPa|FEF|46|TF|TH|AITd| " ] }, { "cell_type": "markdown", "id": "ef74ca3e-98dc-49c9-a4a0-2c640e29b1d9", "metadata": {}, "source": [ "Go back to [Notebook structure](#toc)" ] } ], "metadata": { "kernelspec": { "display_name": "EBRAINS-23.06", "language": "python", "name": "ebrains-23.06" }, "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.8.11" } }, "nbformat": 4, "nbformat_minor": 5 }