diff --git a/multi-area-model.ipynb b/multi-area-model.ipynb index 92ec9be9aa6e847ace8c2b222bc306c8caefe207..af6ffc99a2b4ea2faf7aa705980d304e2e19a368 100644 --- a/multi-area-model.ipynb +++ b/multi-area-model.ipynb @@ -10,96 +10,92 @@ }, { "cell_type": "markdown", - "id": "3e163b35-5330-48ca-8c7e-9e0a884520ca", + "id": "d782e527", "metadata": {}, "source": [ - "## Import dependencies" + "### Create config file" ] }, { "cell_type": "code", "execution_count": null, - "id": "96517739", + "id": "9b985084", "metadata": {}, "outputs": [], "source": [ - "%matplotlib inline\n", - "import matplotlib.pyplot as plt\n", - "import numpy as np\n", - "import os" + "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": "markdown", + "id": "4a853b97", + "metadata": {}, + "source": [ + "### Import dependencies" ] }, { "cell_type": "code", "execution_count": null, - "id": "7e07b0d0", + "id": "96517739", "metadata": {}, "outputs": [], "source": [ - "!pip install nested_dict dicthash" + "%matplotlib inline\n", + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "import os\n", + "import nest\n", + "\n", + "from multiarea_model import MultiAreaModel\n", + "from config import base_path" ] }, { "cell_type": "code", - "execution_count": 7, - "id": "1d440c07-9b69-4e52-8573-26b13493bc5a", + "execution_count": null, + "id": "7e07b0d0", "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "<style>\n", - "table {float:left}\n", - "</style>\n" - ], - "text/plain": [ - "<IPython.core.display.HTML object>" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ - "%%html\n", - "<style>\n", - "table {float:left}\n", - "</style>" + "!pip install nested_dict dicthash" ] }, { "cell_type": "markdown", - "id": "98555af1-a5c5-4db6-85dc-6d07e40f38cc", + "id": "2f429063", "metadata": {}, "source": [ - "## Create config file" + "### Jupyter notebook display format setting" ] }, { "cell_type": "code", "execution_count": null, - "id": "72c170e4", + "id": "1d440c07-9b69-4e52-8573-26b13493bc5a", "metadata": {}, "outputs": [], "source": [ - "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", - "''')" + "# specify the format the table in output\n", + "%%html\n", + "<style>\n", + "table {float:left}\n", + "</style>" ] }, { - "cell_type": "code", - "execution_count": null, - "id": "2784f76b", + "cell_type": "markdown", + "id": "89d4866d", "metadata": {}, - "outputs": [], "source": [ - "from multiarea_model import MultiAreaModel" + "<br>" ] }, { @@ -119,9 +115,19 @@ "tags": [] }, "source": [ - "### 1. Scaling parameter\n", - "**Scaling parameter** (scale_down_to) is the parameter 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 in relative shorter period of time.<br> <br> \n", - "Neurons and indegrees are both scaled down to 0.5%, 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.**" + "### 1. Scaling factor (scale_down_to)\n", + "**Scaling factor** (scale_down_to) is the parameter 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> <br> \n", + "Neurons and indegrees are both scaled down to 0.5%, 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.**" + ] + }, + { + "cell_type": "markdown", + "id": "f66dbf02", + "metadata": {}, + "source": [ + "|Parameter |Parameter description |Variable |Value |Value description |\n", + "|:-------------:|:----------------------|:---------------------------:|:------------------:|:------------------|\n", + "|Scaling factor | | scale_down_to |0.005 | |" ] }, { @@ -131,7 +137,7 @@ "metadata": {}, "outputs": [], "source": [ - "scale_down_to = 0.005" + "scale_down_to = 0.005 # Change it to 1. for running the fullscale network" ] }, { @@ -175,7 +181,6 @@ "source": [ "conn_params = {'replace_non_simulated_areas': 'het_poisson_stat',\n", " 'g': -11.,\n", - " \n", " 'K_stable': 'K_stable.npy',\n", " 'fac_nu_ext_TH': 1.2,\n", " 'fac_nu_ext_5E': 1.125,\n", @@ -254,14 +259,14 @@ "id": "3e437aca-1fd0-4296-a0f6-a346b1319903", "metadata": {}, "source": [ - "| Parameter | Parameter description | Variable | Value | Value description |\n", - "|:---------:|:----------------------|:---------------------:|:-----------------------------:|:------------------|\n", - "| | | N_scaling | scale_down_to | |\n", - "| | | K_scaling | scale_down_to | |\n", - "| | | fullscale_rates | 'tests/fullscale_rates.json' | |\n", - "| | | input_params | input_params | |\n", - "| | | connection_params | conn_params | |\n", - "| | | neuron_params | neuron_params | |" + "| Parameter | Parameter description | Variable | Value | Value description |\n", + "|:---------------------------------------:|:----------------------|:---------------------:|:-----------------------------:|:------------------|\n", + "| Scaling factor of the number of neurons | | N_scaling | scale_down_to | |\n", + "| Scaling factor of the number of synapses| | K_scaling | scale_down_to | |\n", + "| Fullscale rates | | fullscale_rates | 'tests/fullscale_rates.json' | |\n", + "| Input parameters | | input_params | input_params | |\n", + "| Connections parameters | | connection_params | conn_params | |\n", + "| Neuron parameters | | neuron_params | neuron_params | |" ] }, { @@ -284,7 +289,7 @@ "id": "a0730f70-ed9b-4664-b677-3dda965a01ef", "metadata": {}, "source": [ - "### 3. Simulation paramters (sim_params)" + "### 2.5 Simulation paramters (sim_params)" ] }, { @@ -292,13 +297,13 @@ "id": "c989ee79-fa3d-405c-a1bf-da8ec884d878", "metadata": {}, "source": [ - "| Parameter | Parameter description | Variable | Value | Value description |\n", - "|:---------:|:----------------------|:--------------------:|:------------------:|:------------------|\n", - "| | |t_sim |2000. | |\n", - "| | |num_processes |1 | |\n", - "| | |local_num_threads |1 | |\n", - "| | |recording_dict |input_params | |\n", - "| | |record_vm |False | |" + "| Parameter | Parameter description | Variable | Value | Value description |\n", + "|:---------------------:|:----------------------|:--------------------:|:------------------:|:------------------|\n", + "|Simulation time | |t_sim |2000. | |\n", + "|Number of processes | |num_processes |1 | |\n", + "|Number of local threads| |local_num_threads |1 | |\n", + "| | |recording_dict |input_params | |\n", + "| | |record_vm |False | |" ] }, { @@ -311,7 +316,8 @@ "sim_params = {'t_sim': 2000.,\n", " 'num_processes': 1,\n", " 'local_num_threads': 1,\n", - " 'recording_dict': {'record_vm': False}}" + " 'recording_dict': {'record_vm': False},\n", + " 'rng_seed': 1} # global random seed\n" ] }, { @@ -319,7 +325,7 @@ "id": "79596d77-c105-45d0-9a57-2d15e31f1189", "metadata": {}, "source": [ - "### 4. Theory paramters (theory_params)" + "### 2.6. Theory paramters (theory_params)" ] }, { @@ -342,18 +348,34 @@ "theory_params = {'dt': 0.1}" ] }, + { + "cell_type": "markdown", + "id": "1472e9c5", + "metadata": {}, + "source": [ + "<br>" + ] + }, { "cell_type": "markdown", "id": "de4a6703", "metadata": {}, "source": [ - "## Instantiate a multi-area model, predict firing rates from theroy " + "## Instantiate a multi-area model and analyse" + ] + }, + { + "cell_type": "markdown", + "id": "1fd58841", + "metadata": {}, + "source": [ + "### 1. Insantiate a multi-area model " ] }, { "cell_type": "code", "execution_count": null, - "id": "d409be95", + "id": "ab25f9f8", "metadata": {}, "outputs": [], "source": [ @@ -363,10 +385,18 @@ " theory_spec=theory_params)" ] }, + { + "cell_type": "markdown", + "id": "91649c30", + "metadata": {}, + "source": [ + "### 2. Predict firing rates from theory" + ] + }, { "cell_type": "code", "execution_count": null, - "id": "918d907f", + "id": "6a7ddf0e", "metadata": {}, "outputs": [], "source": [ @@ -375,6 +405,70 @@ " \"rate of {0:.3f} spikes/s across all populations.\".format(np.mean(r[:, -1])))" ] }, + { + "cell_type": "markdown", + "id": "2062ddf3", + "metadata": {}, + "source": [ + "### 3. Extract connectivity" + ] + }, + { + "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)." + ] + }, + { + "cell_type": "markdown", + "id": "b7396606", + "metadata": {}, + "source": [ + "#### 3.1 Node indegrees" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6316ac24", + "metadata": {}, + "outputs": [], + "source": [ + "# Dictionary of nodes indegrees organized as:\n", + "# {<source_area>: {<source_pop>: {<target_area>: {<target_pop>: indegree_values}}}}\n", + "M.K" + ] + }, + { + "cell_type": "markdown", + "id": "253a2aba", + "metadata": {}, + "source": [ + "#### 3.2 Synapses" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "445a722a", + "metadata": {}, + "outputs": [], + "source": [ + "# 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" + ] + }, + { + "cell_type": "markdown", + "id": "6c01820e", + "metadata": {}, + "source": [ + "<br>" + ] + }, { "cell_type": "markdown", "id": "0c1cad59-81d0-4e24-ac33-13c4ca8c6dec", @@ -390,15 +484,122 @@ "metadata": {}, "outputs": [], "source": [ + "# 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": [ + "<br>" + ] + }, + { + "cell_type": "markdown", + "id": "28e071f8", + "metadata": {}, + "source": [ + "## Simulation results analysis" + ] + }, + { + "cell_type": "markdown", + "id": "89c7b7cf", + "metadata": {}, + "source": [ + "The following instructions will work when the `simulate` parameter is set to `True` during the creation of the MultiAreaModel object, and the `M.simulation.simulate()` method is executed." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dc3b1820", + "metadata": {}, + "outputs": [], + "source": [ + "# Uncomment the lines in this code cell below to test if the number of synapses created by NEST matches the expected values\n", + "\n", + "# \"\"\"\n", + "# Test if the correct number of synapses has been created.\n", + "# \"\"\"\n", + "# print(\"Testing synapse numbers\")\n", + "# for target_area_name in M.area_list:\n", + "# target_area = M.simulation.areas[M.simulation.areas.index(target_area_name)]\n", + "# for source_area_name in M.area_list:\n", + "# source_area = M.simulation.areas[M.simulation.areas.index(source_area_name)]\n", + "# for target_pop in M.structure[target_area.name]:\n", + "# target_nodes = target_area.gids[target_pop]\n", + "# for source_pop in M.structure[source_area.name]:\n", + "# source_nodes = source_area.gids[source_pop]\n", + "# created_syn = nest.GetConnections(source=source_nodes,\n", + "# target=target_nodes)\n", + "# syn = M.synapses[target_area.name][target_pop][source_area.name][source_pop]\n", + "# assert(len(created_syn) == int(syn))" + ] + }, + { + "cell_type": "markdown", + "id": "57401110", + "metadata": {}, + "source": [ + "To obtain the connections information, you can extract the lists of connected sources and targets. Moreover, you can access additional synaptic details, such as synaptic weights and delays." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e7eb052e", + "metadata": {}, + "outputs": [], + "source": [ + "conns = nest.GetConnections()\n", + "conns_sparse_matrix = conns.get(['source', 'target', 'weight'])\n", + "\n", + "srcs = conns_sparse_matrix['source']\n", + "tgts = conns_sparse_matrix['target']\n", + "weights = conns_sparse_matrix['weight']" + ] + }, + { + "cell_type": "markdown", + "id": "ef4b2e4b", + "metadata": {}, + "source": [ + "You can determine the area and subpopulation to which the neuron ID ranges belong by referring to the file `network_gids.txt`, which is automatically generated during network creation." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "902f2800", + "metadata": {}, + "outputs": [], + "source": [ + "# Open the file using a with statement\n", + "with open(os.path.join(M.simulation.data_dir,\"recordings/network_gids.txt\"), \"r\") as file:\n", + " # Read the contents of the file\n", + " gids = file.read()\n", + "\n", + "# Print the contents\n", + "print(gids)" + ] + }, + { + "cell_type": "markdown", + "id": "875263c1", + "metadata": {}, + "source": [ + "<br>" + ] + }, { "cell_type": "markdown", "id": "9be9287d-4891-4b4b-bd19-cfc2ebed02ac", "metadata": {}, "source": [ - "## Load and process simulation results data" + "## Load and process data of simulation results" ] }, { @@ -438,6 +639,14 @@ "rate = spikecount / M.simulation.params['dt'] * 1e3 / np.sum(M.N_vec)" ] }, + { + "cell_type": "markdown", + "id": "ca603daf", + "metadata": {}, + "source": [ + "<br>" + ] + }, { "cell_type": "markdown", "id": "57ff902c-d6ce-4f96-9e4f-8e3e7166ab66",