From 99a73a316fb62cb5917f54b4263aca6b014baf8c Mon Sep 17 00:00:00 2001 From: Michael Deistler Date: Thu, 14 Nov 2024 21:30:28 +0100 Subject: [PATCH] clearer wording for some tutorials (#504) --- docs/tutorials/01_morph_neurons.ipynb | 90 ++++++++++----------- docs/tutorials/02_small_network.ipynb | 78 +++++++++--------- docs/tutorials/04_jit_and_vmap.ipynb | 74 ++++++++--------- docs/tutorials/06_groups.ipynb | 60 ++++++-------- docs/tutorials/09_advanced_indexing.ipynb | 98 +++++++++++------------ 5 files changed, 197 insertions(+), 203 deletions(-) diff --git a/docs/tutorials/01_morph_neurons.ipynb b/docs/tutorials/01_morph_neurons.ipynb index 6abe65b1..dc317a58 100644 --- a/docs/tutorials/01_morph_neurons.ipynb +++ b/docs/tutorials/01_morph_neurons.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "markdown", - "id": "3cb59f08", + "id": "23de17f3", "metadata": {}, "source": [ "# Basics of Jaxley" @@ -10,7 +10,7 @@ }, { "cell_type": "markdown", - "id": "9cab6953", + "id": "f3ec2d4a", "metadata": {}, "source": [ "In this tutorial, you will learn how to:\n", @@ -61,7 +61,7 @@ }, { "cell_type": "markdown", - "id": "031ce290", + "id": "811381aa", "metadata": {}, "source": [ "First, we import the relevant libraries:" @@ -70,7 +70,7 @@ { "cell_type": "code", "execution_count": 1, - "id": "e1f3cf24", + "id": "f7b6139b", "metadata": {}, "outputs": [], "source": [ @@ -91,7 +91,7 @@ }, { "cell_type": "markdown", - "id": "010e823e", + "id": "80c1db84", "metadata": {}, "source": [ "We will now build our first cell in `Jaxley`. You have two options to do this: you can either build a cell bottom-up by defining the morphology yourselve, or you can [load cells from SWC files](https://jaxley.readthedocs.io/en/latest/tutorials/08_importing_morphologies.html).\n" @@ -99,7 +99,7 @@ }, { "cell_type": "markdown", - "id": "22c43455", + "id": "b26c95af", "metadata": {}, "source": [ "### Define the cell from scratch\n", @@ -110,7 +110,7 @@ { "cell_type": "code", "execution_count": 2, - "id": "145ff540", + "id": "e0209d33", "metadata": {}, "outputs": [], "source": [ @@ -120,7 +120,7 @@ }, { "cell_type": "markdown", - "id": "bb109c89", + "id": "a29cbb32", "metadata": {}, "source": [ "Next, we can assemble branches into a cell. To do so, we have to define for each branch what its parent branch is. A `-1` entry means that this branch does not have a parent." @@ -129,7 +129,7 @@ { "cell_type": "code", "execution_count": 3, - "id": "a069d64b", + "id": "ebcf5e9f", "metadata": {}, "outputs": [], "source": [ @@ -139,7 +139,7 @@ }, { "cell_type": "markdown", - "id": "f621d887", + "id": "3c674521", "metadata": {}, "source": [ "To learn more about `Compartment`s, `Branch`es, and `Cell`s, see [this tutorial](https://jaxley.readthedocs.io/en/latest/tutorials/00_jaxley_api.html)." @@ -147,7 +147,7 @@ }, { "cell_type": "markdown", - "id": "21af5a58", + "id": "c697cd51", "metadata": {}, "source": [ "### Read the cell from an SWC file\n", @@ -161,7 +161,7 @@ }, { "cell_type": "markdown", - "id": "6f23848c", + "id": "1a7fb15c", "metadata": {}, "source": [ "### Visualize the cells" @@ -169,7 +169,7 @@ }, { "cell_type": "markdown", - "id": "533c3adb", + "id": "3cd044a6", "metadata": {}, "source": [ "Cells can be visualized as follows:" @@ -178,7 +178,7 @@ { "cell_type": "code", "execution_count": 4, - "id": "eeb15b15", + "id": "eadf3c25", "metadata": {}, "outputs": [ { @@ -201,7 +201,7 @@ }, { "cell_type": "markdown", - "id": "13f7151d", + "id": "833e4597", "metadata": {}, "source": [ "### Insert mechanisms\n", @@ -212,7 +212,7 @@ { "cell_type": "code", "execution_count": 5, - "id": "802b59c4", + "id": "728984f3", "metadata": {}, "outputs": [], "source": [ @@ -223,7 +223,7 @@ }, { "cell_type": "markdown", - "id": "ffbeb0a8", + "id": "c750def0", "metadata": {}, "source": [ "Once the cell is created, we can inspect its `.nodes` attribute which lists all properties of the cell:" @@ -232,7 +232,7 @@ { "cell_type": "code", "execution_count": 6, - "id": "255e0e70", + "id": "b147d551", "metadata": {}, "outputs": [ { @@ -588,7 +588,7 @@ }, { "cell_type": "markdown", - "id": "650a2692", + "id": "09315df3", "metadata": {}, "source": [ "_Note that `Jaxley` uses the same units as the `NEURON` simulator, which are listed [here](https://www.neuron.yale.edu/neuron/static/docs/units/unitchart.html)._\n", @@ -599,7 +599,7 @@ { "cell_type": "code", "execution_count": 7, - "id": "e2ef065e", + "id": "54bd54f1", "metadata": {}, "outputs": [ { @@ -731,7 +731,7 @@ }, { "cell_type": "markdown", - "id": "825fb9ce", + "id": "04a85440", "metadata": {}, "source": [ "The easiest way to know which branch is the 1st branch (or, e.g., the zero-eth compartment of the 1st branch) is to plot it in a different color:" @@ -740,7 +740,7 @@ { "cell_type": "code", "execution_count": 8, - "id": "e6d9f62b", + "id": "643ea991", "metadata": {}, "outputs": [ { @@ -763,7 +763,7 @@ }, { "cell_type": "markdown", - "id": "415a0534", + "id": "b1cb9b9b", "metadata": {}, "source": [ "More background and features on indexing as `cell.branch(0)` is in [this tutorial](https://jaxley.readthedocs.io/en/latest/tutorials/00_jaxley_api.html)." @@ -771,7 +771,7 @@ }, { "cell_type": "markdown", - "id": "d2c05ca5", + "id": "fea0d9ea", "metadata": {}, "source": [ "### Change parameters of the cell\n", @@ -782,7 +782,7 @@ { "cell_type": "code", "execution_count": 9, - "id": "1b2df394", + "id": "d34cf35c", "metadata": {}, "outputs": [], "source": [ @@ -791,7 +791,7 @@ }, { "cell_type": "markdown", - "id": "17104361", + "id": "e25971ab", "metadata": {}, "source": [ "And we can again inspect the `.nodes` to make sure that the axial resistivity indeed changed:" @@ -800,7 +800,7 @@ { "cell_type": "code", "execution_count": 10, - "id": "130c13e5", + "id": "16b25603", "metadata": {}, "outputs": [ { @@ -932,16 +932,16 @@ }, { "cell_type": "markdown", - "id": "9967ca4c", + "id": "b37a14b7", "metadata": {}, "source": [ - "In a similar way, you can modify channel properties or initial states (all units are the same as for the `NEURON` simulator, which are listed [here](https://www.neuron.yale.edu/neuron/static/docs/units/unitchart.html)):" + "In a similar way, you can modify channel properties or initial states (units are again [here](https://www.neuron.yale.edu/neuron/static/docs/units/unitchart.html)):" ] }, { "cell_type": "code", "execution_count": 11, - "id": "b4da8cba", + "id": "bb0bb6b9", "metadata": {}, "outputs": [], "source": [ @@ -951,7 +951,7 @@ }, { "cell_type": "markdown", - "id": "d559f3e9", + "id": "6bc4c09f", "metadata": {}, "source": [ "### Stimulate the cell\n", @@ -962,7 +962,7 @@ { "cell_type": "code", "execution_count": 12, - "id": "7655a254", + "id": "e3f56a7a", "metadata": {}, "outputs": [ { @@ -988,7 +988,7 @@ }, { "cell_type": "markdown", - "id": "e367d928", + "id": "6e5cc5a0", "metadata": {}, "source": [ "We then stimulate one of the compartments of the cell with this step current:" @@ -997,7 +997,7 @@ { "cell_type": "code", "execution_count": 13, - "id": "9c7ec374", + "id": "24582568", "metadata": {}, "outputs": [ { @@ -1015,7 +1015,7 @@ }, { "cell_type": "markdown", - "id": "fd0fbd52", + "id": "cf4723f6", "metadata": {}, "source": [ "### Define recordings" @@ -1023,7 +1023,7 @@ }, { "cell_type": "markdown", - "id": "a3a04360", + "id": "a7ef6084", "metadata": {}, "source": [ "Next, you have to define where to record the voltage. In this case, we will record the voltage at two locations:" @@ -1032,7 +1032,7 @@ { "cell_type": "code", "execution_count": 14, - "id": "790ab537", + "id": "a03a5b85", "metadata": {}, "outputs": [ { @@ -1052,7 +1052,7 @@ }, { "cell_type": "markdown", - "id": "362531bc", + "id": "c054ef72", "metadata": {}, "source": [ "We can again visualize these locations to understand where we inserted recordings:" @@ -1061,7 +1061,7 @@ { "cell_type": "code", "execution_count": 15, - "id": "97b38d8e", + "id": "0d76ecdc", "metadata": {}, "outputs": [ { @@ -1084,7 +1084,7 @@ }, { "cell_type": "markdown", - "id": "61bbea8a", + "id": "19a01ad4", "metadata": {}, "source": [ "### Simulate the cell response\n", @@ -1095,7 +1095,7 @@ { "cell_type": "code", "execution_count": 16, - "id": "6c08054b", + "id": "dca9f6f8", "metadata": {}, "outputs": [ { @@ -1113,7 +1113,7 @@ }, { "cell_type": "markdown", - "id": "36a05bb6", + "id": "658889d6", "metadata": {}, "source": [ "The `jx.integrate` function returns an array of shape `(num_recordings, num_timepoints)`. In our case, we inserted `2` recordings and we simulated for 10ms at a 0.025 time step, which leads to 402 time steps.\n", @@ -1124,7 +1124,7 @@ { "cell_type": "code", "execution_count": 17, - "id": "7c605c24", + "id": "809514e3", "metadata": {}, "outputs": [ { @@ -1146,7 +1146,7 @@ }, { "cell_type": "markdown", - "id": "507752b4", + "id": "3cf92844", "metadata": {}, "source": [ "At the location of the first recording (in blue) the cell spiked, whereas at the second recording, it did not. This makes sense because we only inserted sodium and potassium channels into the first branch, but not in the entire cell." @@ -1154,7 +1154,7 @@ }, { "cell_type": "markdown", - "id": "558fdda4", + "id": "2ed34987", "metadata": {}, "source": [ "Congrats! You have just run your first morphologically detailed neuron simulation in `Jaxley`. We suggest to continue by learning how to [build networks](https://jaxley.readthedocs.io/en/latest/tutorials/02_small_network.html). If you are only interested in single cell simulations, you can directly jump to learning how to [speed up simulations](https://jaxley.readthedocs.io/en/latest/tutorials/04_jit_and_vmap.html). If you want to simulate detailed morphologies from SWC files, checkout our tutorial on [working with detailed morphologies](https://jaxley.readthedocs.io/en/latest/tutorials/08_importing_morphologies.html)." diff --git a/docs/tutorials/02_small_network.ipynb b/docs/tutorials/02_small_network.ipynb index 72b18413..0beac421 100644 --- a/docs/tutorials/02_small_network.ipynb +++ b/docs/tutorials/02_small_network.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "markdown", - "id": "90a14a0a", + "id": "daf16a06", "metadata": {}, "source": [ "# Network simulations in Jaxley" @@ -10,7 +10,7 @@ }, { "cell_type": "markdown", - "id": "8a6ee5d1", + "id": "4cadbc28", "metadata": {}, "source": [ "In this tutorial, you will learn how to:\n", @@ -48,7 +48,7 @@ }, { "cell_type": "markdown", - "id": "8c67dec8", + "id": "55d469cc", "metadata": {}, "source": [ "In the previous tutorial, you learned how to build single cells with morphological detail, how to insert stimuli and recordings, and how to run a first simulation. In this tutorial, we will define networks of multiple cells and connect them with synapses. Let's get started:" @@ -57,7 +57,7 @@ { "cell_type": "code", "execution_count": 1, - "id": "d053f37a", + "id": "e243b76c", "metadata": {}, "outputs": [], "source": [ @@ -78,7 +78,7 @@ }, { "cell_type": "markdown", - "id": "0f67fdb1", + "id": "1c61ce71", "metadata": {}, "source": [ "### Define the network\n", @@ -89,7 +89,7 @@ { "cell_type": "code", "execution_count": 2, - "id": "8dbea2ab", + "id": "efdd3c18", "metadata": {}, "outputs": [], "source": [ @@ -100,7 +100,7 @@ }, { "cell_type": "markdown", - "id": "3e021130", + "id": "89420836", "metadata": {}, "source": [ "We can assemble multiple cells into a network by using `jx.Network`, which takes a list of `jx.Cell`s. Here, we assemble 11 cells into a network:" @@ -109,7 +109,7 @@ { "cell_type": "code", "execution_count": 3, - "id": "275a0617", + "id": "7a33f986", "metadata": {}, "outputs": [], "source": [ @@ -119,7 +119,7 @@ }, { "cell_type": "markdown", - "id": "2a8d8beb", + "id": "6627d8c4", "metadata": {}, "source": [ "At this point, we can already visualize this network:" @@ -128,7 +128,7 @@ { "cell_type": "code", "execution_count": 4, - "id": "aa7c7cff", + "id": "b435350c", "metadata": {}, "outputs": [ { @@ -151,15 +151,15 @@ }, { "cell_type": "markdown", - "id": "dd9582ce", + "id": "1af6b8ef", "metadata": {}, "source": [ - "Note: you can use `move_to` to have more control over the location of cells, e.g.: `network.cell(i).move_to(x=0, y=200)`." + "_Note: you can use `move_to` to have more control over the location of cells, e.g.: `network.cell(i).move_to(x=0, y=200)`._" ] }, { "cell_type": "markdown", - "id": "fb251c0c", + "id": "8811377d", "metadata": {}, "source": [ "As you can see, the neurons are not connected yet. Let's fix this by connecting neurons with synapses. We will build a network consisting of two layers: 10 neurons in the input layer and 1 neuron in the output layer.\n", @@ -170,7 +170,7 @@ { "cell_type": "code", "execution_count": 5, - "id": "02f19e14", + "id": "b276f3d6", "metadata": {}, "outputs": [], "source": [ @@ -181,7 +181,7 @@ }, { "cell_type": "markdown", - "id": "8fa9123f", + "id": "a7f93d60", "metadata": {}, "source": [ "Let's visualize this again:" @@ -190,7 +190,7 @@ { "cell_type": "code", "execution_count": 6, - "id": "f6c78f17", + "id": "66f6adc5", "metadata": {}, "outputs": [ { @@ -211,7 +211,7 @@ }, { "cell_type": "markdown", - "id": "504d21d5", + "id": "3c65b97d", "metadata": {}, "source": [ "As you can see, the `full_connect` method inserted one synapse (in blue) from every neuron in the first layer to the output neuron. The `fully_connect` method builds this synapse from the zero-eth compartment and zero-eth branch of the presynaptic neuron onto a random branch of the postsynaptic neuron. If you want more control over the pre- and post-synaptic branches, you can use the `connect` method:" @@ -220,7 +220,7 @@ { "cell_type": "code", "execution_count": 7, - "id": "012e7779", + "id": "d27915a4", "metadata": {}, "outputs": [], "source": [ @@ -232,7 +232,7 @@ { "cell_type": "code", "execution_count": 8, - "id": "f2f58f2d", + "id": "ab4a5c40", "metadata": {}, "outputs": [ { @@ -253,7 +253,7 @@ }, { "cell_type": "markdown", - "id": "5185b39e", + "id": "b89a542e", "metadata": {}, "source": [ "### Inspecting and changing synaptic parameters" @@ -261,7 +261,7 @@ }, { "cell_type": "markdown", - "id": "a6554cda", + "id": "00ed47a3", "metadata": {}, "source": [ "You can inspect synaptic parameters via the `.edges` attribute:" @@ -270,7 +270,7 @@ { "cell_type": "code", "execution_count": 9, - "id": "319e7096", + "id": "8f26e379", "metadata": {}, "outputs": [ { @@ -543,7 +543,7 @@ }, { "cell_type": "markdown", - "id": "461c7154", + "id": "dbe103a2", "metadata": {}, "source": [ "To modify a parameter of all synapses you can again use `.set()`:" @@ -552,7 +552,7 @@ { "cell_type": "code", "execution_count": 10, - "id": "8cff6d8e", + "id": "8e4b4548", "metadata": {}, "outputs": [], "source": [ @@ -561,7 +561,7 @@ }, { "cell_type": "markdown", - "id": "c55c7d16", + "id": "cee4fbb6", "metadata": {}, "source": [ "To modify individual syanptic parameters, use the `.select()` method. Below, we change the values of the first two synapses:" @@ -570,7 +570,7 @@ { "cell_type": "code", "execution_count": 11, - "id": "5d381e66", + "id": "9842f48e", "metadata": {}, "outputs": [], "source": [ @@ -579,7 +579,7 @@ }, { "cell_type": "markdown", - "id": "dba8d29a", + "id": "75a640d3", "metadata": {}, "source": [ "For more details on how to flexibly set synaptic parameters (e.g., by cell type, or by pre-synaptic cell index,...), see [this tutorial](https://jaxley.readthedocs.io/en/latest/tutorials/09_advanced_indexing.html)." @@ -587,7 +587,7 @@ }, { "cell_type": "markdown", - "id": "6e522bb2", + "id": "3adca2eb", "metadata": {}, "source": [ "### Stimulating, recording, and simulating the network" @@ -595,7 +595,7 @@ }, { "cell_type": "markdown", - "id": "7f6fe380", + "id": "4fa7a8b0", "metadata": {}, "source": [ "We will now set up a simulation of the network. This works exactly as it does for single neurons:" @@ -604,7 +604,7 @@ { "cell_type": "code", "execution_count": 12, - "id": "a0872a05", + "id": "f0f8c0ea", "metadata": {}, "outputs": [], "source": [ @@ -621,7 +621,7 @@ { "cell_type": "code", "execution_count": 13, - "id": "38359eaa", + "id": "926b7339", "metadata": {}, "outputs": [], "source": [ @@ -630,7 +630,7 @@ }, { "cell_type": "markdown", - "id": "5b3c4b39", + "id": "cacb1eb9", "metadata": {}, "source": [ "As a simple example, we insert sodium, potassium, and leak into every compartment of every cell of the network." @@ -639,7 +639,7 @@ { "cell_type": "code", "execution_count": 14, - "id": "bf712140", + "id": "130424d9", "metadata": {}, "outputs": [], "source": [ @@ -650,7 +650,7 @@ }, { "cell_type": "markdown", - "id": "489cb351", + "id": "7d60ac41", "metadata": {}, "source": [ "We stimulate every neuron in the input layer and record the voltage from the output neuron:" @@ -659,7 +659,7 @@ { "cell_type": "code", "execution_count": 15, - "id": "acf7fbaf", + "id": "85e79399", "metadata": {}, "outputs": [ { @@ -692,7 +692,7 @@ }, { "cell_type": "markdown", - "id": "123ab9c0", + "id": "f6d6682a", "metadata": {}, "source": [ "Finally, we can again run the network simulation and plot the result:" @@ -701,7 +701,7 @@ { "cell_type": "code", "execution_count": 16, - "id": "7615dd48", + "id": "e7bcd093", "metadata": {}, "outputs": [], "source": [ @@ -711,7 +711,7 @@ { "cell_type": "code", "execution_count": 17, - "id": "ebf739d5", + "id": "1c34dc99", "metadata": {}, "outputs": [ { @@ -732,7 +732,7 @@ }, { "cell_type": "markdown", - "id": "708c519c", + "id": "1043fd12", "metadata": {}, "source": [ "That's it! You now know how to simulate networks of morphologically detailed neurons. We recommend that you now have a look at how you can [speed up your simulation](https://jaxley.readthedocs.io/en/latest/tutorials/04_jit_and_vmap.html). To learn more about handling synaptic parameters, we recommend to check out [this tutorial](https://jaxley.readthedocs.io/en/latest/tutorials/09_advanced_indexing.html)." diff --git a/docs/tutorials/04_jit_and_vmap.ipynb b/docs/tutorials/04_jit_and_vmap.ipynb index f8d681f8..918ea643 100644 --- a/docs/tutorials/04_jit_and_vmap.ipynb +++ b/docs/tutorials/04_jit_and_vmap.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "markdown", - "id": "a1074115", + "id": "320fdce2", "metadata": {}, "source": [ "# Speeding up simulations" @@ -10,7 +10,7 @@ }, { "cell_type": "markdown", - "id": "d3e38494", + "id": "a505b54c", "metadata": {}, "source": [ "In this tutorial, you will learn how to:\n", @@ -47,7 +47,7 @@ }, { "cell_type": "markdown", - "id": "ea191f70", + "id": "332060c6", "metadata": {}, "source": [ "In the previous tutorials, you learned how to build single cells or networks and how to change their parameters. In this tutorial, you will learn how to speed up such simulations by many orders of magnitude. This can be achieved in to ways:\n", @@ -60,7 +60,7 @@ }, { "cell_type": "markdown", - "id": "ca8ac1e5", + "id": "6e4b08d7", "metadata": {}, "source": [ "### Using GPU or CPU" @@ -68,7 +68,7 @@ }, { "cell_type": "markdown", - "id": "694e9c23", + "id": "0b8ba3c2", "metadata": {}, "source": [ "In `Jaxley` you can set whether you want to use `gpu` or `cpu` with the following lines at the beginning of your script:" @@ -77,7 +77,7 @@ { "cell_type": "code", "execution_count": 1, - "id": "f23c8747", + "id": "fdc59326", "metadata": {}, "outputs": [], "source": [ @@ -87,7 +87,7 @@ }, { "cell_type": "markdown", - "id": "49d24dba", + "id": "c3f002d1", "metadata": {}, "source": [ "`JAX` (and `Jaxley`) also allow to choose between `float32` and `float64`. Especially on GPUs, `float32` will be faster, but we have experienced stability issues when simulating morphologically detailed neurons with `float32`." @@ -96,7 +96,7 @@ { "cell_type": "code", "execution_count": 2, - "id": "6082571d", + "id": "cbe3e524", "metadata": {}, "outputs": [], "source": [ @@ -105,7 +105,7 @@ }, { "cell_type": "markdown", - "id": "ee8102e8", + "id": "5c83979f", "metadata": {}, "source": [ "Next, we will import relevant libraries:" @@ -114,7 +114,7 @@ { "cell_type": "code", "execution_count": 3, - "id": "6cf78785", + "id": "59158dfc", "metadata": {}, "outputs": [], "source": [ @@ -129,7 +129,7 @@ }, { "cell_type": "markdown", - "id": "03812c92", + "id": "2fd8cb92", "metadata": {}, "source": [ "### Building the cell or network\n", @@ -140,7 +140,7 @@ { "cell_type": "code", "execution_count": 4, - "id": "581ccd8d", + "id": "de2386de", "metadata": {}, "outputs": [ { @@ -174,7 +174,7 @@ }, { "cell_type": "markdown", - "id": "540877f4", + "id": "78d9c56f", "metadata": {}, "source": [ "### Parameter sweeps\n", @@ -185,7 +185,7 @@ { "cell_type": "code", "execution_count": 5, - "id": "c916acb9", + "id": "cea2152e", "metadata": {}, "outputs": [], "source": [ @@ -198,7 +198,7 @@ }, { "cell_type": "markdown", - "id": "3b5d7365", + "id": "ffe1b7f8", "metadata": {}, "source": [ "The `.data_set()` method takes three arguments: \n", @@ -210,7 +210,7 @@ }, { "cell_type": "markdown", - "id": "47ac2b5e", + "id": "7fbe2b72", "metadata": {}, "source": [ "Having done this, the simplest (but least efficient) way to perform the parameter sweep is to run a for-loop over many parameter sets:" @@ -219,7 +219,7 @@ { "cell_type": "code", "execution_count": 6, - "id": "3884b17d", + "id": "103bad5d", "metadata": {}, "outputs": [ { @@ -240,7 +240,7 @@ }, { "cell_type": "markdown", - "id": "258e2d34", + "id": "fa20a108", "metadata": {}, "source": [ "The resulting voltages have shape `(num_simulations, num_recordings, num_timesteps)`." @@ -248,7 +248,7 @@ }, { "cell_type": "markdown", - "id": "d6fd93ba", + "id": "39d19d3e", "metadata": {}, "source": [ "### Stimulus sweeps\n", @@ -266,7 +266,7 @@ }, { "cell_type": "markdown", - "id": "6c82d4f1", + "id": "d308a0dc", "metadata": {}, "source": [ "### Speeding up for loops via `jit` compilation\n", @@ -277,7 +277,7 @@ { "cell_type": "code", "execution_count": 7, - "id": "b293fe5b", + "id": "b17f4ea8", "metadata": {}, "outputs": [], "source": [ @@ -287,7 +287,7 @@ { "cell_type": "code", "execution_count": 8, - "id": "9c3cb96d", + "id": "02030518", "metadata": {}, "outputs": [], "source": [ @@ -298,7 +298,7 @@ { "cell_type": "code", "execution_count": 9, - "id": "c13179b2", + "id": "0aa677d6", "metadata": {}, "outputs": [ { @@ -317,7 +317,7 @@ }, { "cell_type": "markdown", - "id": "7ecf907e", + "id": "0edb4e39", "metadata": {}, "source": [ "`jit` compilation can be up to 10k times faster, especially for small simulations with few compartments. For very large models, the gain obtained with `jit` will be much smaller (`jit` may even provide no speed up at all)." @@ -325,7 +325,7 @@ }, { "cell_type": "markdown", - "id": "65e38925", + "id": "dc67192b", "metadata": {}, "source": [ "### Speeding up with GPU parallelization via `vmap`\n", @@ -336,7 +336,7 @@ { "cell_type": "code", "execution_count": 10, - "id": "364322dd", + "id": "71db56a5", "metadata": {}, "outputs": [], "source": [ @@ -346,7 +346,7 @@ }, { "cell_type": "markdown", - "id": "489a1f8d", + "id": "ae8713ad", "metadata": {}, "source": [ "We can then run this method on __all__ parameter sets (`all_params.shape == (100, 2)`), and `Jaxley` will automatically parallelize across them. Of course, you will only get a speed-up if you have a GPU available and you specified `gpu` as device in the beginning of this tutorial." @@ -355,7 +355,7 @@ { "cell_type": "code", "execution_count": 11, - "id": "a5f2824c", + "id": "22a4d754", "metadata": {}, "outputs": [], "source": [ @@ -364,7 +364,7 @@ }, { "cell_type": "markdown", - "id": "fb975d94", + "id": "6791c491", "metadata": {}, "source": [ "GPU parallelization with `vmap` can give a large speed-up, which can easily be 2-3 orders of magnitude." @@ -372,7 +372,7 @@ }, { "cell_type": "markdown", - "id": "a0cccc7f", + "id": "9ab125e9", "metadata": {}, "source": [ "### Combining `jit` and `vmap`" @@ -380,7 +380,7 @@ }, { "cell_type": "markdown", - "id": "5186402d", + "id": "e103f5ac", "metadata": {}, "source": [ "Finally, you can also combine using `jit` and `vmap`. For example, you can run multiple batches of many parallel simulations. Each batch can be parallelized with `vmap` and simulating each batch can be compiled with `jit`:" @@ -389,7 +389,7 @@ { "cell_type": "code", "execution_count": 12, - "id": "2d6c32ab", + "id": "ab54c5e1", "metadata": {}, "outputs": [], "source": [ @@ -399,7 +399,7 @@ { "cell_type": "code", "execution_count": 13, - "id": "03ade1b5", + "id": "d207bb9d", "metadata": {}, "outputs": [], "source": [ @@ -410,7 +410,7 @@ }, { "cell_type": "markdown", - "id": "4b6ec113", + "id": "8f616a20", "metadata": {}, "source": [ "That's all you have to know about `jit` and `vmap`! If you have worked through this and the previous tutorials, you should be ready to set up your first network simulations." @@ -418,14 +418,16 @@ }, { "cell_type": "markdown", - "id": "2b5e93d1", + "id": "0684416c", "metadata": {}, "source": [ "### Next steps\n", "\n", "If you want to learn more, we recommend you to read the [tutorial on building channel and synapse models](https://jaxley.readthedocs.io/en/latest/tutorials/05_channel_and_synapse_models.html).\n", "\n", - "Alternatively, you can also directly jump ahead to the [tutorial on training biophysical networks](https://jaxley.readthedocs.io/en/latest/tutorials/07_gradient_descent.html) which will teach you how you can optimize parameters of biophysical models with gradient descent." + "Alternatively, you can also directly jump ahead to the [tutorial on training biophysical networks](https://jaxley.readthedocs.io/en/latest/tutorials/07_gradient_descent.html) which will teach you how you can optimize parameters of biophysical models with gradient descent.\n", + "\n", + "Finally, if you want to learn more about JAX, check out their [tutorial on jit](https://jax.readthedocs.io/en/latest/jit-compilation.html) or their [tutorial on vmap](https://jax.readthedocs.io/en/latest/automatic-vectorization.html)." ] } ], diff --git a/docs/tutorials/06_groups.ipynb b/docs/tutorials/06_groups.ipynb index 823eb640..cc6ff71f 100644 --- a/docs/tutorials/06_groups.ipynb +++ b/docs/tutorials/06_groups.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "markdown", - "id": "95c6ecde", + "id": "d2391d78", "metadata": {}, "source": [ "# Defining groups\n", @@ -41,7 +41,7 @@ { "cell_type": "code", "execution_count": 40, - "id": "a87e484b", + "id": "512857ee", "metadata": {}, "outputs": [], "source": [ @@ -64,16 +64,16 @@ }, { "cell_type": "markdown", - "id": "a932be87", + "id": "f947b991", "metadata": {}, "source": [ - "First, we define a network as you saw in the [previous tutorial](https://jaxley.readthedocs.io/en/latest/tutorials/01_morph_neurons.html):" + "First, we define a network as you saw in the [previous tutorial](https://jaxley.readthedocs.io/en/latest/tutorials/02_small_network.html):" ] }, { "cell_type": "code", "execution_count": 41, - "id": "45cb0bec", + "id": "d1af07da", "metadata": {}, "outputs": [ { @@ -102,7 +102,7 @@ }, { "cell_type": "markdown", - "id": "c543ead9", + "id": "28fa2342", "metadata": {}, "source": [ "### Group: apical dendrites\n", @@ -112,7 +112,7 @@ { "cell_type": "code", "execution_count": 42, - "id": "a5cd53c9", + "id": "09ac3d79", "metadata": {}, "outputs": [], "source": [ @@ -123,7 +123,7 @@ }, { "cell_type": "markdown", - "id": "1eb717f9", + "id": "e13e0f5f", "metadata": {}, "source": [ "After this, we can access `network.apical` as we previously accesses anything else:" @@ -132,7 +132,7 @@ { "cell_type": "code", "execution_count": 43, - "id": "bfb1ed58", + "id": "61cd784b", "metadata": {}, "outputs": [], "source": [ @@ -142,7 +142,7 @@ { "cell_type": "code", "execution_count": 44, - "id": "86207c99", + "id": "9b114506", "metadata": {}, "outputs": [ { @@ -554,7 +554,7 @@ }, { "cell_type": "markdown", - "id": "8ca3f041", + "id": "a22bfbc6", "metadata": {}, "source": [ "### Group: fast spiking\n", @@ -564,7 +564,7 @@ { "cell_type": "code", "execution_count": 45, - "id": "9f957bc0", + "id": "a1d820d0", "metadata": {}, "outputs": [], "source": [ @@ -575,7 +575,7 @@ { "cell_type": "code", "execution_count": 46, - "id": "cba556c9", + "id": "88800571", "metadata": {}, "outputs": [], "source": [ @@ -585,7 +585,7 @@ { "cell_type": "code", "execution_count": 47, - "id": "67f3fc20", + "id": "654e33ff", "metadata": {}, "outputs": [ { @@ -1109,7 +1109,7 @@ }, { "cell_type": "markdown", - "id": "21b5d94c", + "id": "4721b618", "metadata": {}, "source": [ "### Groups from SWC files" @@ -1117,7 +1117,7 @@ }, { "cell_type": "markdown", - "id": "e28b0471", + "id": "7a0fa060", "metadata": {}, "source": [ "If you are reading `.swc` morphologigies, you can automatically assign groups with \n", @@ -1129,7 +1129,7 @@ }, { "cell_type": "markdown", - "id": "82663192", + "id": "025e96e1", "metadata": {}, "source": [ "### How groups are interpreted by `.make_trainable()`\n", @@ -1139,7 +1139,7 @@ { "cell_type": "code", "execution_count": 48, - "id": "4cef0eec", + "id": "305e64fb", "metadata": {}, "outputs": [ { @@ -1156,7 +1156,7 @@ }, { "cell_type": "markdown", - "id": "85c887ef", + "id": "8881edc1", "metadata": {}, "source": [ "As such, `get_parameters()` returns only a single trainable parameter, which will be the sodium conductance for every compartment of every fast-spiking neuron:" @@ -1165,7 +1165,7 @@ { "cell_type": "code", "execution_count": 49, - "id": "10b93b04", + "id": "db131033", "metadata": {}, "outputs": [ { @@ -1185,7 +1185,7 @@ }, { "cell_type": "markdown", - "id": "0b4cb4de", + "id": "1bdcc8d1", "metadata": {}, "source": [ "If, instead, you would want a separate parameter for every fast-spiking cell, you should not use the group, but instead do the following (remember that fast-spiking neurons had indices [0,1]):" @@ -1194,7 +1194,7 @@ { "cell_type": "code", "execution_count": 50, - "id": "fb867251", + "id": "a023cced", "metadata": {}, "outputs": [ { @@ -1212,7 +1212,7 @@ { "cell_type": "code", "execution_count": 51, - "id": "3593b3ed", + "id": "e45969d2", "metadata": {}, "outputs": [ { @@ -1233,7 +1233,7 @@ }, { "cell_type": "markdown", - "id": "2aa7bacd", + "id": "49dc611c", "metadata": {}, "source": [ "This generated two parameters for the axial resistivitiy, each corresponding to one cell." @@ -1241,7 +1241,7 @@ }, { "cell_type": "markdown", - "id": "72cdc4ac", + "id": "38f08471", "metadata": {}, "source": [ "### Summary" @@ -1249,19 +1249,11 @@ }, { "cell_type": "markdown", - "id": "a1f23438", + "id": "9ddfb1d9", "metadata": {}, "source": [ "Groups allow you to organize your simulation in a more intuitive way, and they allow to perform parameter sharing with `make_trainable()`." ] - }, - { - "cell_type": "markdown", - "id": "a80b31fe", - "metadata": {}, - "source": [ - "If you have not done so already, we recommend you to check out the tutorial on [how to compute the gradient and train biophysical models](https://jaxley.readthedocs.io/en/latest/tutorials/07_gradient_descent.html)." - ] } ], "metadata": { diff --git a/docs/tutorials/09_advanced_indexing.ipynb b/docs/tutorials/09_advanced_indexing.ipynb index 60481da4..1314137b 100644 --- a/docs/tutorials/09_advanced_indexing.ipynb +++ b/docs/tutorials/09_advanced_indexing.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "markdown", - "id": "cccba774", + "id": "273681a2", "metadata": {}, "source": [ "# Customizing synaptic parameters" @@ -10,7 +10,7 @@ }, { "cell_type": "markdown", - "id": "5e77930a", + "id": "8fc65919", "metadata": {}, "source": [ "In this tutorial, you will learn how to:\n", @@ -43,10 +43,10 @@ }, { "cell_type": "markdown", - "id": "c67e4a61", + "id": "3fbb3088", "metadata": {}, "source": [ - "In a [previous tutorial](https://jaxley.readthedocs.io/en/latest/tutorials/03_setting_parameters.html) you learned how to set parameters of a `jx.Cell` or `jx.Network`. In that tutorial, we briefly mentioned the `select()` method which allowed to set individual synapses to particular values. In this tutorial, we will go into detail in how you can fully customize your `Jaxley` simulation.\n", + "In a [previous tutorial](https://jaxley.readthedocs.io/en/latest/tutorials/02_small_network.html) you learned how to set parameters of a `jx.Network`. In that tutorial, we briefly mentioned the `select()` method which allowed to set individual synapses to particular values. In this tutorial, we will go into detail in how you can fully customize your `Jaxley` simulation.\n", "\n", "Let's go!" ] @@ -54,7 +54,7 @@ { "cell_type": "code", "execution_count": 1, - "id": "baafd10a", + "id": "30ebd3be", "metadata": { "tags": [] }, @@ -68,7 +68,7 @@ }, { "cell_type": "markdown", - "id": "97f4c174", + "id": "f2c5eeb0", "metadata": {}, "source": [ "### Preface: Building the network\n", @@ -79,7 +79,7 @@ { "cell_type": "code", "execution_count": 2, - "id": "9240cb5a", + "id": "615db52b", "metadata": { "tags": [] }, @@ -97,7 +97,7 @@ }, { "cell_type": "markdown", - "id": "5fefa4ac", + "id": "c9a7159b", "metadata": {}, "source": [ "### Setting individual synapse parameters\n", @@ -108,7 +108,7 @@ { "cell_type": "code", "execution_count": 3, - "id": "d85e300f", + "id": "312ee464", "metadata": { "tags": [] }, @@ -396,7 +396,7 @@ }, { "cell_type": "markdown", - "id": "bacd6c24", + "id": "485dd830", "metadata": {}, "source": [ "This table has nine rows, each corresponding to one synapse. This makes sense because we fully connected three neurons (0, 1, 2) to three other neurons (3, 4, 5), giving a total of `3x3=9` synapses.\n", @@ -407,7 +407,7 @@ { "cell_type": "code", "execution_count": 4, - "id": "9c64cf6a", + "id": "034247a0", "metadata": {}, "outputs": [], "source": [ @@ -416,7 +416,7 @@ }, { "cell_type": "markdown", - "id": "deb6a604", + "id": "c87be6d5", "metadata": {}, "source": [ "Above, we are modifying the synapses with indices `[3, 4, 5]` (i.e., the indices of the `net.edges` DataFrame). The resulting values are indeed changed:" @@ -425,7 +425,7 @@ { "cell_type": "code", "execution_count": 5, - "id": "edb9457a", + "id": "bcfcce14", "metadata": {}, "outputs": [ { @@ -454,7 +454,7 @@ }, { "cell_type": "markdown", - "id": "0a42bd0e", + "id": "86d940c7", "metadata": {}, "source": [ "### Example 1: Setting synaptic parameters which connect particular neurons" @@ -462,7 +462,7 @@ }, { "cell_type": "markdown", - "id": "e6d948f0", + "id": "11cea815", "metadata": {}, "source": [ "This is great, but setting synaptic parameters just by their index can be exhausting, in particular in very large networks. Instead, we would want to, for example, set the maximal conductance of all synapses that connect from cell 0 or 1 to any other neuron.\n", @@ -473,7 +473,7 @@ { "cell_type": "code", "execution_count": 6, - "id": "dbc0a6d6", + "id": "c3292eb9", "metadata": {}, "outputs": [], "source": [ @@ -489,7 +489,7 @@ { "cell_type": "code", "execution_count": 7, - "id": "4020e781", + "id": "ddc9f60d", "metadata": {}, "outputs": [ { @@ -518,7 +518,7 @@ }, { "cell_type": "markdown", - "id": "173bab00", + "id": "6370f460", "metadata": {}, "source": [ "Indeed, the first six synapses now have the value `0.23`! Let's look at the individual lines to understand how this worked:" @@ -526,7 +526,7 @@ }, { "cell_type": "markdown", - "id": "9ad29af6", + "id": "c3159220", "metadata": {}, "source": [ "We want to set parameter by cell index. However, by default, the pre- or post-synaptic cell-indices are not listed in `net.edges`. We can add the cell index to the `.edges` dataframe by calling `.copy_node_property_to_edges()`:\n", @@ -537,7 +537,7 @@ }, { "cell_type": "markdown", - "id": "1a557a93", + "id": "2c19dea8", "metadata": {}, "source": [ "After this, the pre- and post-synaptic cell indices are listed in `net.edges` as `pre_global_cell_index` and `post_global_cell_index`." @@ -545,7 +545,7 @@ }, { "cell_type": "markdown", - "id": "ee89312f", + "id": "1a5ebcc5", "metadata": {}, "source": [ "Next, we take `.edges`, which is a [pandas DataFrame](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.html):\n", @@ -556,7 +556,7 @@ }, { "cell_type": "markdown", - "id": "01e7920c", + "id": "5524765c", "metadata": {}, "source": [ "We then modify this DataFrame to only contain those rows where the global cell index is in 0 or 1:\n", @@ -567,7 +567,7 @@ }, { "cell_type": "markdown", - "id": "1d5e0c96", + "id": "9ed887d8", "metadata": {}, "source": [ "For the above step, you use any column of the DataFrame to filter it (you can see all columns with `df.columns`). Note that, while we used `.query()` here, you can really filter the pandas DataFrame however you want. For example, the `query` above is identical to `df = df[df[\"global_pre_cell_index\"].isin([0, 1])]`.\n", @@ -580,7 +580,7 @@ }, { "cell_type": "markdown", - "id": "87cce3f1", + "id": "58e30f27", "metadata": {}, "source": [ "### Example 2: Setting parameters given pre- and post-synaptic cell indices" @@ -588,7 +588,7 @@ }, { "cell_type": "markdown", - "id": "c8c0c04f", + "id": "6970798d", "metadata": {}, "source": [ "Say you want to select all synapses that have cells 1 or 2 as presynaptic neuron and cell 4 or 5 as postsynaptic neuron." @@ -597,7 +597,7 @@ { "cell_type": "code", "execution_count": 8, - "id": "ea0b241a", + "id": "377807ba", "metadata": {}, "outputs": [], "source": [ @@ -607,7 +607,7 @@ }, { "cell_type": "markdown", - "id": "5456ab17", + "id": "5933a3b9", "metadata": {}, "source": [ "Just like before, we can simply use `.query()` as already shown above. However, this time, call `.query()` to twice to filter by pre- and post-synaptic cell indices:" @@ -616,7 +616,7 @@ { "cell_type": "code", "execution_count": 9, - "id": "fe3d95fe", + "id": "c03923d9", "metadata": {}, "outputs": [], "source": [ @@ -631,7 +631,7 @@ { "cell_type": "code", "execution_count": 10, - "id": "4fa434b9", + "id": "76000c26", "metadata": {}, "outputs": [ { @@ -660,7 +660,7 @@ }, { "cell_type": "markdown", - "id": "11778d87", + "id": "a047a9ae", "metadata": {}, "source": [ "### Example 3: Applying this strategy to cell level parameters" @@ -668,7 +668,7 @@ }, { "cell_type": "markdown", - "id": "95357091", + "id": "7ec67cf1", "metadata": {}, "source": [ "You had previously seen that you can modify parameters with, e.g., `net.cell(0).set(...)`. However, if you need more flexibility than this, you can also use the above strategy to modify cell-level parameters:" @@ -677,7 +677,7 @@ { "cell_type": "code", "execution_count": 11, - "id": "f2f6ba44", + "id": "ed9101e0", "metadata": {}, "outputs": [], "source": [ @@ -691,7 +691,7 @@ }, { "cell_type": "markdown", - "id": "26dc46f1", + "id": "8c9fbf3e", "metadata": {}, "source": [ "### Example 4: Flexibly setting parameters based on their `groups`" @@ -699,7 +699,7 @@ }, { "cell_type": "markdown", - "id": "88bbff27", + "id": "a89376bb", "metadata": {}, "source": [ "If you are using groups, as shown in [this tutorial](https://jaxley.readthedocs.io/en/latest/tutorials/06_groups.html), then you can also use this for querying synapses. To demonstrate this, let's create a group of excitatory neurons (e.g., cells 0, 3, 5):" @@ -708,7 +708,7 @@ { "cell_type": "code", "execution_count": 12, - "id": "f34d907f", + "id": "33e5bb5d", "metadata": {}, "outputs": [], "source": [ @@ -721,7 +721,7 @@ }, { "cell_type": "markdown", - "id": "9ae53276", + "id": "2a362d8f", "metadata": {}, "source": [ "Now, say we want all synapses that start from these excitatory neurons. You can do this as follows:" @@ -730,7 +730,7 @@ { "cell_type": "code", "execution_count": 13, - "id": "ce76a0c1", + "id": "8ea9e21a", "metadata": {}, "outputs": [], "source": [ @@ -746,7 +746,7 @@ }, { "cell_type": "markdown", - "id": "6450fa6d", + "id": "d3c0c2a3", "metadata": {}, "source": [ "### Example 5: Setting synaptic parameters based on properties of the presynaptic cell" @@ -754,7 +754,7 @@ }, { "cell_type": "markdown", - "id": "72d76ba3", + "id": "c4b1d18c", "metadata": {}, "source": [ "Let's discuss one more example: Imagine we only want to modify those synapses whose presynaptic compartment has a sodium channel. Let's first add a sodium channel to some of the cells:" @@ -763,7 +763,7 @@ { "cell_type": "code", "execution_count": 14, - "id": "a9560bf6", + "id": "8bd15f6a", "metadata": {}, "outputs": [], "source": [ @@ -776,7 +776,7 @@ }, { "cell_type": "markdown", - "id": "34550f32", + "id": "42c4a577", "metadata": {}, "source": [ "Now, let us query which cells have the desired synapses:" @@ -785,7 +785,7 @@ { "cell_type": "code", "execution_count": 15, - "id": "374f377e", + "id": "1352bf55", "metadata": {}, "outputs": [], "source": [ @@ -796,7 +796,7 @@ }, { "cell_type": "markdown", - "id": "08e7c2d0", + "id": "a359edcd", "metadata": {}, "source": [ "`indices_of_sodium_compartments` lists all compartments which contained sodium:" @@ -805,7 +805,7 @@ { "cell_type": "code", "execution_count": 16, - "id": "b231ba68", + "id": "7d04f731", "metadata": {}, "outputs": [ { @@ -822,7 +822,7 @@ }, { "cell_type": "markdown", - "id": "16597e8d", + "id": "3ba3092b", "metadata": {}, "source": [ "Then, we can proceed as always and filter for the global pre-synaptic **compartment** index:" @@ -831,7 +831,7 @@ { "cell_type": "code", "execution_count": 17, - "id": "07a665f9", + "id": "9a818fc3", "metadata": {}, "outputs": [], "source": [ @@ -843,7 +843,7 @@ { "cell_type": "code", "execution_count": 18, - "id": "64ed3c08", + "id": "04f2f9ae", "metadata": {}, "outputs": [ { @@ -872,7 +872,7 @@ }, { "cell_type": "markdown", - "id": "91d7819c", + "id": "492c6f3b", "metadata": {}, "source": [ "Indeed, only synapses coming from the first neuron were modified (as its presynaptic compartment contained sodium), in contrast to synapses from neuron 2 (whose presynaptic compartment did not)." @@ -880,7 +880,7 @@ }, { "cell_type": "markdown", - "id": "0371f357", + "id": "f3fe95d2", "metadata": {}, "source": [ "### Summary\n",